summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apct-tests/perftests/core/OWNERS8
-rw-r--r--apct-tests/perftests/core/src/android/input/MotionPredictorBenchmark.kt4
-rw-r--r--apct-tests/perftests/settingsprovider/src/android/provider/SettingsProviderPerfTest.java9
-rw-r--r--apex/jobscheduler/framework/java/android/app/job/JobInfo.java87
-rw-r--r--apex/jobscheduler/framework/java/android/app/job/JobParameters.java2
-rw-r--r--apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java90
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobNotificationCoordinator.java11
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java55
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java1
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java15
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java4
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java5
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java14
-rw-r--r--apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING13
-rw-r--r--core/api/current.txt190
-rw-r--r--core/api/system-current.txt277
-rw-r--r--core/api/test-current.txt30
-rw-r--r--core/java/android/accessibilityservice/AccessibilityService.java54
-rw-r--r--core/java/android/app/ActivityClient.java17
-rw-r--r--core/java/android/app/ActivityManager.java20
-rw-r--r--core/java/android/app/ActivityManagerInternal.java8
-rw-r--r--core/java/android/app/ActivityThread.java47
-rw-r--r--core/java/android/app/AppOpsManager.java278
-rw-r--r--core/java/android/app/ApplicationExitInfo.java9
-rw-r--r--core/java/android/app/BroadcastOptions.java55
-rw-r--r--core/java/android/app/ClientTransactionHandler.java2
-rw-r--r--core/java/android/app/ContextImpl.java10
-rw-r--r--core/java/android/app/IActivityClientController.aidl10
-rw-r--r--core/java/android/app/IActivityManager.aidl6
-rw-r--r--core/java/android/app/IActivityTaskManager.aidl7
-rw-r--r--core/java/android/app/IApplicationThread.aidl1
-rw-r--r--core/java/android/app/LocaleConfig.java46
-rw-r--r--core/java/android/app/LocaleManager.java5
-rw-r--r--core/java/android/app/Notification.java82
-rw-r--r--core/java/android/app/NotificationManager.java2
-rw-r--r--core/java/android/app/StartForegroundCalledOnStoppedServiceException.java62
-rw-r--r--core/java/android/app/SystemServiceRegistry.java7
-rw-r--r--core/java/android/app/TaskInfo.java2
-rw-r--r--core/java/android/app/backup/BackupManager.java1
-rw-r--r--core/java/android/app/backup/BackupTransport.java5
-rw-r--r--core/java/android/app/servertransaction/LaunchActivityItem.java4
-rw-r--r--core/java/android/app/servertransaction/TransactionExecutor.java3
-rw-r--r--core/java/android/app/timedetector/TimeDetector.java14
-rw-r--r--core/java/android/companion/CompanionDeviceManager.java147
-rw-r--r--core/java/android/companion/ICompanionDeviceManager.aidl12
-rw-r--r--core/java/android/companion/IOnMessageReceivedListener.aidl23
-rw-r--r--core/java/android/companion/IOnTransportsChangedListener.aidl25
-rw-r--r--core/java/android/companion/virtual/VirtualDevice.java5
-rw-r--r--core/java/android/companion/virtual/VirtualDeviceManager.java78
-rw-r--r--core/java/android/companion/virtual/VirtualDeviceParams.java78
-rw-r--r--core/java/android/companion/virtual/sensor/IVirtualSensorCallback.aidl28
-rw-r--r--core/java/android/companion/virtual/sensor/VirtualSensorCallback.java75
-rw-r--r--core/java/android/companion/virtual/sensor/VirtualSensorConfig.java114
-rw-r--r--core/java/android/content/AttributionSource.java5
-rw-r--r--core/java/android/content/ClipboardManager.java33
-rw-r--r--core/java/android/content/ContentCaptureOptions.java40
-rw-r--r--core/java/android/content/ContentProvider.java4
-rw-r--r--core/java/android/content/Context.java20
-rw-r--r--core/java/android/content/IClipboard.aidl4
-rw-r--r--core/java/android/content/Intent.java5
-rw-r--r--core/java/android/content/pm/PackageInstaller.java233
-rw-r--r--core/java/android/content/pm/PackageManager.java196
-rw-r--r--core/java/android/content/pm/ServiceInfo.java46
-rw-r--r--core/java/android/content/pm/TEST_MAPPING56
-rw-r--r--core/java/android/content/pm/UserPackage.java64
-rw-r--r--core/java/android/content/res/FontScaleConverterFactory.java70
-rw-r--r--core/java/android/content/res/OWNERS2
-rw-r--r--core/java/android/credentials/CreateCredentialRequest.java129
-rw-r--r--core/java/android/credentials/CredentialDescription.java14
-rw-r--r--core/java/android/credentials/CredentialManager.java135
-rw-r--r--core/java/android/credentials/GetCredentialRequest.java45
-rw-r--r--core/java/android/credentials/ICredentialManager.aidl4
-rw-r--r--core/java/android/credentials/ui/CancelUiRequest.java79
-rw-r--r--core/java/android/credentials/ui/IntentFactory.java22
-rw-r--r--core/java/android/hardware/SystemSensorManager.java15
-rw-r--r--core/java/android/hardware/biometrics/AuthenticateOptions.java77
-rw-r--r--core/java/android/hardware/camera2/CameraCharacteristics.java4
-rw-r--r--core/java/android/hardware/camera2/CameraExtensionCharacteristics.java9
-rw-r--r--core/java/android/hardware/camera2/CameraManager.java27
-rw-r--r--core/java/android/hardware/camera2/CameraMetadata.java35
-rw-r--r--core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java6
-rw-r--r--core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java13
-rw-r--r--core/java/android/hardware/camera2/impl/CameraExtensionUtils.java2
-rw-r--r--core/java/android/hardware/display/DisplayManager.java89
-rw-r--r--core/java/android/hardware/display/VirtualDisplayConfig.java645
-rw-r--r--core/java/android/hardware/face/FaceAuthenticateOptions.aidl19
-rw-r--r--core/java/android/hardware/face/FaceAuthenticateOptions.java633
-rw-r--r--core/java/android/hardware/face/FaceManager.java39
-rw-r--r--core/java/android/hardware/face/IFaceService.aidl13
-rw-r--r--core/java/android/hardware/fingerprint/FingerprintAuthenticateOptions.aidl19
-rw-r--r--core/java/android/hardware/fingerprint/FingerprintAuthenticateOptions.java456
-rw-r--r--core/java/android/hardware/fingerprint/FingerprintManager.java40
-rw-r--r--core/java/android/hardware/fingerprint/IFingerprintService.aidl14
-rw-r--r--core/java/android/hardware/input/InputManager.java21
-rw-r--r--core/java/android/hardware/input/InputManagerGlobal.java82
-rw-r--r--core/java/android/hardware/input/VirtualTouchEvent.java15
-rw-r--r--core/java/android/net/NetworkPolicyManager.java28
-rw-r--r--core/java/android/nfc/NfcAdapter.java25
-rw-r--r--core/java/android/nfc/cardemulation/ApduServiceInfo.java2
-rw-r--r--core/java/android/nfc/cardemulation/NfcFServiceInfo.java2
-rw-r--r--core/java/android/nfc/cardemulation/Utils.java37
-rw-r--r--core/java/android/os/BatteryManager.java112
-rw-r--r--core/java/android/os/CancellationSignalBeamer.java325
-rw-r--r--core/java/android/os/IUserManager.aidl1
-rw-r--r--core/java/android/os/UserManager.java26
-rw-r--r--core/java/android/provider/Settings.java324
-rw-r--r--core/java/android/provider/Telephony.java62
-rw-r--r--core/java/android/service/autofill/FillEventHistory.java25
-rw-r--r--core/java/android/service/credentials/BeginCreateCredentialResponse.java12
-rw-r--r--core/java/android/service/credentials/BeginGetCredentialOption.java4
-rw-r--r--core/java/android/service/credentials/BeginGetCredentialResponse.java12
-rw-r--r--core/java/android/service/credentials/CallingAppInfo.java38
-rw-r--r--core/java/android/service/credentials/GetCredentialRequest.java49
-rw-r--r--core/java/android/service/credentials/RemoteEntry.java97
-rw-r--r--core/java/android/service/dreams/DreamActivity.java2
-rw-r--r--core/java/android/service/dreams/DreamService.java3
-rw-r--r--core/java/android/service/notification/ZenModeConfig.java2
-rw-r--r--core/java/android/service/voice/AbstractDetector.java7
-rw-r--r--core/java/android/service/voice/AlwaysOnHotwordDetector.java7
-rw-r--r--core/java/android/service/voice/HotwordDetectionService.java16
-rw-r--r--core/java/android/service/voice/HotwordDetector.java6
-rw-r--r--core/java/android/service/voice/IVoiceInteractionService.aidl1
-rw-r--r--core/java/android/service/voice/SandboxedDetectionInitializer.java (renamed from core/java/android/service/voice/SandboxedDetectionServiceBase.java)6
-rw-r--r--core/java/android/service/voice/SoftwareHotwordDetector.java7
-rw-r--r--core/java/android/service/voice/VisualQueryDetectionService.java243
-rw-r--r--core/java/android/service/voice/VisualQueryDetector.java15
-rw-r--r--core/java/android/service/voice/VoiceInteractionService.java32
-rw-r--r--core/java/android/service/wallpaper/WallpaperService.java62
-rw-r--r--core/java/android/speech/RecognitionPart.java20
-rw-r--r--core/java/android/telephony/CellBroadcastIntents.java20
-rw-r--r--core/java/android/telephony/TelephonyRegistryManager.java13
-rw-r--r--core/java/android/text/GraphemeClusterSegmentFinder.java71
-rw-r--r--core/java/android/util/FeatureFlagUtils.java6
-rw-r--r--core/java/android/util/NtpTrustedTime.java9
-rw-r--r--core/java/android/util/SparseArrayMap.java8
-rw-r--r--core/java/android/view/AccessibilityInteractionController.java2
-rw-r--r--core/java/android/view/Choreographer.java175
-rw-r--r--core/java/android/view/Display.java9
-rw-r--r--core/java/android/view/DisplayEventReceiver.java11
-rw-r--r--core/java/android/view/DisplayInfo.java17
-rw-r--r--core/java/android/view/HandwritingDelegateConfiguration.java74
-rw-r--r--core/java/android/view/HandwritingInitiator.java58
-rw-r--r--core/java/android/view/InsetsSource.java5
-rw-r--r--core/java/android/view/InsetsState.java2
-rw-r--r--core/java/android/view/KeyEvent.java23
-rw-r--r--core/java/android/view/MotionPredictor.java36
-rw-r--r--core/java/android/view/OWNERS1
-rw-r--r--core/java/android/view/TaskTransitionSpec.java30
-rw-r--r--core/java/android/view/View.java236
-rw-r--r--core/java/android/view/ViewGroup.java6
-rw-r--r--core/java/android/view/ViewRootImpl.java23
-rw-r--r--core/java/android/view/WindowManager.java18
-rw-r--r--core/java/android/view/accessibility/AccessibilityEvent.java18
-rw-r--r--core/java/android/view/accessibility/AccessibilityManager.java12
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeInfo.java30
-rw-r--r--core/java/android/view/accessibility/AccessibilityRecord.java24
-rw-r--r--core/java/android/view/accessibility/AccessibilityWindowInfo.java1
-rw-r--r--core/java/android/view/accessibility/DirectAccessibilityConnection.java22
-rw-r--r--core/java/android/view/autofill/AutofillManager.java3
-rw-r--r--core/java/android/view/autofill/OWNERS8
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureContext.java13
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureManager.java44
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureSession.java16
-rw-r--r--core/java/android/view/contentcapture/MainContentCaptureSession.java12
-rw-r--r--core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java79
-rw-r--r--core/java/android/view/inputmethod/ImeTracker.java102
-rw-r--r--core/java/android/view/inputmethod/InputMethodInfo.java24
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java171
-rw-r--r--core/java/android/view/textclassifier/TextLinks.java2
-rw-r--r--core/java/android/widget/Editor.java39
-rw-r--r--core/java/android/widget/RemoteViews.java4
-rw-r--r--core/java/android/widget/TextView.java8
-rw-r--r--core/java/android/window/ITaskOrganizer.aidl3
-rw-r--r--core/java/android/window/SnapshotDrawerUtils.java24
-rw-r--r--core/java/android/window/StartingWindowInfo.java50
-rw-r--r--core/java/android/window/StartingWindowRemovalInfo.java18
-rw-r--r--core/java/android/window/TaskFragmentInfo.java26
-rw-r--r--core/java/android/window/TaskOrganizer.java10
-rw-r--r--core/java/android/window/WindowOnBackInvokedDispatcher.java5
-rw-r--r--core/java/com/android/internal/accessibility/AccessibilityShortcutController.java5
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java35
-rw-r--r--core/java/com/android/internal/config/sysui/SystemUiSystemPropertiesFlags.java2
-rw-r--r--core/java/com/android/internal/inputmethod/IImeTracker.aidl (renamed from core/java/com/android/internal/view/IImeTracker.aidl)30
-rw-r--r--core/java/com/android/internal/jank/EventLogTags.logtags6
-rw-r--r--core/java/com/android/internal/jank/InteractionJankMonitor.java42
-rw-r--r--core/java/com/android/internal/midi/EventScheduler.java53
-rw-r--r--core/java/com/android/internal/midi/MidiEventMultiScheduler.java128
-rw-r--r--core/java/com/android/internal/midi/MidiEventScheduler.java2
-rw-r--r--core/java/com/android/internal/os/BatteryStatsHistory.java5
-rw-r--r--core/java/com/android/internal/os/ProcessCpuTracker.java34
-rw-r--r--core/java/com/android/internal/os/RuntimeInit.java26
-rw-r--r--core/java/com/android/internal/protolog/BaseProtoLogImpl.java1
-rw-r--r--core/java/com/android/internal/statusbar/IStatusBar.aidl1
-rw-r--r--core/java/com/android/internal/view/IInputMethodManager.aidl11
-rw-r--r--core/java/com/android/internal/widget/LockPatternUtils.java38
-rw-r--r--core/jni/android_hardware_SensorManager.cpp7
-rw-r--r--core/jni/android_media_MicrophoneInfo.cpp1
-rw-r--r--core/jni/android_view_MotionPredictor.cpp25
-rw-r--r--core/proto/android/nfc/Android.bp43
-rw-r--r--core/proto/android/providers/settings/secure.proto2
-rw-r--r--core/proto/android/service/notification.proto64
-rw-r--r--core/res/AndroidManifest.xml10
-rw-r--r--core/res/res/values-af/strings.xml10
-rw-r--r--core/res/res/values-am/strings.xml10
-rw-r--r--core/res/res/values-ar/strings.xml10
-rw-r--r--core/res/res/values-as/strings.xml10
-rw-r--r--core/res/res/values-az/strings.xml10
-rw-r--r--core/res/res/values-b+sr+Latn/strings.xml10
-rw-r--r--core/res/res/values-be/strings.xml10
-rw-r--r--core/res/res/values-bg/strings.xml10
-rw-r--r--core/res/res/values-bn/strings.xml10
-rw-r--r--core/res/res/values-bs/strings.xml10
-rw-r--r--core/res/res/values-ca/strings.xml10
-rw-r--r--core/res/res/values-cs/strings.xml10
-rw-r--r--core/res/res/values-da/strings.xml10
-rw-r--r--core/res/res/values-de/strings.xml12
-rw-r--r--core/res/res/values-el/strings.xml10
-rw-r--r--core/res/res/values-en-rAU/strings.xml4
-rw-r--r--core/res/res/values-en-rCA/strings.xml4
-rw-r--r--core/res/res/values-en-rGB/strings.xml4
-rw-r--r--core/res/res/values-en-rIN/strings.xml4
-rw-r--r--core/res/res/values-en-rXC/strings.xml4
-rw-r--r--core/res/res/values-es-rUS/strings.xml10
-rw-r--r--core/res/res/values-es/strings.xml10
-rw-r--r--core/res/res/values-et/strings.xml10
-rw-r--r--core/res/res/values-eu/strings.xml12
-rw-r--r--core/res/res/values-fa/strings.xml12
-rw-r--r--core/res/res/values-fi/strings.xml10
-rw-r--r--core/res/res/values-fr-rCA/strings.xml10
-rw-r--r--core/res/res/values-fr/strings.xml10
-rw-r--r--core/res/res/values-gl/strings.xml10
-rw-r--r--core/res/res/values-gu/strings.xml10
-rw-r--r--core/res/res/values-hi/strings.xml10
-rw-r--r--core/res/res/values-hr/strings.xml10
-rw-r--r--core/res/res/values-hu/strings.xml10
-rw-r--r--core/res/res/values-hy/strings.xml12
-rw-r--r--core/res/res/values-in/strings.xml10
-rw-r--r--core/res/res/values-is/strings.xml10
-rw-r--r--core/res/res/values-it/strings.xml12
-rw-r--r--core/res/res/values-iw/strings.xml10
-rw-r--r--core/res/res/values-ja/strings.xml10
-rw-r--r--core/res/res/values-ka/strings.xml10
-rw-r--r--core/res/res/values-kk/strings.xml10
-rw-r--r--core/res/res/values-km/strings.xml10
-rw-r--r--core/res/res/values-kn/strings.xml10
-rw-r--r--core/res/res/values-ko/strings.xml10
-rw-r--r--core/res/res/values-ky/strings.xml10
-rw-r--r--core/res/res/values-lo/strings.xml10
-rw-r--r--core/res/res/values-lt/strings.xml10
-rw-r--r--core/res/res/values-lv/strings.xml10
-rw-r--r--core/res/res/values-mk/strings.xml10
-rw-r--r--core/res/res/values-ml/strings.xml10
-rw-r--r--core/res/res/values-mn/strings.xml10
-rw-r--r--core/res/res/values-mr/strings.xml10
-rw-r--r--core/res/res/values-ms/strings.xml10
-rw-r--r--core/res/res/values-my/strings.xml10
-rw-r--r--core/res/res/values-nb/strings.xml10
-rw-r--r--core/res/res/values-ne/strings.xml10
-rw-r--r--core/res/res/values-nl/strings.xml10
-rw-r--r--core/res/res/values-or/strings.xml10
-rw-r--r--core/res/res/values-pa/strings.xml10
-rw-r--r--core/res/res/values-pl/strings.xml10
-rw-r--r--core/res/res/values-pt-rBR/strings.xml10
-rw-r--r--core/res/res/values-pt-rPT/strings.xml16
-rw-r--r--core/res/res/values-pt/strings.xml10
-rw-r--r--core/res/res/values-ro/strings.xml10
-rw-r--r--core/res/res/values-ru/strings.xml14
-rw-r--r--core/res/res/values-si/strings.xml10
-rw-r--r--core/res/res/values-sk/strings.xml10
-rw-r--r--core/res/res/values-sl/strings.xml10
-rw-r--r--core/res/res/values-sq/strings.xml10
-rw-r--r--core/res/res/values-sr/strings.xml10
-rw-r--r--core/res/res/values-sv/strings.xml10
-rw-r--r--core/res/res/values-sw/strings.xml10
-rw-r--r--core/res/res/values-ta/strings.xml10
-rw-r--r--core/res/res/values-te/strings.xml10
-rw-r--r--core/res/res/values-th/strings.xml10
-rw-r--r--core/res/res/values-tl/strings.xml10
-rw-r--r--core/res/res/values-tr/strings.xml10
-rw-r--r--core/res/res/values-uk/strings.xml10
-rw-r--r--core/res/res/values-ur/strings.xml10
-rw-r--r--core/res/res/values-uz/strings.xml10
-rw-r--r--core/res/res/values-vi/strings.xml10
-rw-r--r--core/res/res/values-zh-rCN/strings.xml10
-rw-r--r--core/res/res/values-zh-rHK/strings.xml10
-rw-r--r--core/res/res/values-zh-rTW/strings.xml10
-rw-r--r--core/res/res/values-zu/strings.xml10
-rw-r--r--core/res/res/values/arrays.xml6
-rw-r--r--core/res/res/values/attrs.xml4
-rw-r--r--core/res/res/values/attrs_manifest.xml2
-rw-r--r--core/res/res/values/config.xml49
-rw-r--r--core/res/res/values/config_telephony.xml6
-rw-r--r--core/res/res/values/public-staging.xml2
-rw-r--r--core/res/res/values/symbols.xml5
-rw-r--r--core/res/res/xml/irq_device_map.xml11
-rw-r--r--core/tests/coretests/src/android/app/activity/ActivityThreadTest.java2
-rw-r--r--core/tests/coretests/src/android/companion/virtual/sensor/VirtualSensorConfigTest.java44
-rw-r--r--core/tests/coretests/src/android/content/ContextTest.java2
-rw-r--r--core/tests/coretests/src/android/content/pm/UserPackageTest.java39
-rw-r--r--core/tests/coretests/src/android/content/res/FontScaleConverterActivityTest.java13
-rw-r--r--core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt103
-rw-r--r--core/tests/coretests/src/android/credentials/CredentialManagerTest.java16
-rw-r--r--core/tests/coretests/src/android/hardware/face/FaceManagerTest.java151
-rw-r--r--core/tests/coretests/src/android/hardware/face/OWNERS1
-rw-r--r--core/tests/coretests/src/android/hardware/fingerprint/FingerprintManagerTest.java152
-rw-r--r--core/tests/coretests/src/android/hardware/fingerprint/OWNERS1
-rw-r--r--core/tests/coretests/src/android/os/CancellationSignalBeamerTest.java224
-rw-r--r--core/tests/coretests/src/android/provider/NameValueCacheTest.java259
-rw-r--r--core/tests/coretests/src/android/view/InsetsControllerTest.java11
-rw-r--r--core/tests/coretests/src/android/view/InsetsSourceTest.java14
-rw-r--r--core/tests/coretests/src/android/view/InsetsStateTest.java12
-rw-r--r--core/tests/coretests/src/android/view/KeyEventTest.java32
-rw-r--r--core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java2
-rw-r--r--core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java17
-rw-r--r--core/tests/coretests/src/android/view/stylus/HandwritingInitiatorTest.java14
-rw-r--r--core/tests/coretests/src/android/widget/TextViewContextMenuTest.java73
-rw-r--r--core/tests/coretests/src/com/android/internal/os/SafeZipPathValidatorCallbackTest.java244
-rw-r--r--core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java5
-rw-r--r--core/tests/mockingcoretests/src/android/view/DisplayTest.java25
-rw-r--r--core/tests/overlaytests/device/Android.bp1
-rw-r--r--core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java9
-rw-r--r--data/etc/privapp-permissions-platform.xml5
-rw-r--r--data/etc/services.core.protolog.json24
-rw-r--r--graphics/java/android/graphics/Bitmap.java2
-rw-r--r--graphics/java/android/graphics/Color.java2
-rw-r--r--graphics/java/android/graphics/Gainmap.java12
-rw-r--r--graphics/java/android/graphics/Mesh.java2
-rw-r--r--graphics/java/android/graphics/text/GraphemeBreak.java59
-rw-r--r--graphics/java/android/graphics/text/LineBreaker.java34
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java30
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java33
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java1
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java2
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java8
-rw-r--r--libs/WindowManager/Shell/res/color-night/taskbar_background.xml (renamed from libs/WindowManager/Shell/res/color/split_divider_background.xml)3
-rw-r--r--libs/WindowManager/Shell/res/color/taskbar_background.xml2
-rw-r--r--libs/WindowManager/Shell/res/drawable/desktop_mode_decor_menu_background.xml2
-rw-r--r--libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background.xml21
-rw-r--r--libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background_ripple.xml31
-rw-r--r--libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background.xml22
-rw-r--r--libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background_ripple.xml32
-rw-r--r--libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background.xml23
-rw-r--r--libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background_ripple.xml34
-rw-r--r--libs/WindowManager/Shell/res/layout/compat_mode_hint.xml6
-rw-r--r--libs/WindowManager/Shell/res/layout/desktop_mode_decor_handle_menu.xml25
-rw-r--r--libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml2
-rw-r--r--libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml12
-rw-r--r--libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml6
-rw-r--r--libs/WindowManager/Shell/res/values-af/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-am/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-ar/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-as/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-az/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-be/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-bg/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-bn/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-bs/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-ca/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-cs/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-da/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-de/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-el/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-en-rAU/strings.xml5
-rw-r--r--libs/WindowManager/Shell/res/values-en-rCA/strings.xml5
-rw-r--r--libs/WindowManager/Shell/res/values-en-rGB/strings.xml5
-rw-r--r--libs/WindowManager/Shell/res/values-en-rIN/strings.xml5
-rw-r--r--libs/WindowManager/Shell/res/values-en-rXC/strings.xml5
-rw-r--r--libs/WindowManager/Shell/res/values-es-rUS/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-es/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-et/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-eu/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-fa/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-fi/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-fr-rCA/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-fr/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-gl/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-gu/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-hi/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-hr/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-hu/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-hy/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-in/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-is/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-it/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-iw/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-ja/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-ka/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-kk/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-km/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-kn/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-ko/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-ky/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-lo/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-lt/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-lv/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-mk/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-ml/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-mn/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-mr/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-ms/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-my/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-nb/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-ne/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-night/colors.xml1
-rw-r--r--libs/WindowManager/Shell/res/values-nl/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-or/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-pa/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-pl/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-pt-rBR/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-pt-rPT/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-pt/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-ro/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-ru/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-si/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-sk/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-sl/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-sq/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-sr/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-sv/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-sw/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-ta/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-te/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-th/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-tl/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-tr/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-uk/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-ur/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-uz/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-vi/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-zh-rCN/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-zh-rHK/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-zh-rTW/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values-zu/strings.xml17
-rw-r--r--libs/WindowManager/Shell/res/values/colors.xml6
-rw-r--r--libs/WindowManager/Shell/res/values/dimen.xml27
-rw-r--r--libs/WindowManager/Shell/res/values/styles.xml37
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/ProtoLogController.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/TaskViewTransitions.java9
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java18
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java54
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java13
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblesNavBarGestureTracker.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java30
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java30
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java11
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java29
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt16
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java35
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java18
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java46
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java13
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java155
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogImpl.java3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java9
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java83
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java14
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/AbsSplashWindowCreator.java67
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SnapshotWindowCreator.java70
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java22
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenWindowCreator.java506
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java688
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java29
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java44
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java165
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSplashWindowCreator.java150
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/phone/PhoneStartingWindowTypeAlgorithm.java10
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInit.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/CounterRotatorHelper.java3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java36
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java21
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/SleepHandler.java65
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java39
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java149
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/FullscreenUnfoldTaskAnimator.java33
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/SplitTaskUnfoldAnimator.java25
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java264
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java100
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java15
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskOperations.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskPositioner.java40
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java14
-rw-r--r--libs/WindowManager/Shell/tests/flicker/Android.bp2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/AndroidTest.xml4
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt8
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt50
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/BaseBubbleScreen.kt14
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTest.kt8
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTestCfArm.kt4
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTestShellTransit.kt6
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DragToDismissBubbleScreenTest.kt6
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DragToDismissBubbleScreenTestCfArm.kt4
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleOnLocksreenTest.kt (renamed from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleOnLockreenTest.kt)10
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleTest.kt6
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleTestCfArm.kt4
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/SendBubbleNotificationTest.kt6
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/SendBubbleNotificationTestCfArm.kt4
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt8
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt10
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTestCfArm.kt10
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipTransition.kt16
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt8
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTestCfArm.kt10
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt14
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTestCfArm.kt4
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt22
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationCfArm.kt10
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt12
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt8
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTestCfArm.kt10
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt10
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt10
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTestCfArm.kt10
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt10
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTestCfArm.kt10
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt16
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTestTestCfArm.kt10
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTest.kt12
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTestCfArm.kt10
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt8
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt18
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTestCfArm.kt10
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTestShellTransit.kt6
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipShelfHeightTransition.kt10
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt8
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt12
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt14
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinned.kt24
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt12
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplayCfArm.kt6
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/PipAppHelperTv.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt4
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt12
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByDivider.kt24
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByGoHome.kt8
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt10
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromAllApps.kt14
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromNotification.kt14
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromShortcut.kt12
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromTaskbar.kt14
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenFromOverview.kt8
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenBase.kt4
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenUtils.kt31
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt19
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromAnotherApp.kt12
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromHome.kt14
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromRecent.kt14
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairs.kt8
-rw-r--r--libs/WindowManager/Shell/tests/unittest/AndroidManifest.xml1
-rw-r--r--libs/WindowManager/Shell/tests/unittest/res/values/dimen.xml2
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java5
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java30
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java8
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java35
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java1
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java106
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java42
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java3
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/TaskPositionerTest.kt247
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java22
-rw-r--r--libs/dream/OWNERS1
-rw-r--r--libs/hwui/Android.bp5
-rw-r--r--libs/hwui/DisplayListOps.in3
-rw-r--r--libs/hwui/MemoryPolicy.h4
-rw-r--r--libs/hwui/Mesh.cpp102
-rw-r--r--libs/hwui/Mesh.h199
-rw-r--r--libs/hwui/RecordingCanvas.cpp38
-rw-r--r--libs/hwui/RecordingCanvas.h16
-rw-r--r--libs/hwui/SafeMath.h107
-rw-r--r--libs/hwui/SkiaCanvas.cpp15
-rw-r--r--libs/hwui/SkiaCanvas.h3
-rw-r--r--libs/hwui/apex/LayoutlibLoader.cpp3
-rw-r--r--libs/hwui/apex/jni_runtime.cpp2
-rw-r--r--libs/hwui/hwui/Bitmap.cpp7
-rw-r--r--libs/hwui/hwui/Canvas.h14
-rw-r--r--libs/hwui/jni/BufferUtils.cpp130
-rw-r--r--libs/hwui/jni/BufferUtils.h32
-rw-r--r--libs/hwui/jni/GraphicsJNI.h20
-rw-r--r--libs/hwui/jni/Interpolator.cpp4
-rw-r--r--libs/hwui/jni/JvmErrorReporter.h5
-rw-r--r--libs/hwui/jni/Mesh.h265
-rw-r--r--libs/hwui/jni/Path.cpp4
-rw-r--r--libs/hwui/jni/PathEffect.cpp6
-rw-r--r--libs/hwui/jni/Shader.cpp19
-rw-r--r--libs/hwui/jni/android_graphics_Canvas.cpp7
-rw-r--r--libs/hwui/jni/android_graphics_HardwareBufferRenderer.cpp5
-rw-r--r--libs/hwui/jni/android_graphics_HardwareRenderer.cpp59
-rw-r--r--libs/hwui/jni/android_graphics_Matrix.cpp2
-rw-r--r--libs/hwui/jni/android_graphics_Mesh.cpp (renamed from libs/hwui/jni/Mesh.cpp)120
-rw-r--r--libs/hwui/jni/text/GraphemeBreak.cpp67
-rw-r--r--libs/hwui/pipeline/skia/SkiaDisplayList.cpp8
-rw-r--r--libs/hwui/pipeline/skia/SkiaDisplayList.h2
-rw-r--r--libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp5
-rw-r--r--libs/hwui/pipeline/skia/SkiaRecordingCanvas.h1
-rw-r--r--location/java/android/location/GnssCapabilities.java70
-rw-r--r--media/java/android/media/AudioManager.java14
-rw-r--r--media/java/android/media/AudioRecord.java2
-rw-r--r--media/java/android/media/MediaDrm.java8
-rw-r--r--media/java/android/media/PlayerBase.java2
-rw-r--r--media/java/android/media/RingtoneManager.java2
-rw-r--r--media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java6
-rw-r--r--media/java/android/media/tv/tuner/frontend/IptvFrontendSettings.java16
-rw-r--r--media/java/android/media/tv/tuner/frontend/IptvFrontendSettingsFec.java12
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/AudioManagerUnitTest.java2
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/AudioRecordUnitTest.java2
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/AudioTrackUnitTest.java2
-rw-r--r--packages/AppPredictionLib/Android.bp2
-rw-r--r--packages/CarrierDefaultApp/res/values-af/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-am/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-ar/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-as/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-az/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-b+sr+Latn/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-be/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-bg/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-bn/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-bs/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-ca/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-cs/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-da/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-de/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-el/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-en-rAU/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-en-rCA/strings.xml4
-rw-r--r--packages/CarrierDefaultApp/res/values-en-rGB/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-en-rIN/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-en-rXC/strings.xml4
-rw-r--r--packages/CarrierDefaultApp/res/values-es-rUS/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-es/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-et/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-eu/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-fa/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-fi/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-fr-rCA/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-fr/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-gl/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-gu/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-hi/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-hr/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-hu/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-hy/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-in/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-is/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-it/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-iw/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-ja/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-ka/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-kk/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-km/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-kn/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-ko/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-ky/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-lo/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-lt/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-lv/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-mk/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-ml/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-mn/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-mr/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-ms/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-my/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-nb/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-ne/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-nl/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-or/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-pa/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-pl/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-pt-rBR/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-pt-rPT/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-pt/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-ro/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-ru/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-si/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-sk/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-sl/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-sq/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-sr/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-sv/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-sw/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-ta/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-te/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-th/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-tl/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-tr/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-uk/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-ur/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-uz/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-vi/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-zh-rCN/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-zh-rHK/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-zh-rTW/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values-zu/strings.xml6
-rw-r--r--packages/CarrierDefaultApp/res/values/strings.xml2
-rw-r--r--packages/CompanionDeviceManager/res/values-am/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-ar/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-as/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-az/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-be/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-bg/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-bn/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-bs/strings.xml14
-rw-r--r--packages/CompanionDeviceManager/res/values-ca/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-da/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-de/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-es-rUS/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-es/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-et/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-eu/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-fa/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-fr/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-gl/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-gu/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-hi/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-hu/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-in/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-is/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-ja/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-kk/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-km/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-ko/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-lv/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-mk/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-mn/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-mr/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-nb/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-or/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-pa/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-pl/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-ro/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-si/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-sl/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-sr/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-sv/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-sw/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-ta/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-te/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-tl/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-tr/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-uk/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-ur/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-vi/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml21
-rw-r--r--packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml21
-rw-r--r--packages/CredentialManager/Android.bp1
-rw-r--r--packages/CredentialManager/AndroidManifest.xml9
-rw-r--r--packages/CredentialManager/res/drawable/ic_other_devices.xml15
-rw-r--r--packages/CredentialManager/res/drawable/ic_other_sign_in.xml36
-rw-r--r--packages/CredentialManager/res/drawable/ic_other_sign_in_24.xml30
-rw-r--r--packages/CredentialManager/res/drawable/ic_passkey.xml16
-rw-r--r--packages/CredentialManager/res/drawable/ic_passkey_24.xml28
-rw-r--r--packages/CredentialManager/res/drawable/ic_password.xml31
-rw-r--r--packages/CredentialManager/res/drawable/ic_password_24.xml34
-rw-r--r--packages/CredentialManager/res/values-af/strings.xml11
-rw-r--r--packages/CredentialManager/res/values-am/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-ar/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-as/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-az/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-b+sr+Latn/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-be/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-bg/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-bn/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-bs/strings.xml15
-rw-r--r--packages/CredentialManager/res/values-ca/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-cs/strings.xml11
-rw-r--r--packages/CredentialManager/res/values-da/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-de/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-el/strings.xml11
-rw-r--r--packages/CredentialManager/res/values-en-rAU/strings.xml11
-rw-r--r--packages/CredentialManager/res/values-en-rCA/strings.xml11
-rw-r--r--packages/CredentialManager/res/values-en-rGB/strings.xml11
-rw-r--r--packages/CredentialManager/res/values-en-rIN/strings.xml11
-rw-r--r--packages/CredentialManager/res/values-en-rXC/strings.xml11
-rw-r--r--packages/CredentialManager/res/values-es-rUS/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-es/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-et/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-eu/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-fa/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-fi/strings.xml11
-rw-r--r--packages/CredentialManager/res/values-fr-rCA/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-fr/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-gl/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-gu/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-hi/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-hr/strings.xml11
-rw-r--r--packages/CredentialManager/res/values-hu/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-hy/strings.xml11
-rw-r--r--packages/CredentialManager/res/values-in/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-is/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-it/strings.xml11
-rw-r--r--packages/CredentialManager/res/values-iw/strings.xml11
-rw-r--r--packages/CredentialManager/res/values-ja/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-ka/strings.xml11
-rw-r--r--packages/CredentialManager/res/values-kk/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-km/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-kn/strings.xml11
-rw-r--r--packages/CredentialManager/res/values-ko/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-ky/strings.xml11
-rw-r--r--packages/CredentialManager/res/values-lo/strings.xml11
-rw-r--r--packages/CredentialManager/res/values-lt/strings.xml11
-rw-r--r--packages/CredentialManager/res/values-lv/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-mk/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-ml/strings.xml11
-rw-r--r--packages/CredentialManager/res/values-mn/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-mr/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-ms/strings.xml11
-rw-r--r--packages/CredentialManager/res/values-my/strings.xml11
-rw-r--r--packages/CredentialManager/res/values-nb/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-ne/strings.xml11
-rw-r--r--packages/CredentialManager/res/values-nl/strings.xml11
-rw-r--r--packages/CredentialManager/res/values-or/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-pa/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-pl/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-pt-rBR/strings.xml11
-rw-r--r--packages/CredentialManager/res/values-pt-rPT/strings.xml21
-rw-r--r--packages/CredentialManager/res/values-pt/strings.xml11
-rw-r--r--packages/CredentialManager/res/values-ro/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-ru/strings.xml11
-rw-r--r--packages/CredentialManager/res/values-si/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-sk/strings.xml11
-rw-r--r--packages/CredentialManager/res/values-sl/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-sq/strings.xml11
-rw-r--r--packages/CredentialManager/res/values-sr/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-sv/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-sw/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-ta/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-te/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-th/strings.xml11
-rw-r--r--packages/CredentialManager/res/values-tl/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-tr/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-uk/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-ur/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-uz/strings.xml11
-rw-r--r--packages/CredentialManager/res/values-vi/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-zh-rCN/strings.xml11
-rw-r--r--packages/CredentialManager/res/values-zh-rHK/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-zh-rTW/strings.xml17
-rw-r--r--packages/CredentialManager/res/values-zu/strings.xml11
-rw-r--r--packages/CredentialManager/res/values/strings.xml11
-rw-r--r--packages/CredentialManager/res/values/themes.xml6
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt154
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/CredentialProviderReceiver.kt35
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt25
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt11
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt98
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/TestUtils.kt48
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/common/DialogResult.kt2
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/common/material/ModalBottomSheet.kt11
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/common/ui/ActionButton.kt13
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/common/ui/BottomSheet.kt5
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/common/ui/Cards.kt67
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/common/ui/ConfirmButton.kt16
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt296
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/common/ui/HeadlineIcon.kt81
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/common/ui/SectionHeader.kt48
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/common/ui/SnackBar.kt92
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/common/ui/SystemUiControllerUtils.kt40
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/common/ui/Texts.kt155
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt1091
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt7
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt525
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt9
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/ui/theme/AndroidColorScheme.kt45
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/ui/theme/Color.kt36
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/ui/theme/PlatformTheme.kt64
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/ui/theme/Theme.kt38
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/ui/theme/Type.kt56
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/ui/theme/typography/PlatformTypography.kt48
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/ui/theme/typography/TypeScaleTokens.kt98
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/ui/theme/typography/TypefaceTokens.kt75
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/ui/theme/typography/TypographyTokens.kt143
-rw-r--r--packages/DynamicSystemInstallationService/AndroidManifest.xml7
-rw-r--r--packages/LocalTransport/src/com/android/localtransport/LocalTransport.java3
-rw-r--r--packages/SettingsLib/Android.bp2
-rw-r--r--packages/SettingsLib/DeviceStateRotationLock/OWNERS1
-rw-r--r--packages/SettingsLib/Spa/.idea/codeStyles/Project.xml5
-rw-r--r--packages/SettingsLib/Spa/build.gradle4
-rw-r--r--packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties2
-rw-r--r--packages/SettingsLib/Spa/spa/build.gradle6
-rw-r--r--packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPage.kt5
-rw-r--r--packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SpaEnvironment.kt9
-rw-r--r--packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/button/ActionButtons.kt17
-rw-r--r--packages/SettingsLib/Spa/testutils/build.gradle6
-rw-r--r--packages/SettingsLib/SpaPrivileged/AndroidManifest.xml3
-rw-r--r--packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppOpsController.kt11
-rw-r--r--packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppRepository.kt30
-rw-r--r--packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt8
-rw-r--r--packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListViewModelTest.kt3
-rw-r--r--packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppOpsControllerTest.kt9
-rw-r--r--packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppRepositoryTest.kt96
-rw-r--r--packages/SettingsLib/res/drawable-mcc310-mnc012/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/drawable-mcc310-mnc590/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/drawable-mcc310-mnc591/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/drawable-mcc310-mnc592/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/drawable-mcc310-mnc593/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/drawable-mcc310-mnc594/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/drawable-mcc310-mnc595/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/drawable-mcc310-mnc596/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/drawable-mcc310-mnc597/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/drawable-mcc310-mnc598/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/drawable-mcc310-mnc599/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/drawable-mcc310-mnc890/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/drawable-mcc311-mnc270/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/drawable-mcc311-mnc280/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/drawable-mcc311-mnc281/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/drawable-mcc311-mnc282/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/drawable-mcc311-mnc283/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/drawable-mcc311-mnc284/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/drawable-mcc311-mnc285/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/drawable-mcc311-mnc286/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/drawable-mcc311-mnc287/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/drawable-mcc311-mnc288/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/drawable-mcc311-mnc289/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/drawable-mcc311-mnc480/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/drawable-mcc311-mnc481/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/drawable-mcc311-mnc482/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/drawable-mcc311-mnc483/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/drawable-mcc311-mnc484/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/drawable-mcc311-mnc485/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/drawable-mcc311-mnc486/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/drawable-mcc311-mnc487/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/drawable-mcc311-mnc488/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/drawable-mcc311-mnc489/ic_5g_plus_mobiledata.xml35
-rw-r--r--packages/SettingsLib/res/values-af/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-af/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-am/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-ar/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-as/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-az/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-b+sr+Latn/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-be/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-bg/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-bn/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-bn/strings.xml12
-rw-r--r--packages/SettingsLib/res/values-bs/arrays.xml18
-rw-r--r--packages/SettingsLib/res/values-bs/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ca/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-ca/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-cs/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-da/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-de/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-el/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-en-rAU/arrays.xml18
-rw-r--r--packages/SettingsLib/res/values-en-rCA/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-en-rGB/arrays.xml18
-rw-r--r--packages/SettingsLib/res/values-en-rIN/arrays.xml18
-rw-r--r--packages/SettingsLib/res/values-en-rXC/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-es-rUS/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-es/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-es/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-et/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-eu/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-eu/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-fa/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-fi/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-fr-rCA/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-fr/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-gl/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-gu/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-hi/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-hr/arrays.xml18
-rw-r--r--packages/SettingsLib/res/values-hu/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-hy/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-in/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-is/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-it/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-iw/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-ja/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-ka/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-kk/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-km/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-kn/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-ko/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-ky/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-lo/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-lt/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-lv/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-mcc310-mnc012/strings.xml23
-rw-r--r--packages/SettingsLib/res/values-mcc310-mnc590/strings.xml22
-rw-r--r--packages/SettingsLib/res/values-mcc310-mnc591/strings.xml22
-rw-r--r--packages/SettingsLib/res/values-mcc310-mnc592/strings.xml22
-rw-r--r--packages/SettingsLib/res/values-mcc310-mnc593/strings.xml22
-rw-r--r--packages/SettingsLib/res/values-mcc310-mnc594/strings.xml22
-rw-r--r--packages/SettingsLib/res/values-mcc310-mnc595/strings.xml22
-rw-r--r--packages/SettingsLib/res/values-mcc310-mnc596/strings.xml22
-rw-r--r--packages/SettingsLib/res/values-mcc310-mnc597/strings.xml22
-rw-r--r--packages/SettingsLib/res/values-mcc310-mnc598/strings.xml22
-rw-r--r--packages/SettingsLib/res/values-mcc310-mnc599/strings.xml22
-rw-r--r--packages/SettingsLib/res/values-mcc310-mnc890/strings.xml22
-rw-r--r--packages/SettingsLib/res/values-mcc311-mnc270/strings.xml22
-rw-r--r--packages/SettingsLib/res/values-mcc311-mnc280/strings.xml22
-rw-r--r--packages/SettingsLib/res/values-mcc311-mnc281/strings.xml22
-rw-r--r--packages/SettingsLib/res/values-mcc311-mnc282/strings.xml22
-rw-r--r--packages/SettingsLib/res/values-mcc311-mnc283/strings.xml22
-rw-r--r--packages/SettingsLib/res/values-mcc311-mnc284/strings.xml22
-rw-r--r--packages/SettingsLib/res/values-mcc311-mnc285/strings.xml22
-rw-r--r--packages/SettingsLib/res/values-mcc311-mnc286/strings.xml22
-rw-r--r--packages/SettingsLib/res/values-mcc311-mnc287/strings.xml22
-rw-r--r--packages/SettingsLib/res/values-mcc311-mnc288/strings.xml22
-rw-r--r--packages/SettingsLib/res/values-mcc311-mnc289/strings.xml22
-rw-r--r--packages/SettingsLib/res/values-mcc311-mnc481/strings.xml22
-rw-r--r--packages/SettingsLib/res/values-mcc311-mnc482/strings.xml22
-rw-r--r--packages/SettingsLib/res/values-mcc311-mnc483/strings.xml22
-rw-r--r--packages/SettingsLib/res/values-mcc311-mnc484/strings.xml22
-rw-r--r--packages/SettingsLib/res/values-mcc311-mnc485/strings.xml22
-rw-r--r--packages/SettingsLib/res/values-mcc311-mnc486/strings.xml22
-rw-r--r--packages/SettingsLib/res/values-mcc311-mnc487/strings.xml22
-rw-r--r--packages/SettingsLib/res/values-mcc311-mnc488/strings.xml22
-rw-r--r--packages/SettingsLib/res/values-mcc311-mnc489/strings.xml22
-rw-r--r--packages/SettingsLib/res/values-mk/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-ml/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-mn/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-mr/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-ms/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-my/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-nb/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-ne/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-ne/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-nl/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-or/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-pa/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-pl/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-pl/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-pt-rBR/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-pt-rBR/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-pt-rPT/arrays.xml18
-rw-r--r--packages/SettingsLib/res/values-pt-rPT/strings.xml6
-rw-r--r--packages/SettingsLib/res/values-pt/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-pt/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ro/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-ro/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ru/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-ru/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-si/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-sk/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-sk/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-sl/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-sq/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-sr/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-sv/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-sw/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-ta/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-te/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-th/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-tl/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-tr/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-tr/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-uk/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-ur/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-uz/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-vi/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-zh-rCN/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-zh-rHK/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-zh-rTW/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values-zh-rTW/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-zu/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values/arrays.xml14
-rw-r--r--packages/SettingsLib/res/values/styles.xml4
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/Utils.java8
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java2
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java2
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java13
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java3
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java3
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/udfps/UdfpsUtils.java49
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java31
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java25
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java25
-rw-r--r--packages/SettingsProvider/Android.bp1
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java3
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java3
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java209
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java9
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java3
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java63
-rw-r--r--packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java2
-rw-r--r--packages/SettingsProvider/test/src/com/android/providers/settings/GenerationRegistryTest.java177
-rw-r--r--packages/Shell/AndroidManifest.xml6
-rw-r--r--packages/SystemUI/Android.bp1
-rw-r--r--packages/SystemUI/AndroidManifest.xml2
-rw-r--r--packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/AccessibilityMenuService.java1
-rw-r--r--packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java9
-rw-r--r--packages/SystemUI/animation/Android.bp26
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/Expandable.kt2
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt2
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt2
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/RemoteTransitionAdapter.kt4
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/ShadeInterpolation.kt2
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt5
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableImageView.kt2
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableTextView.kt2
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/MultiRippleView.kt18
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt2
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt19
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt10
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt2
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt4
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/util/AnimatorExtensions.kt80
-rw-r--r--packages/SystemUI/checks/src/com/android/internal/systemui/lint/DumpableNotRegisteredDetector.kt127
-rw-r--r--packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt1
-rw-r--r--packages/SystemUI/checks/tests/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetectorTest.kt27
-rw-r--r--packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DumpableNotRegisteredDetectorTest.kt328
-rw-r--r--packages/SystemUI/compose/core/src/com/android/compose/SystemUiController.kt18
-rw-r--r--packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt4
-rw-r--r--packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt4
-rw-r--r--packages/SystemUI/compose/core/src/com/android/compose/pager/Pager.kt34
-rw-r--r--packages/SystemUI/compose/core/src/com/android/compose/pager/PagerState.kt2
-rw-r--r--packages/SystemUI/compose/core/src/com/android/compose/pager/SnappingFlingBehavior.kt4
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreen.kt2
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreenEmpty.kt4
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt7
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt16
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderContract.kt20
-rw-r--r--packages/SystemUI/ktfmt_includes.txt121
-rw-r--r--packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt2
-rw-r--r--packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/DynamicColor.java8
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt16
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogBuffer.kt33
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerDebug.kt1
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/util/RingBuffer.kt2
-rw-r--r--packages/SystemUI/res-keyguard/drawable-mdpi/ic_lockscreen_sim.pngbin2602 -> 0 bytes
-rw-r--r--packages/SystemUI/res-keyguard/drawable-xhdpi/ic_lockscreen_sim.pngbin5201 -> 0 bytes
-rw-r--r--packages/SystemUI/res-keyguard/drawable/ic_lockscreen_sim.png (renamed from packages/SystemUI/res-keyguard/drawable-hdpi/ic_lockscreen_sim.png)bin4083 -> 4083 bytes
-rw-r--r--packages/SystemUI/res-keyguard/layout/fsi_chrome_view.xml49
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_num_pad_key.xml4
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml341
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml301
-rw-r--r--packages/SystemUI/res-keyguard/values-af/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-am/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-ar/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-as/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-az/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-be/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-bg/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-bn/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-bs/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-ca/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-cs/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-da/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-de/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-el/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-en-rAU/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-en-rCA/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-en-rGB/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-en-rIN/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-en-rXC/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-es-rUS/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-es/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-et/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-eu/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-fa/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-fi/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-fr/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-gl/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-gu/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-hi/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-hr/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-hu/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-hy/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-in/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-is/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-it/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-iw/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-ja/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-ka/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-kk/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-km/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-kn/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-ko/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-ky/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-lo/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-lt/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-lv/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-mk/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-ml/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-mn/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-mr/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-ms/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-my/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-nb/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-ne/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-nl/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-or/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-pa/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-pl/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-pt/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-ro/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-ru/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-si/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-sk/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-sl/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-sq/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-sr/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-sv/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-sw/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-ta/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-te/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-th/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-tl/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-tr/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-uk/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-ur/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-uz/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-vi/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values-zu/strings.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values/strings.xml2
-rw-r--r--packages/SystemUI/res-product/values/strings.xml9
-rw-r--r--packages/SystemUI/res/drawable/controls_panel_background.xml2
-rw-r--r--packages/SystemUI/res/drawable/qs_footer_edit_circle.xml36
-rw-r--r--packages/SystemUI/res/drawable/statusbar_chip_bg.xml23
-rw-r--r--packages/SystemUI/res/drawable/statusbar_privacy_chip_bg.xml (renamed from packages/SystemUI/res/drawable/privacy_chip_bg.xml)0
-rw-r--r--packages/SystemUI/res/layout/battery_status_chip.xml43
-rw-r--r--packages/SystemUI/res/layout/combined_qs_header.xml11
-rw-r--r--packages/SystemUI/res/layout/controls_fullscreen.xml12
-rw-r--r--packages/SystemUI/res/layout/controls_with_favorites.xml140
-rw-r--r--packages/SystemUI/res/layout/large_screen_shade_header.xml100
-rw-r--r--packages/SystemUI/res/layout/notif_half_shelf.xml9
-rw-r--r--packages/SystemUI/res/layout/notif_half_shelf_row.xml3
-rw-r--r--packages/SystemUI/res/layout/ongoing_privacy_chip.xml14
-rw-r--r--packages/SystemUI/res/layout/qs_footer_impl.xml2
-rw-r--r--packages/SystemUI/res/layout/quick_qs_status_icons.xml111
-rw-r--r--packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml32
-rw-r--r--packages/SystemUI/res/layout/quick_status_bar_header_date_privacy.xml75
-rw-r--r--packages/SystemUI/res/layout/window_magnification_settings_view.xml4
-rw-r--r--packages/SystemUI/res/raw/biometricprompt_rear_landscape_base.json1
-rw-r--r--packages/SystemUI/res/raw/biometricprompt_rear_portrait_base.json1
-rw-r--r--packages/SystemUI/res/raw/biometricprompt_rear_portrait_reverse_base.json1
-rw-r--r--packages/SystemUI/res/values-af/strings.xml67
-rw-r--r--packages/SystemUI/res/values-af/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-am/strings.xml66
-rw-r--r--packages/SystemUI/res/values-am/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-ar/strings.xml73
-rw-r--r--packages/SystemUI/res/values-ar/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-as/strings.xml71
-rw-r--r--packages/SystemUI/res/values-as/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-az/strings.xml71
-rw-r--r--packages/SystemUI/res/values-az/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-b+sr+Latn/strings.xml71
-rw-r--r--packages/SystemUI/res/values-b+sr+Latn/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-be/strings.xml71
-rw-r--r--packages/SystemUI/res/values-be/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-bg/strings.xml71
-rw-r--r--packages/SystemUI/res/values-bg/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-bn/strings.xml73
-rw-r--r--packages/SystemUI/res/values-bn/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-bs/strings.xml71
-rw-r--r--packages/SystemUI/res/values-bs/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-ca/strings.xml73
-rw-r--r--packages/SystemUI/res/values-ca/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-cs/strings.xml65
-rw-r--r--packages/SystemUI/res/values-cs/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-da/strings.xml71
-rw-r--r--packages/SystemUI/res/values-da/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-de/strings.xml77
-rw-r--r--packages/SystemUI/res/values-de/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-el/strings.xml65
-rw-r--r--packages/SystemUI/res/values-el/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-en-rAU/strings.xml65
-rw-r--r--packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-en-rCA/strings.xml59
-rw-r--r--packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-en-rGB/strings.xml65
-rw-r--r--packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-en-rIN/strings.xml65
-rw-r--r--packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-en-rXC/strings.xml59
-rw-r--r--packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings.xml73
-rw-r--r--packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-es/strings.xml73
-rw-r--r--packages/SystemUI/res/values-es/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-et/strings.xml71
-rw-r--r--packages/SystemUI/res/values-et/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-eu/strings.xml72
-rw-r--r--packages/SystemUI/res/values-eu/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-fa/strings.xml77
-rw-r--r--packages/SystemUI/res/values-fa/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-fi/strings.xml69
-rw-r--r--packages/SystemUI/res/values-fi/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-fr-rCA/strings.xml78
-rw-r--r--packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-fr/strings.xml71
-rw-r--r--packages/SystemUI/res/values-fr/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-gl/strings.xml71
-rw-r--r--packages/SystemUI/res/values-gl/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-gu/strings.xml71
-rw-r--r--packages/SystemUI/res/values-gu/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-hi/strings.xml73
-rw-r--r--packages/SystemUI/res/values-hi/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-hr/strings.xml65
-rw-r--r--packages/SystemUI/res/values-hr/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-hu/strings.xml65
-rw-r--r--packages/SystemUI/res/values-hu/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-hy/strings.xml67
-rw-r--r--packages/SystemUI/res/values-hy/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-in/strings.xml71
-rw-r--r--packages/SystemUI/res/values-in/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-is/strings.xml75
-rw-r--r--packages/SystemUI/res/values-is/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-it/strings.xml67
-rw-r--r--packages/SystemUI/res/values-it/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-iw/strings.xml65
-rw-r--r--packages/SystemUI/res/values-iw/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-ja/strings.xml71
-rw-r--r--packages/SystemUI/res/values-ja/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-ka/strings.xml65
-rw-r--r--packages/SystemUI/res/values-ka/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-kk/strings.xml71
-rw-r--r--packages/SystemUI/res/values-kk/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-km/strings.xml71
-rw-r--r--packages/SystemUI/res/values-km/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-kn/strings.xml65
-rw-r--r--packages/SystemUI/res/values-kn/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml73
-rw-r--r--packages/SystemUI/res/values-ko/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-ky/strings.xml65
-rw-r--r--packages/SystemUI/res/values-ky/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-land/dimens.xml4
-rw-r--r--packages/SystemUI/res/values-lo/strings.xml65
-rw-r--r--packages/SystemUI/res/values-lo/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-lt/strings.xml65
-rw-r--r--packages/SystemUI/res/values-lt/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-lv/strings.xml75
-rw-r--r--packages/SystemUI/res/values-lv/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-mk/strings.xml71
-rw-r--r--packages/SystemUI/res/values-mk/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-ml/strings.xml65
-rw-r--r--packages/SystemUI/res/values-ml/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-mn/strings.xml71
-rw-r--r--packages/SystemUI/res/values-mn/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-mr/strings.xml71
-rw-r--r--packages/SystemUI/res/values-mr/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-ms/strings.xml65
-rw-r--r--packages/SystemUI/res/values-ms/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-my/strings.xml65
-rw-r--r--packages/SystemUI/res/values-my/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-nb/strings.xml71
-rw-r--r--packages/SystemUI/res/values-nb/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-ne/strings.xml65
-rw-r--r--packages/SystemUI/res/values-ne/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-nl/strings.xml65
-rw-r--r--packages/SystemUI/res/values-nl/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-or/strings.xml71
-rw-r--r--packages/SystemUI/res/values-or/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-pa/strings.xml71
-rw-r--r--packages/SystemUI/res/values-pa/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml71
-rw-r--r--packages/SystemUI/res/values-pl/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-pt-rBR/strings.xml65
-rw-r--r--packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings.xml65
-rw-r--r--packages/SystemUI/res/values-pt-rPT/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-pt/strings.xml65
-rw-r--r--packages/SystemUI/res/values-pt/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-ro/strings.xml71
-rw-r--r--packages/SystemUI/res/values-ro/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-ru/strings.xml65
-rw-r--r--packages/SystemUI/res/values-ru/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-si/strings.xml71
-rw-r--r--packages/SystemUI/res/values-si/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-sk/strings.xml65
-rw-r--r--packages/SystemUI/res/values-sk/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-sl/strings.xml75
-rw-r--r--packages/SystemUI/res/values-sl/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-sq/strings.xml65
-rw-r--r--packages/SystemUI/res/values-sq/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-sr/strings.xml71
-rw-r--r--packages/SystemUI/res/values-sr/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-sv/strings.xml71
-rw-r--r--packages/SystemUI/res/values-sv/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-sw/strings.xml73
-rw-r--r--packages/SystemUI/res/values-sw/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-sw600dp/dimens.xml4
-rw-r--r--packages/SystemUI/res/values-sw720dp-land/dimens.xml2
-rw-r--r--packages/SystemUI/res/values-sw720dp-port/dimens.xml2
-rw-r--r--packages/SystemUI/res/values-sw720dp/dimens.xml3
-rw-r--r--packages/SystemUI/res/values-ta/strings.xml72
-rw-r--r--packages/SystemUI/res/values-ta/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-te/strings.xml65
-rw-r--r--packages/SystemUI/res/values-te/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-th/strings.xml67
-rw-r--r--packages/SystemUI/res/values-th/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-tl/strings.xml71
-rw-r--r--packages/SystemUI/res/values-tl/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-tr/strings.xml71
-rw-r--r--packages/SystemUI/res/values-tr/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-uk/strings.xml71
-rw-r--r--packages/SystemUI/res/values-uk/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-ur/strings.xml83
-rw-r--r--packages/SystemUI/res/values-ur/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-uz/strings.xml77
-rw-r--r--packages/SystemUI/res/values-uz/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-vi/strings.xml71
-rw-r--r--packages/SystemUI/res/values-vi/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings.xml67
-rw-r--r--packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-zh-rHK/strings.xml79
-rw-r--r--packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-zh-rTW/strings.xml71
-rw-r--r--packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-zu/strings.xml65
-rw-r--r--packages/SystemUI/res/values-zu/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values/config.xml4
-rw-r--r--packages/SystemUI/res/values/dimens.xml18
-rw-r--r--packages/SystemUI/res/values/strings.xml22
-rw-r--r--packages/SystemUI/screenshot/AndroidManifest.xml1
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimator.kt33
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/condition/Evaluator.kt2
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl5
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java6
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java2
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java15
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java221
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java270
-rw-r--r--packages/SystemUI/src/com/android/keyguard/EmergencyButton.java9
-rw-r--r--packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java114
-rw-r--r--packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt1
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt5
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java27
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java10
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java17
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java30
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java5
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java173
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java10
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java21
-rw-r--r--packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java5
-rw-r--r--packages/SystemUI/src/com/android/keyguard/NumPadKey.java15
-rw-r--r--packages/SystemUI/src/com/android/keyguard/PasswordTextView.java12
-rw-r--r--packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt622
-rw-r--r--packages/SystemUI/src/com/android/keyguard/mediator/ScreenOnCoordinator.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java31
-rw-r--r--packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt41
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/FaceHelpMessageDeferral.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/udfps/NormalizedTouchData.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialog.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogController.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/common/coroutine/ChannelExt.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsView.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt13
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt20
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepository.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImpl.kt20
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsDialogManager.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/ControlsDialogsFactory.kt49
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt59
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt21
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/devicepolicy/DevicePolicyManagerExt.kt32
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java35
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/BouncerScrimController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/Flags.kt60
-rw-r--r--packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/KeyboardModule.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/data/model/BacklightModel.kt (renamed from core/java/android/window/IWindowlessStartingSurfaceCallback.aidl)17
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/data/repository/KeyboardRepository.kt116
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManager.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt27
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DevicePostureRepository.kt58
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManager.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt21
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/shared/model/DevicePosture.kt41
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/shared/model/SysUiFaceAuthenticateOptions.kt99
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt21
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardLongPressViewBinder.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLockscreenLog.java33
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt26
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/models/player/SeekBarViewModel.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/SmartspaceMediaData.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataFilter.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt46
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaTimeoutListener.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/resume/MediaResumeListener.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowserLogger.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/AnimationBindHandler.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/IlluminationDrawable.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt118
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt19
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSwitcherDialogUI.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionTaskView.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProvider.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java80
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java64
-rw-r--r--packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt139
-rw-r--r--packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEnabledKey.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEntryPoint.kt41
-rw-r--r--packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEventLogger.kt101
-rw-r--r--packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfo.kt33
-rw-r--r--packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfoResolver.kt49
-rw-r--r--packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt37
-rw-r--r--packages/SystemUI/src/com/android/systemui/notetask/NoteTaskLaunchMode.kt33
-rw-r--r--packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/notetask/OWNERS2
-rw-r--r--packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfig.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceModule.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt18
-rw-r--r--packages/SystemUI/src/com/android/systemui/qrcodescanner/dagger/QRCodeScannerModule.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSFragment.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSHost.java71
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanel.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java68
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java462
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java161
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/TileServiceRequestController.kt22
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/FontScalingTile.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/WorkProfileMessageController.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivity.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/scrim/ScrimDrawable.java58
-rw-r--r--packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt16
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt28
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManager.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationController.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java255
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt25
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationsQuickSettingsContainer.java41
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java156
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt (renamed from packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt)292
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt47
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt20
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/transition/SplitShadeOverScroller.kt167
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java42
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BatteryStatusChip.kt73
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutsReceiver.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProvider.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/events/StatusBarEventsModule.kt71
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt27
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt116
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt30
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt322
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImpl.kt425
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLegacyImpl.kt314
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt27
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DismissibilityCoordinator.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SectionStyleProvider.kt37
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeRepo.kt102
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeView.kt83
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewBinder.kt99
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewModelFactory.kt87
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiDebug.kt16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiTaskViewConfig.kt75
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java91
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java35
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java44
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesComponent.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt50
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfig.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcher.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/stylus/OWNERS2
-rw-r--r--packages/SystemUI/src/com/android/systemui/stylus/StylusManager.kt89
-rw-r--r--packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerStartable.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt18
-rw-r--r--packages/SystemUI/src/com/android/systemui/telephony/ui/activity/SwitchToManagedProfileForCallActivity.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/temporarydisplay/TouchableRegionViewController.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarAnimator.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/unfold/FoldStateLoggingProviderImpl.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/user/UserCreator.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/user/domain/interactor/GuestUserInteractor.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/EmergencyButtonControllerTest.kt112
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt20
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java43
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java371
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/mediator/ScreenOnCoordinatorTest.kt28
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/accessibility/fontscaling/FontScalingDialogTest.kt10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt216
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt156
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bluetooth/BroadcastDialogTest.java29
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsViewTest.java17
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt34
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImplTest.kt12
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/settings/ControlsSettingsDialogManagerImplTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsDialogsFactoryTest.kt89
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt68
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/ui/OverflowMenuAdapterTest.kt8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/devicepolicy/DevicePolicyManagerExtTest.kt94
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java30
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java38
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt191
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt52
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DevicePostureRepositoryTest.kt80
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManagerTest.kt9
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt12
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt13
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt292
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/controls/resume/MediaResumeListenerTest.kt44
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt118
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt26
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/monet/DynamicColorTest.java96
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt390
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskEventLoggerTest.kt160
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoResolverTest.kt15
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoTest.kt73
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInitializerTest.kt52
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/notetask/OWNERS2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfigTest.kt5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java18
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt19
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java129
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt157
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileAdapterTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java30
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTest.java18
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceRequestControllerTest.kt28
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java70
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt17
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CameraToggleTileTest.kt7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorCorrectionTileTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DreamTileTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FlashlightTileTest.kt11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt16
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HotspotTileTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java12
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NfcTileTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt66
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/OneHandedModeTileTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java13
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UiModeNightTileTest.kt11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsActivityTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerTest.kt319
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java754
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java766
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerWithCoroutinesTest.kt179
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/NotificationQSContainerControllerTest.kt19
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerTest.java244
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt (renamed from packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerCombinedTest.kt)597
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt130
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/transition/SplitShadeOverScrollerTest.kt112
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt35
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt30
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt35
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shared/system/RemoteTransitionTest.java3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyboardShortcutsReceiverTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/events/FakeStatusEvent.kt29
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImplTest.kt470
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLoggerTest.kt111
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorTest.kt163
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/FakeNodeController.kt29
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/fsi/FsiChromeRepoTest.kt210
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewModelFactoryTest.kt112
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt34
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java31
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java149
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java66
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java20
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java68
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java25
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java31
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/stylus/OWNERS2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/stylus/StylusManagerTest.kt31
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerStartableTest.kt1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt124
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt27
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/coroutines/Flow.kt1
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeBiometricSettingsRepository.kt4
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDevicePostureRepository.kt31
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt17
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/util/FakeSystemUIDialogController.kt86
-rw-r--r--packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt12
-rw-r--r--packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt23
-rw-r--r--packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt62
-rw-r--r--packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt13
-rw-r--r--packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.kt1
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java11
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java6
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java172
-rw-r--r--services/accessibility/java/com/android/server/accessibility/FlashNotificationsController.java7
-rw-r--r--services/accessibility/java/com/android/server/accessibility/ProxyAccessibilityServiceConnection.java45
-rw-r--r--services/accessibility/java/com/android/server/accessibility/ProxyManager.java67
-rw-r--r--services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java2
-rw-r--r--services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java80
-rw-r--r--services/api/current.txt2
-rw-r--r--services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java26
-rw-r--r--services/autofill/java/com/android/server/autofill/Session.java43
-rw-r--r--services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java35
-rw-r--r--services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferProcessor.java16
-rw-r--r--services/companion/java/com/android/server/companion/securechannel/AttestationVerifier.java2
-rw-r--r--services/companion/java/com/android/server/companion/securechannel/SecureChannel.java7
-rw-r--r--services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java536
-rw-r--r--services/companion/java/com/android/server/companion/transport/CryptoManager.java103
-rw-r--r--services/companion/java/com/android/server/companion/transport/RawTransport.java93
-rw-r--r--services/companion/java/com/android/server/companion/transport/SecureTransport.java137
-rw-r--r--services/companion/java/com/android/server/companion/transport/Transport.java239
-rw-r--r--services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java14
-rw-r--r--services/companion/java/com/android/server/companion/virtual/InputController.java9
-rw-r--r--services/companion/java/com/android/server/companion/virtual/SensorController.java70
-rw-r--r--services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java355
-rw-r--r--services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java152
-rw-r--r--services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java30
-rw-r--r--services/core/java/android/os/BatteryStatsInternal.java2
-rw-r--r--services/core/java/com/android/server/BatteryService.java93
-rw-r--r--services/core/java/com/android/server/BinaryTransparencyService.java51
-rw-r--r--services/core/java/com/android/server/DropBoxManagerService.java12
-rw-r--r--services/core/java/com/android/server/StorageManagerService.java13
-rw-r--r--services/core/java/com/android/server/TEST_MAPPING24
-rw-r--r--services/core/java/com/android/server/accounts/AccountManagerService.java7
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java190
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerConstants.java50
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerLocal.java54
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java296
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerShellCommand.java46
-rw-r--r--services/core/java/com/android/server/am/AnrHelper.java2
-rw-r--r--services/core/java/com/android/server/am/AppBatteryTracker.java2
-rw-r--r--services/core/java/com/android/server/am/AppExitInfoTracker.java2
-rw-r--r--services/core/java/com/android/server/am/AppProfiler.java8
-rw-r--r--services/core/java/com/android/server/am/BatteryStatsService.java23
-rw-r--r--services/core/java/com/android/server/am/BroadcastQueueModernImpl.java16
-rw-r--r--services/core/java/com/android/server/am/CachedAppOptimizer.java64
-rw-r--r--services/core/java/com/android/server/am/ContentProviderHelper.java116
-rw-r--r--services/core/java/com/android/server/am/EventLogTags.logtags6
-rw-r--r--services/core/java/com/android/server/am/ForegroundServiceTypeLoggerModule.java4
-rw-r--r--services/core/java/com/android/server/am/OomAdjuster.java428
-rw-r--r--services/core/java/com/android/server/am/PendingIntentRecord.java3
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java5
-rw-r--r--services/core/java/com/android/server/am/SameProcessApplicationThread.java29
-rw-r--r--services/core/java/com/android/server/am/TEST_MAPPING4
-rw-r--r--services/core/java/com/android/server/appop/AppOpsService.java208
-rw-r--r--services/core/java/com/android/server/appop/AppOpsUidStateTrackerImpl.java9
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java15
-rw-r--r--services/core/java/com/android/server/audio/SoundDoseHelper.java364
-rw-r--r--services/core/java/com/android/server/audio/TEST_MAPPING6
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java26
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java2
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/BiometricServiceProvider.java3
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/BiometricStateCallback.java2
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java12
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java11
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/FaceService.java42
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java18
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java30
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java14
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInternalCleanupClient.java4
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java45
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java38
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java17
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceInternalCleanupClient.java4
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java10
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java103
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java17
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/AidlConversionUtils.java4
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java13
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java8
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java5
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClient.java3
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java37
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java39
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java12
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java17
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java8
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintInternalCleanupClient.java3
-rw-r--r--services/core/java/com/android/server/clipboard/ClipboardService.java49
-rw-r--r--services/core/java/com/android/server/connectivity/NetdEventListenerService.java38
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java5
-rw-r--r--services/core/java/com/android/server/cpu/CpuMonitorService.java2
-rw-r--r--services/core/java/com/android/server/display/BrightnessTracker.java41
-rw-r--r--services/core/java/com/android/server/display/DeviceStateToLayoutMap.java2
-rw-r--r--services/core/java/com/android/server/display/DisplayDevice.java9
-rw-r--r--services/core/java/com/android/server/display/DisplayDeviceConfig.java125
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java48
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java180
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController2.java180
-rw-r--r--services/core/java/com/android/server/display/LocalDisplayAdapter.java23
-rw-r--r--services/core/java/com/android/server/display/LogicalDisplay.java20
-rw-r--r--services/core/java/com/android/server/display/LogicalDisplayMapper.java10
-rw-r--r--services/core/java/com/android/server/display/OWNERS2
-rw-r--r--services/core/java/com/android/server/display/OverlayDisplayAdapter.java1
-rw-r--r--services/core/java/com/android/server/display/brightness/BrightnessEvent.java2
-rw-r--r--services/core/java/com/android/server/display/layout/Layout.java17
-rw-r--r--services/core/java/com/android/server/display/mode/DisplayModeDirector.java (renamed from services/core/java/com/android/server/display/DisplayModeDirector.java)159
-rw-r--r--services/core/java/com/android/server/display/mode/SkinThermalStatusObserver.java263
-rw-r--r--services/core/java/com/android/server/dreams/DreamController.java7
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiControlService.java4
-rw-r--r--services/core/java/com/android/server/health/HealthServiceWrapperAidl.java17
-rw-r--r--services/core/java/com/android/server/input/KeyboardLayoutManager.java24
-rw-r--r--services/core/java/com/android/server/inputmethod/HandwritingModeController.java51
-rw-r--r--services/core/java/com/android/server/inputmethod/ImeTrackerService.java150
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java12
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java285
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodUtils.java9
-rw-r--r--services/core/java/com/android/server/locales/AppSupportedLocalesChangedAtomRecord.java72
-rw-r--r--services/core/java/com/android/server/locales/LocaleManagerService.java122
-rw-r--r--services/core/java/com/android/server/location/contexthub/ContextHubService.java21
-rw-r--r--services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java5
-rw-r--r--services/core/java/com/android/server/locksettings/LockSettingsService.java155
-rw-r--r--services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java46
-rw-r--r--services/core/java/com/android/server/media/AudioPoliciesBluetoothRouteController.java482
-rw-r--r--services/core/java/com/android/server/media/AudioPoliciesDeviceRouteController.java175
-rw-r--r--services/core/java/com/android/server/media/BluetoothProfileMonitor.java178
-rw-r--r--services/core/java/com/android/server/media/BluetoothRouteController.java17
-rw-r--r--services/core/java/com/android/server/media/DeviceRouteController.java95
-rw-r--r--services/core/java/com/android/server/media/LegacyBluetoothRouteController.java8
-rw-r--r--services/core/java/com/android/server/media/LegacyDeviceRouteController.java184
-rw-r--r--services/core/java/com/android/server/media/MediaFeatureFlagManager.java66
-rw-r--r--services/core/java/com/android/server/media/SystemMediaRoute2Provider.java142
-rw-r--r--services/core/java/com/android/server/notification/ManagedServices.java20
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java23
-rw-r--r--services/core/java/com/android/server/notification/PreferencesHelper.java15
-rw-r--r--services/core/java/com/android/server/notification/ZenModeHelper.java2
-rw-r--r--services/core/java/com/android/server/pm/BackgroundDexOptService.java4
-rw-r--r--services/core/java/com/android/server/pm/DexOptHelper.java48
-rw-r--r--services/core/java/com/android/server/pm/InstallPackageHelper.java4
-rw-r--r--services/core/java/com/android/server/pm/InstallRequest.java26
-rw-r--r--services/core/java/com/android/server/pm/PackageDexOptimizer.java4
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java12
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommand.java8
-rw-r--r--services/core/java/com/android/server/pm/PackageMetrics.java11
-rw-r--r--services/core/java/com/android/server/pm/ResilientAtomicFile.java265
-rw-r--r--services/core/java/com/android/server/pm/Settings.java1343
-rw-r--r--services/core/java/com/android/server/pm/ShortcutPackage.java102
-rw-r--r--services/core/java/com/android/server/pm/ShortcutPackageItem.java7
-rw-r--r--services/core/java/com/android/server/pm/ShortcutService.java113
-rw-r--r--services/core/java/com/android/server/pm/SuspendPackageHelper.java17
-rw-r--r--services/core/java/com/android/server/pm/UserManagerInternal.java35
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java52
-rw-r--r--services/core/java/com/android/server/pm/UserManagerServiceShellCommand.java18
-rw-r--r--services/core/java/com/android/server/pm/UserVisibilityMediator.java221
-rw-r--r--services/core/java/com/android/server/policy/PermissionPolicyService.java37
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java152
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java23
-rw-r--r--services/core/java/com/android/server/power/stats/BatteryStatsImpl.java12
-rw-r--r--services/core/java/com/android/server/power/stats/CpuWakeupStats.java37
-rw-r--r--services/core/java/com/android/server/rollback/OWNERS4
-rw-r--r--services/core/java/com/android/server/sensors/SensorManagerInternal.java28
-rw-r--r--services/core/java/com/android/server/sensors/SensorService.java7
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java4
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerService.java9
-rw-r--r--services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java207
-rw-r--r--services/core/java/com/android/server/timedetector/NetworkTimeUpdateServiceShellCommand.java14
-rw-r--r--services/core/java/com/android/server/timedetector/TimeDetectorService.java96
-rw-r--r--services/core/java/com/android/server/timedetector/TimeDetectorShellCommand.java40
-rw-r--r--services/core/java/com/android/server/utils/Slogf.java145
-rw-r--r--services/core/java/com/android/server/wallpaper/WallpaperManagerService.java4
-rw-r--r--services/core/java/com/android/server/wm/AccessibilityController.java2
-rw-r--r--services/core/java/com/android/server/wm/ActivityClientController.java16
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java180
-rw-r--r--services/core/java/com/android/server/wm/ActivitySecurityModelFeatureFlags.java3
-rw-r--r--services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java35
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java115
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java59
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskSupervisor.java187
-rw-r--r--services/core/java/com/android/server/wm/AppTransition.java40
-rw-r--r--services/core/java/com/android/server/wm/AppTransitionController.java2
-rw-r--r--services/core/java/com/android/server/wm/AsyncRotationController.java29
-rw-r--r--services/core/java/com/android/server/wm/BackNavigationController.java328
-rw-r--r--services/core/java/com/android/server/wm/BackgroundActivityStartController.java29
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java34
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java14
-rw-r--r--services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java69
-rw-r--r--services/core/java/com/android/server/wm/EventLogTags.logtags2
-rw-r--r--services/core/java/com/android/server/wm/ImeTargetVisibilityPolicy.java51
-rw-r--r--services/core/java/com/android/server/wm/InsetsPolicy.java20
-rw-r--r--services/core/java/com/android/server/wm/LetterboxConfiguration.java15
-rw-r--r--services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java27
-rw-r--r--services/core/java/com/android/server/wm/LetterboxUiController.java76
-rw-r--r--services/core/java/com/android/server/wm/OWNERS1
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java105
-rw-r--r--services/core/java/com/android/server/wm/Session.java2
-rw-r--r--services/core/java/com/android/server/wm/Task.java28
-rw-r--r--services/core/java/com/android/server/wm/TaskDisplayArea.java5
-rw-r--r--services/core/java/com/android/server/wm/TaskFragment.java7
-rw-r--r--services/core/java/com/android/server/wm/TaskOrganizerController.java54
-rw-r--r--services/core/java/com/android/server/wm/Transition.java37
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java15
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java3
-rw-r--r--services/core/java/com/android/server/wm/WindowOrganizerController.java21
-rw-r--r--services/core/java/com/android/server/wm/WindowProcessController.java30
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java6
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java52
-rw-r--r--services/core/java/com/android/server/wm/WindowSurfaceController.java5
-rw-r--r--services/core/jni/Android.bp1
-rw-r--r--services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp232
-rw-r--r--services/core/jni/com_android_server_sensor_SensorService.cpp69
-rw-r--r--services/core/xsd/display-device-config/display-device-config.xsd30
-rw-r--r--services/core/xsd/display-device-config/schema/current.txt18
-rw-r--r--services/core/xsd/display-layout-config/display-layout-config.xsd1
-rw-r--r--services/core/xsd/display-layout-config/schema/current.txt2
-rw-r--r--services/credentials/java/com/android/server/credentials/ClearRequestSession.java18
-rw-r--r--services/credentials/java/com/android/server/credentials/CreateRequestSession.java27
-rw-r--r--services/credentials/java/com/android/server/credentials/CredentialDescriptionRegistry.java35
-rw-r--r--services/credentials/java/com/android/server/credentials/CredentialManagerService.java241
-rw-r--r--services/credentials/java/com/android/server/credentials/GetRequestSession.java64
-rw-r--r--services/credentials/java/com/android/server/credentials/MetricUtilities.java110
-rw-r--r--services/credentials/java/com/android/server/credentials/ProviderCreateSession.java9
-rw-r--r--services/credentials/java/com/android/server/credentials/ProviderGetSession.java80
-rw-r--r--services/credentials/java/com/android/server/credentials/ProviderRegistryGetSession.java50
-rw-r--r--services/credentials/java/com/android/server/credentials/ProviderSession.java5
-rw-r--r--services/credentials/java/com/android/server/credentials/RequestSession.java58
-rw-r--r--services/credentials/java/com/android/server/credentials/metrics/ApiName.java48
-rw-r--r--services/credentials/java/com/android/server/credentials/metrics/ApiStatus.java46
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java20
-rw-r--r--services/incremental/TEST_MAPPING6
-rw-r--r--services/robotests/src/com/android/server/media/AudioPoliciesBluetoothRouteControllerTest.java293
-rw-r--r--services/tests/InputMethodSystemServerTests/Android.bp4
-rw-r--r--services/tests/InputMethodSystemServerTests/AndroidTest.xml1
-rw-r--r--services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceRestrictImeAmountTest.java159
-rw-r--r--services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java4
-rw-r--r--services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/SwitchKeyboardLayoutTest.java39
-rw-r--r--services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java24
-rw-r--r--services/tests/mockingservicestests/src/android/hardware/face/FaceManagerTest.java86
-rw-r--r--services/tests/mockingservicestests/src/android/hardware/fingerprint/FingerprintManagerTest.java88
-rw-r--r--services/tests/mockingservicestests/src/android/hardware/fingerprint/OWNERS2
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java148
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/ExpectableTestCase.java181
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/ExtendedMockitoRule.java183
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/ExtendedMockitoTestCase.java249
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/Visitor.java23
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java28
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceInjectorTest.java14
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java54
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java39
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java53
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/cpu/CpuInfoReaderTest.java8
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/cpu/CpuMonitorServiceTest.java14
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java25
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java26
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java1
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/job/JobNotificationCoordinatorTest.java82
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java66
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java2
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java4
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java21
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUPANDTest.java10
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java57
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorVisibleBackgroundUserTestCase.java101
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/utils/SlogfTest.java155
-rw-r--r--services/tests/servicestests/Android.bp2
-rw-r--r--services/tests/servicestests/AndroidTest.xml2
-rw-r--r--services/tests/servicestests/data/broken_shortcut.xmlbin0 -> 851 bytes
-rw-r--r--services/tests/servicestests/res/xml/irq_device_map_3.xml2
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java35
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java87
-rw-r--r--services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java28
-rw-r--r--services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/am/OomAdjusterTests.java56
-rw-r--r--services/tests/servicestests/src/com/android/server/am/UidObserverControllerTest.java6
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java189
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java15
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceDetectClientTest.java10
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/BiometricStateCallbackTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceTest.java151
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java12
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClientTest.java10
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java10
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClientTest.java3
-rw-r--r--services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/companion/virtual/SensorControllerTest.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java286
-rw-r--r--services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceTest.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java3
-rw-r--r--services/tests/servicestests/src/com/android/server/credentials/CredentialDescriptionRegistryTest.java197
-rw-r--r--services/tests/servicestests/src/com/android/server/credentials/OWNERS1
-rw-r--r--services/tests/servicestests/src/com/android/server/display/BrightnessThrottlerTest.java1
-rw-r--r--services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java11
-rw-r--r--services/tests/servicestests/src/com/android/server/display/DeviceStateToLayoutMapTest.java33
-rw-r--r--services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java57
-rw-r--r--services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java43
-rw-r--r--services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java8
-rw-r--r--services/tests/servicestests/src/com/android/server/display/color/ColorDisplayServiceTest.java7
-rw-r--r--services/tests/servicestests/src/com/android/server/display/mode/DisplayModeDirectorTest.java (renamed from services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java)53
-rw-r--r--services/tests/servicestests/src/com/android/server/display/mode/SkinThermalStatusObserverTest.java247
-rw-r--r--services/tests/servicestests/src/com/android/server/input/KeyboardLayoutManagerTests.kt4
-rw-r--r--services/tests/servicestests/src/com/android/server/job/PendingJobQueueTest.java14
-rw-r--r--services/tests/servicestests/src/com/android/server/location/contexthub/ContextHubServiceTest.java35
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java5
-rw-r--r--services/tests/servicestests/src/com/android/server/media/LegacyDeviceRouteControllerTest.java371
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java165
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/UserManagerServiceShellCommandTest.java27
-rw-r--r--services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java15
-rw-r--r--services/tests/servicestests/src/com/android/server/power/stats/CpuWakeupStatsTest.java89
-rw-r--r--services/tests/servicestests/src/com/android/server/power/stats/MockBatteryStatsImpl.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/timedetector/NetworkTimeUpdateServiceTest.java169
-rw-r--r--services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java47
-rw-r--r--services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java2
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java54
-rwxr-xr-xservices/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java89
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java57
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java163
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java14
-rw-r--r--services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java22
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java28
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java39
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java80
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java13
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java1
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java15
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java176
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java1
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskTests.java28
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java25
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TransitionTests.java17
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java10
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java8
-rw-r--r--services/usage/java/com/android/server/usage/TEST_MAPPING4
-rw-r--r--services/usb/java/com/android/server/usb/UsbDirectMidiDevice.java317
-rw-r--r--services/usb/java/com/android/server/usb/UsbMidiPacketConverter.java142
-rw-r--r--services/usb/java/com/android/server/usb/descriptors/UsbEndpointDescriptor.java2
-rw-r--r--services/voiceinteraction/TEST_MAPPING2
-rw-r--r--services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLogging.java13
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java65
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/DspTrustedHotwordDetectorSession.java65
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java23
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/SoftwareTrustedHotwordDetectorSession.java52
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VisualQueryDetectorSession.java7
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java14
-rw-r--r--telecomm/java/android/telecom/CallControl.java86
-rw-r--r--telecomm/java/android/telecom/CallControlCallback.java23
-rw-r--r--telecomm/java/android/telecom/CallEventCallback.java17
-rw-r--r--telecomm/java/android/telecom/PhoneAccount.java6
-rw-r--r--telecomm/java/android/telecom/TelecomManager.java19
-rw-r--r--telecomm/java/com/android/internal/telecom/ClientTransactionalServiceWrapper.java56
-rw-r--r--telecomm/java/com/android/internal/telecom/ICallControl.aidl3
-rw-r--r--telecomm/java/com/android/internal/telecom/ICallEventCallback.aidl7
-rw-r--r--telephony/java/android/service/euicc/EuiccProfileInfo.java3
-rw-r--r--telephony/java/android/telephony/CarrierConfigManager.java5
-rw-r--r--telephony/java/android/telephony/DomainSelectionService.java9
-rw-r--r--telephony/java/android/telephony/PhoneNumberUtils.java4
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java11
-rw-r--r--telephony/java/android/telephony/TransportSelectorCallback.java4
-rw-r--r--telephony/java/android/telephony/WwanSelectorCallback.java3
-rwxr-xr-xtelephony/java/android/telephony/ims/ImsCallSession.java3
-rw-r--r--telephony/java/android/telephony/ims/feature/ImsFeature.java4
-rw-r--r--telephony/java/android/telephony/satellite/SatelliteManager.java72
-rw-r--r--telephony/java/android/telephony/satellite/stub/ISatellite.aidl7
-rw-r--r--telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl6
-rw-r--r--telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java18
-rw-r--r--telephony/java/android/telephony/satellite/stub/SatelliteModemState.aidl4
-rw-r--r--telephony/java/android/telephony/satellite/stub/SatelliteService.java7
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl5
-rw-r--r--telephony/java/com/android/internal/telephony/ITransportSelectorCallback.aidl2
-rw-r--r--telephony/java/com/android/internal/telephony/IWwanSelectorCallback.aidl2
-rw-r--r--test-mock/api/current.txt1
-rw-r--r--tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java3
-rw-r--r--tests/EnforcePermission/OWNERS3
-rw-r--r--tests/FlickerTests/Android.bp7
-rw-r--r--tests/FlickerTests/AndroidTest.xml4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt6
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt22
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/ActivityEmbeddingTestBase.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingPlaceholderSplitTest.kt8
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingSecondaryToSplitTest.kt18
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt10
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTestCfArm.kt8
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt10
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTestCfArm.kt8
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt8
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt10
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/AppPairsHelper.kt3
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/AssistantAppHelper.kt7
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FixedOrientationAppHelper.kt5
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerExtensions.kt8
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt7
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt8
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeEditorPopupDialogAppHelper.kt7
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeShownOnAppStartHelper.kt25
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeStateInitializeHelper.kt5
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/LaunchBubbleHelper.kt3
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MailAppHelper.kt6
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MultiWindowUtils.kt3
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NewTasksAppHelper.kt8
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NonResizeableAppHelper.kt5
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt8
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt34
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SeamlessRotationAppHelper.kt5
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt5
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SimpleAppHelper.kt5
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/TwoActivitiesAppHelper.kt8
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt20
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt14
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTestCfArm.kt4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt14
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTestCfArm.kt4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt14
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTestCfArm.kt4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt10
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTestCfArm.kt4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt14
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTestCfArm.kt4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToFixedPortraitAppTest.kt22
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest.kt18
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTestCfArm.kt4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt16
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt21
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTestCfArm.kt4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTestShellTransit.kt6
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt18
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnStartWhenLaunchingAppCfArmTest.kt4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt12
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTestCfArm.kt4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt16
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt20
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTestCfArm.kt4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt12
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTestCfArm.kt6
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTest.kt10
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdFromIcon.kt17
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt12
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLauncherTransition.kt4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt24
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt24
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt15
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt6
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt10
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt12
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt14
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTestCfArm.kt8
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt17
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTransition.kt10
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt10
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenCameraOnDoubleClickPowerButton.kt19
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt25
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt26
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt18
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTestCfArm.kt13
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt6
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt18
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTestCfArm.kt13
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest_ShellTransit.kt6
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt21
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTestCfArm.kt13
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt10
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTestCfArm.kt6
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt8
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt24
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTestCfArm.kt6
-rw-r--r--tests/FlickerTests/test-apps/flickerapp/Android.bp1
-rw-r--r--tests/Input/src/com/android/test/input/MotionPredictorTest.kt10
-rw-r--r--tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/NotificationTest.java13
-rw-r--r--tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java14
-rw-r--r--tests/MidiTests/Android.bp40
-rw-r--r--tests/MidiTests/AndroidManifest.xml30
-rw-r--r--tests/MidiTests/AndroidTest.xml30
-rw-r--r--tests/MidiTests/OWNERS1
-rw-r--r--tests/MidiTests/TEST_MAPPING7
-rw-r--r--tests/MidiTests/src/com/android/server/midi/MidiEventMultiSchedulerTest.java342
-rw-r--r--tests/MotionPrediction/src/test/motionprediction/DrawingView.kt4
-rw-r--r--tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapImage.kt34
-rw-r--r--tests/SurfaceViewBufferTests/src/com/android/test/BufferPresentationTests.kt4
-rw-r--r--tests/SurfaceViewBufferTests/src/com/android/test/BufferRejectionTests.kt23
-rw-r--r--tests/SurfaceViewBufferTests/src/com/android/test/GeometryTests.kt9
-rw-r--r--tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt9
-rw-r--r--tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeTests.kt4
-rw-r--r--tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt19
-rw-r--r--tests/SurfaceViewBufferTests/src/com/android/test/SurfaceViewBufferTestBase.kt8
-rw-r--r--tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt24
-rw-r--r--tests/UsbTests/src/com/android/server/usb/UsbMidiPacketConverterTest.java407
-rw-r--r--tools/aapt2/Android.mk2
-rw-r--r--wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetwork.aidl (renamed from wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl)2
-rw-r--r--wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetwork.java (renamed from wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetwork.java)143
-rw-r--r--wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatus.aidl (renamed from wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatus.aidl)2
-rw-r--r--wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatus.java (renamed from wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatus.java)101
-rw-r--r--wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetwork.java111
-rw-r--r--wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatus.java8
-rw-r--r--wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.aidl (renamed from wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetwork.aidl)2
-rw-r--r--wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.java (renamed from wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.java)75
-rw-r--r--wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityClientCallback.java15
-rw-r--r--wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java196
-rw-r--r--wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityCallback.aidl8
-rw-r--r--wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityService.aidl14
-rw-r--r--wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java360
-rw-r--r--wifi/tests/src/android/net/wifi/sharedconnectivity/app/DeviceInfoTest.java116
-rw-r--r--wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatusTest.java139
-rw-r--r--wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkTest.java157
-rw-r--r--wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatusTest.java49
-rw-r--r--wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkTest.java71
-rw-r--r--wifi/tests/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfoTest.java123
-rw-r--r--wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManagerTest.java314
-rw-r--r--wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivitySettingsStateTest.java23
-rw-r--r--wifi/tests/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatusTest.java128
-rw-r--r--wifi/tests/src/android/net/wifi/sharedconnectivity/app/TetherNetworkTest.java139
-rw-r--r--wifi/tests/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityServiceTest.java124
2345 files changed, 54331 insertions, 27831 deletions
diff --git a/apct-tests/perftests/core/OWNERS b/apct-tests/perftests/core/OWNERS
index 8fb057ddcbce..6abab6e27f8e 100644
--- a/apct-tests/perftests/core/OWNERS
+++ b/apct-tests/perftests/core/OWNERS
@@ -3,4 +3,12 @@ include /graphics/java/android/graphics/fonts/OWNERS
# Bug component: 568761
per-file /apct-tests/perftests/core/res/* = felkachang@google.com,zyy@google.com
+per-file /apct-tests/perftests/core/res/* = file:/core/java/android/content/om/OWNERS
+per-file /apct-tests/perftests/core/src/android/content/res/* = felkachang@google.com
+per-file /apct-tests/perftests/core/src/android/content/res/* = file:/core/java/android/content/res/OWNERS
+
+
+# Bug component: 568631
+per-file /apct-tests/perftests/core/src/android/content/om/* = felkachang@google.com
+per-file /apct-tests/perftests/core/src/android/content/om/* = file:/core/java/android/content/om/OWNERS
diff --git a/apct-tests/perftests/core/src/android/input/MotionPredictorBenchmark.kt b/apct-tests/perftests/core/src/android/input/MotionPredictorBenchmark.kt
index fabf8892b544..9482591c65b5 100644
--- a/apct-tests/perftests/core/src/android/input/MotionPredictorBenchmark.kt
+++ b/apct-tests/perftests/core/src/android/input/MotionPredictorBenchmark.kt
@@ -33,7 +33,6 @@ import androidx.test.filters.LargeTest
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.After
-import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Rule
@@ -132,8 +131,7 @@ class MotionPredictorBenchmark {
predictor.record(moveEvent)
val predictionTime = eventTime + eventInterval
val predicted = predictor.predict(predictionTime.toNanos())
- assertEquals(1, predicted.size)
- assertTrue(predicted[0].eventTime <= (predictionTime + offset).toMillis())
+ assertTrue(predicted.eventTime <= (predictionTime + offset).toMillis())
}
}
diff --git a/apct-tests/perftests/settingsprovider/src/android/provider/SettingsProviderPerfTest.java b/apct-tests/perftests/settingsprovider/src/android/provider/SettingsProviderPerfTest.java
index e31162f37cf8..c00c8d550885 100644
--- a/apct-tests/perftests/settingsprovider/src/android/provider/SettingsProviderPerfTest.java
+++ b/apct-tests/perftests/settingsprovider/src/android/provider/SettingsProviderPerfTest.java
@@ -39,6 +39,7 @@ public final class SettingsProviderPerfTest {
private static final String NAMESPACE = "test@namespace";
private static final String SETTING_NAME1 = "test:setting1";
private static final String SETTING_NAME2 = "test-setting2";
+ private static final String UNSET_SETTING = "test_unset_setting";
private final ContentResolver mContentResolver;
@@ -93,6 +94,14 @@ public final class SettingsProviderPerfTest {
}
@Test
+ public void testSettingsValueConsecutiveReadUnset() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Settings.Secure.getString(mContentResolver, UNSET_SETTING);
+ }
+ }
+
+ @Test
public void testSettingsNamespaceConsecutiveRead() {
final List<String> names = new ArrayList<>();
names.add(SETTING_NAME1);
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
index 11c13c413ced..7f02cb36dfc1 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
@@ -397,18 +397,11 @@ public class JobInfo implements Parcelable {
public static final int FLAG_EXPEDITED = 1 << 4;
/**
- * Whether it's a data transfer job or not.
- *
- * @hide
- */
- public static final int FLAG_DATA_TRANSFER = 1 << 5;
-
- /**
* Whether it's a user initiated job or not.
*
* @hide
*/
- public static final int FLAG_USER_INITIATED = 1 << 6;
+ public static final int FLAG_USER_INITIATED = 1 << 5;
/**
* @hide
@@ -738,13 +731,6 @@ public class JobInfo implements Parcelable {
}
/**
- * @see JobInfo.Builder#setDataTransfer(boolean)
- */
- public boolean isDataTransfer() {
- return (flags & FLAG_DATA_TRANSFER) != 0;
- }
-
- /**
* @see JobInfo.Builder#setUserInitiated(boolean)
*/
public boolean isUserInitiated() {
@@ -1447,7 +1433,6 @@ public class JobInfo implements Parcelable {
* reasonable estimates should use the sentinel value
* {@link JobInfo#NETWORK_BYTES_UNKNOWN}.
* </ul>
- * TODO(255371817): update documentation to reflect how this data will be used
* Note that the system may choose to delay jobs with large network
* usage estimates when the device has a poor network connection, in
* order to save battery and possible network costs.
@@ -1478,6 +1463,7 @@ public class JobInfo implements Parcelable {
* @see JobInfo#getEstimatedNetworkUploadBytes()
* @see JobWorkItem#JobWorkItem(android.content.Intent, long, long)
*/
+ // TODO(b/255371817): update documentation to reflect how this data will be used
public Builder setEstimatedNetworkBytes(@BytesLong long downloadBytes,
@BytesLong long uploadBytes) {
mNetworkDownloadBytes = downloadBytes;
@@ -1850,39 +1836,6 @@ public class JobInfo implements Parcelable {
}
/**
- * Indicates that this job will be used to transfer data to or from a remote server. The
- * system could attempt to run a data transfer job longer than a regular job if the data
- * being transferred is potentially very large and can take a long time to complete.
- *
- * <p>
- * You must provide an estimate of the payload size via
- * {@link #setEstimatedNetworkBytes(long, long)} when scheduling the job or use
- * {@link JobService#updateEstimatedNetworkBytes(JobParameters, long, long)} or
- * {@link JobService#updateEstimatedNetworkBytes(JobParameters, JobWorkItem, long, long)}
- * shortly after the job starts.
- *
- * <p>
- * For user-initiated transfers that must be started immediately, call
- * {@link #setUserInitiated(boolean) setUserInitiated(true)}. Otherwise, the system may
- * defer the job to a more opportune time.
- *
- * <p>
- * If you want to perform more than one data transfer job, consider enqueuing multiple
- * {@link JobWorkItem JobWorkItems} along with {@link #setDataTransfer(boolean)}.
- *
- * @see JobInfo#isDataTransfer()
- */
- @NonNull
- public Builder setDataTransfer(boolean dataTransfer) {
- if (dataTransfer) {
- mFlags |= FLAG_DATA_TRANSFER;
- } else {
- mFlags &= (~FLAG_DATA_TRANSFER);
- }
- return this;
- }
-
- /**
* Indicates that this job is being scheduled to fulfill an explicit user request.
* As such, user-initiated jobs can only be scheduled when the app is in the foreground
* or in a state where launching an activity is allowed, as defined
@@ -1909,6 +1862,11 @@ public class JobInfo implements Parcelable {
* {@link SecurityException}.
*
* <p>
+ * In {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, user-initiated jobs can only
+ * be used for network data transfers. As such, they must specify a required network via
+ * {@link #setRequiredNetwork(NetworkRequest)} or {@link #setRequiredNetworkType(int)}.
+ *
+ * <p>
* These jobs will not be subject to quotas and will be started immediately once scheduled
* if all constraints are met and the device system health allows for additional tasks.
*
@@ -2179,10 +2137,6 @@ public class JobInfo implements Parcelable {
if (isPeriodic) {
throw new IllegalArgumentException("An expedited job cannot be periodic");
}
- if ((flags & FLAG_DATA_TRANSFER) != 0) {
- throw new IllegalArgumentException(
- "An expedited job cannot also be a data transfer job");
- }
if (isUserInitiated) {
throw new IllegalArgumentException("An expedited job cannot be user-initiated");
}
@@ -2202,24 +2156,6 @@ public class JobInfo implements Parcelable {
}
}
- if ((flags & FLAG_DATA_TRANSFER) != 0) {
- if (backoffPolicy == BACKOFF_POLICY_LINEAR) {
- throw new IllegalArgumentException(
- "A data transfer job cannot have a linear backoff policy.");
- }
- if (hasLateConstraint) {
- throw new IllegalArgumentException("A data transfer job cannot have a deadline");
- }
- if ((flags & FLAG_PREFETCH) != 0) {
- throw new IllegalArgumentException(
- "A data transfer job cannot also be a prefetch job");
- }
- if (networkRequest == null) {
- throw new IllegalArgumentException(
- "A data transfer job must specify a valid network type");
- }
- }
-
if (isUserInitiated) {
if (hasEarlyConstraint) {
throw new IllegalArgumentException("A user-initiated job cannot have a time delay");
@@ -2245,6 +2181,15 @@ public class JobInfo implements Parcelable {
throw new IllegalArgumentException(
"Can't call addTriggerContentUri() on a user-initiated job");
}
+ // UIDTs
+ if (networkRequest == null) {
+ throw new IllegalArgumentException(
+ "A user-initaited data transfer job must specify a valid network type");
+ }
+ if (backoffPolicy == BACKOFF_POLICY_LINEAR) {
+ throw new IllegalArgumentException(
+ "A user-initiated data transfer job cannot have a linear backoff policy.");
+ }
}
}
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobParameters.java b/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
index 242b52c5845b..32502eddc9f8 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
@@ -19,6 +19,7 @@ package android.app.job;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.TestApi;
import android.app.ActivityManager;
import android.app.usage.UsageStatsManager;
import android.compat.annotation.UnsupportedAppUsage;
@@ -102,6 +103,7 @@ public class JobParameters implements Parcelable {
* The user stopped the job via some UI (eg. Task Manager).
* @hide
*/
+ @TestApi
public static final int INTERNAL_STOP_REASON_USER_UI_STOP =
JobProtoEnums.INTERNAL_STOP_REASON_USER_UI_STOP; // 11.
/**
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
index 4caaa09f6a31..79a26597ed24 100644
--- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
@@ -79,6 +79,9 @@ import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
import android.provider.DeviceConfig;
+import android.telephony.TelephonyCallback;
+import android.telephony.TelephonyManager;
+import android.telephony.emergency.EmergencyNumber;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
@@ -146,15 +149,17 @@ import java.util.stream.Collectors;
label="deep";
STATE_ACTIVE [
- label="STATE_ACTIVE\nScreen on OR Charging OR Alarm going off soon",
+ label="STATE_ACTIVE\nScreen on OR charging OR alarm going off soon\n"
+ + "OR active emergency call",
color=black,shape=diamond
]
STATE_INACTIVE [
- label="STATE_INACTIVE\nScreen off AND Not charging",color=black,shape=diamond
+ label="STATE_INACTIVE\nScreen off AND not charging AND no active emergency call",
+ color=black,shape=diamond
]
STATE_QUICK_DOZE_DELAY [
label="STATE_QUICK_DOZE_DELAY\n"
- + "Screen off AND Not charging\n"
+ + "Screen off AND not charging AND no active emergency call\n"
+ "Location, motion detection, and significant motion monitoring turned off",
color=black,shape=diamond
]
@@ -237,11 +242,12 @@ import java.util.stream.Collectors;
label="light"
LIGHT_STATE_ACTIVE [
- label="LIGHT_STATE_ACTIVE\nScreen on OR Charging OR Alarm going off soon",
+ label="LIGHT_STATE_ACTIVE\n"
+ + "Screen on OR charging OR alarm going off soon OR active emergency call",
color=black,shape=diamond
]
LIGHT_STATE_INACTIVE [
- label="LIGHT_STATE_INACTIVE\nScreen off AND Not charging",
+ label="LIGHT_STATE_INACTIVE\nScreen off AND not charging AND no active emergency call",
color=black,shape=diamond
]
LIGHT_STATE_IDLE [label="LIGHT_STATE_IDLE\n",color=red,shape=box]
@@ -411,6 +417,7 @@ public class DeviceIdleController extends SystemService
private static final int ACTIVE_REASON_FROM_BINDER_CALL = 5;
private static final int ACTIVE_REASON_FORCED = 6;
private static final int ACTIVE_REASON_ALARM = 7;
+ private static final int ACTIVE_REASON_EMERGENCY_CALL = 8;
@VisibleForTesting
static final int SET_IDLE_FACTOR_RESULT_UNINIT = -1;
@VisibleForTesting
@@ -765,6 +772,8 @@ public class DeviceIdleController extends SystemService
}
};
+ private final EmergencyCallListener mEmergencyCallListener = new EmergencyCallListener();
+
/** Post stationary status only to this listener. */
private void postStationaryStatus(DeviceIdleInternal.StationaryListener listener) {
mHandler.obtainMessage(MSG_REPORT_STATIONARY_STATUS, listener).sendToTarget();
@@ -2323,6 +2332,39 @@ public class DeviceIdleController extends SystemService
}
}
+ private class EmergencyCallListener extends TelephonyCallback implements
+ TelephonyCallback.OutgoingEmergencyCallListener,
+ TelephonyCallback.CallStateListener {
+ private volatile boolean mIsEmergencyCallActive;
+
+ @Override
+ public void onOutgoingEmergencyCall(EmergencyNumber placedEmergencyNumber,
+ int subscriptionId) {
+ mIsEmergencyCallActive = true;
+ if (DEBUG) Slog.d(TAG, "onOutgoingEmergencyCall(): subId = " + subscriptionId);
+ synchronized (DeviceIdleController.this) {
+ mActiveReason = ACTIVE_REASON_EMERGENCY_CALL;
+ becomeActiveLocked("emergency call", Process.myUid());
+ }
+ }
+
+ @Override
+ public void onCallStateChanged(int state) {
+ if (DEBUG) Slog.d(TAG, "onCallStateChanged(): state is " + state);
+ // An emergency call just finished
+ if (state == TelephonyManager.CALL_STATE_IDLE && mIsEmergencyCallActive) {
+ mIsEmergencyCallActive = false;
+ synchronized (DeviceIdleController.this) {
+ becomeInactiveIfAppropriateLocked();
+ }
+ }
+ }
+
+ boolean isEmergencyCallActive() {
+ return mIsEmergencyCallActive;
+ }
+ }
+
static class Injector {
private final Context mContext;
private ConnectivityManager mConnectivityManager;
@@ -2406,6 +2448,10 @@ public class DeviceIdleController extends SystemService
return mContext.getSystemService(SensorManager.class);
}
+ TelephonyManager getTelephonyManager() {
+ return mContext.getSystemService(TelephonyManager.class);
+ }
+
ConstraintController getConstraintController(Handler handler,
DeviceIdleInternal localService) {
if (mContext.getPackageManager()
@@ -2634,6 +2680,9 @@ public class DeviceIdleController extends SystemService
mLocalActivityTaskManager.registerScreenObserver(mScreenObserver);
+ mInjector.getTelephonyManager().registerTelephonyCallback(
+ JobSchedulerBackgroundThread.getExecutor(), mEmergencyCallListener);
+
passWhiteListsToForceAppStandbyTrackerLocked();
updateInteractivityLocked();
}
@@ -3435,6 +3484,7 @@ public class DeviceIdleController extends SystemService
final boolean isScreenBlockingInactive =
mScreenOn && (!mConstants.WAIT_FOR_UNLOCK || !mScreenLocked);
+ final boolean isEmergencyCallActive = mEmergencyCallListener.isEmergencyCallActive();
if (DEBUG) {
Slog.d(TAG, "becomeInactiveIfAppropriateLocked():"
+ " isScreenBlockingInactive=" + isScreenBlockingInactive
@@ -3442,10 +3492,11 @@ public class DeviceIdleController extends SystemService
+ ", WAIT_FOR_UNLOCK=" + mConstants.WAIT_FOR_UNLOCK
+ ", mScreenLocked=" + mScreenLocked + ")"
+ " mCharging=" + mCharging
+ + " emergencyCall=" + isEmergencyCallActive
+ " mForceIdle=" + mForceIdle
);
}
- if (!mForceIdle && (mCharging || isScreenBlockingInactive)) {
+ if (!mForceIdle && (mCharging || isScreenBlockingInactive || isEmergencyCallActive)) {
return;
}
// Become inactive and determine if we will ultimately go idle.
@@ -3568,6 +3619,17 @@ public class DeviceIdleController extends SystemService
}
EventLogTags.writeDeviceIdleLightStep();
+ if (mEmergencyCallListener.isEmergencyCallActive()) {
+ // The emergency call should have raised the state to ACTIVE and kept it there,
+ // so this method shouldn't be called. Don't proceed further.
+ Slog.wtf(TAG, "stepLightIdleStateLocked called when emergency call is active");
+ if (mLightState != LIGHT_STATE_ACTIVE) {
+ mActiveReason = ACTIVE_REASON_EMERGENCY_CALL;
+ becomeActiveLocked("emergency", Process.myUid());
+ }
+ return;
+ }
+
switch (mLightState) {
case LIGHT_STATE_INACTIVE:
mCurLightIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET;
@@ -3650,6 +3712,17 @@ public class DeviceIdleController extends SystemService
if (DEBUG) Slog.d(TAG, "stepIdleStateLocked: mState=" + mState);
EventLogTags.writeDeviceIdleStep();
+ if (mEmergencyCallListener.isEmergencyCallActive()) {
+ // The emergency call should have raised the state to ACTIVE and kept it there,
+ // so this method shouldn't be called. Don't proceed further.
+ Slog.wtf(TAG, "stepIdleStateLocked called when emergency call is active");
+ if (mState != STATE_ACTIVE) {
+ mActiveReason = ACTIVE_REASON_EMERGENCY_CALL;
+ becomeActiveLocked("emergency", Process.myUid());
+ }
+ return;
+ }
+
if (isUpcomingAlarmClock()) {
// Whoops, there is an upcoming alarm. We don't actually want to go idle.
if (mState != STATE_ACTIVE) {
@@ -3984,6 +4057,11 @@ public class DeviceIdleController extends SystemService
}
}
+ @VisibleForTesting
+ boolean isEmergencyCallActive() {
+ return mEmergencyCallListener.isEmergencyCallActive();
+ }
+
@GuardedBy("this")
boolean isOpsInactiveLocked() {
return mActiveIdleOpCount <= 0 && !mJobsActive && !mAlarmsActive;
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobNotificationCoordinator.java b/apex/jobscheduler/service/java/com/android/server/job/JobNotificationCoordinator.java
index ce5ade5531ec..5a1214296526 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobNotificationCoordinator.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobNotificationCoordinator.java
@@ -21,6 +21,7 @@ import static android.app.job.JobService.JOB_END_NOTIFICATION_POLICY_REMOVE;
import android.annotation.NonNull;
import android.app.Notification;
+import android.app.job.JobParameters;
import android.app.job.JobService;
import android.content.pm.UserPackage;
import android.os.UserHandle;
@@ -80,7 +81,7 @@ class JobNotificationCoordinator {
final NotificationDetails oldDetails = mNotificationDetails.get(hostingContext);
if (oldDetails != null && oldDetails.notificationId != notificationId) {
// App is switching notification IDs. Remove association with the old one.
- removeNotificationAssociation(hostingContext);
+ removeNotificationAssociation(hostingContext, JobParameters.STOP_REASON_UNDEFINED);
}
final int userId = UserHandle.getUserId(callingUid);
// TODO(260848384): ensure apps can't cancel the notification for user-initiated job
@@ -100,7 +101,8 @@ class JobNotificationCoordinator {
mNotificationDetails.put(hostingContext, details);
}
- void removeNotificationAssociation(@NonNull JobServiceContext hostingContext) {
+ void removeNotificationAssociation(@NonNull JobServiceContext hostingContext,
+ @JobParameters.StopReason int stopReason) {
final NotificationDetails details = mNotificationDetails.remove(hostingContext);
if (details == null) {
return;
@@ -114,7 +116,10 @@ class JobNotificationCoordinator {
ArraySet<JobServiceContext> associatedContexts = associations.get(details.notificationId);
if (associatedContexts == null || associatedContexts.isEmpty()) {
// No more jobs using this notification. Apply the final job stop policy.
- if (details.jobEndNotificationPolicy == JOB_END_NOTIFICATION_POLICY_REMOVE) {
+ // If the user attempted to stop the job/app, then always remove the notification
+ // so the user doesn't get confused about the app state.
+ if (details.jobEndNotificationPolicy == JOB_END_NOTIFICATION_POLICY_REMOVE
+ || stopReason == JobParameters.STOP_REASON_USER) {
final String packageName = details.userPackage.packageName;
mNotificationManagerInternal.cancelNotification(
packageName, packageName, details.appUid, details.appPid, /* tag */ null,
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index 4088a4832f96..0af191af2a21 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -478,8 +478,6 @@ public class JobSchedulerService extends com.android.server.SystemService
case Constants.KEY_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS:
case Constants.KEY_RUNTIME_MIN_GUARANTEE_MS:
case Constants.KEY_RUNTIME_MIN_EJ_GUARANTEE_MS:
- case Constants.KEY_RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS:
- case Constants.KEY_RUNTIME_DATA_TRANSFER_LIMIT_MS:
case Constants.KEY_RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS:
case Constants.KEY_RUNTIME_USER_INITIATED_LIMIT_MS:
case Constants.KEY_RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_BUFFER_FACTOR:
@@ -574,10 +572,6 @@ public class JobSchedulerService extends com.android.server.SystemService
"runtime_free_quota_max_limit_ms";
private static final String KEY_RUNTIME_MIN_GUARANTEE_MS = "runtime_min_guarantee_ms";
private static final String KEY_RUNTIME_MIN_EJ_GUARANTEE_MS = "runtime_min_ej_guarantee_ms";
- private static final String KEY_RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS =
- "runtime_min_data_transfer_guarantee_ms";
- private static final String KEY_RUNTIME_DATA_TRANSFER_LIMIT_MS =
- "runtime_data_transfer_limit_ms";
private static final String KEY_RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS =
"runtime_min_user_initiated_guarantee_ms";
private static final String KEY_RUNTIME_USER_INITIATED_LIMIT_MS =
@@ -616,10 +610,6 @@ public class JobSchedulerService extends com.android.server.SystemService
public static final long DEFAULT_RUNTIME_MIN_GUARANTEE_MS = 10 * MINUTE_IN_MILLIS;
@VisibleForTesting
public static final long DEFAULT_RUNTIME_MIN_EJ_GUARANTEE_MS = 3 * MINUTE_IN_MILLIS;
- public static final long DEFAULT_RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS =
- DEFAULT_RUNTIME_MIN_GUARANTEE_MS;
- public static final long DEFAULT_RUNTIME_DATA_TRANSFER_LIMIT_MS =
- DEFAULT_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS;
public static final long DEFAULT_RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS =
Math.max(10 * MINUTE_IN_MILLIS, DEFAULT_RUNTIME_MIN_GUARANTEE_MS);
public static final long DEFAULT_RUNTIME_USER_INITIATED_LIMIT_MS =
@@ -739,18 +729,6 @@ public class JobSchedulerService extends com.android.server.SystemService
public long RUNTIME_MIN_EJ_GUARANTEE_MS = DEFAULT_RUNTIME_MIN_EJ_GUARANTEE_MS;
/**
- * The minimum amount of time we try to guarantee normal data transfer jobs will run for.
- */
- public long RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS =
- DEFAULT_RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS;
-
- /**
- * The maximum amount of time we will let a normal data transfer job run for. This will only
- * apply if there are no other limits that apply to the specific data transfer job.
- */
- public long RUNTIME_DATA_TRANSFER_LIMIT_MS = DEFAULT_RUNTIME_DATA_TRANSFER_LIMIT_MS;
-
- /**
* The minimum amount of time we try to guarantee normal user-initiated jobs will run for.
*/
public long RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS =
@@ -885,8 +863,6 @@ public class JobSchedulerService extends com.android.server.SystemService
KEY_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
KEY_RUNTIME_MIN_GUARANTEE_MS, KEY_RUNTIME_MIN_EJ_GUARANTEE_MS,
KEY_RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_BUFFER_FACTOR,
- KEY_RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS,
- KEY_RUNTIME_DATA_TRANSFER_LIMIT_MS,
KEY_RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS,
KEY_RUNTIME_USER_INITIATED_LIMIT_MS,
KEY_RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_MS,
@@ -904,17 +880,6 @@ public class JobSchedulerService extends com.android.server.SystemService
properties.getLong(KEY_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
DEFAULT_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS));
// Make sure min runtime is at least as long as regular jobs.
- RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS = Math.max(RUNTIME_MIN_GUARANTEE_MS,
- properties.getLong(
- KEY_RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS,
- DEFAULT_RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS));
- // Max limit should be at least the min guarantee AND the free quota.
- RUNTIME_DATA_TRANSFER_LIMIT_MS = Math.max(RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
- Math.max(RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS,
- properties.getLong(
- KEY_RUNTIME_DATA_TRANSFER_LIMIT_MS,
- DEFAULT_RUNTIME_DATA_TRANSFER_LIMIT_MS)));
- // Make sure min runtime is at least as long as regular jobs.
RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS = Math.max(RUNTIME_MIN_GUARANTEE_MS,
properties.getLong(
KEY_RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS,
@@ -993,10 +958,6 @@ public class JobSchedulerService extends com.android.server.SystemService
pw.print(KEY_RUNTIME_MIN_EJ_GUARANTEE_MS, RUNTIME_MIN_EJ_GUARANTEE_MS).println();
pw.print(KEY_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS, RUNTIME_FREE_QUOTA_MAX_LIMIT_MS)
.println();
- pw.print(KEY_RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS,
- RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS).println();
- pw.print(KEY_RUNTIME_DATA_TRANSFER_LIMIT_MS,
- RUNTIME_DATA_TRANSFER_LIMIT_MS).println();
pw.print(KEY_RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS,
RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS).println();
pw.print(KEY_RUNTIME_USER_INITIATED_LIMIT_MS,
@@ -1476,7 +1437,8 @@ public class JobSchedulerService extends com.android.server.SystemService
/* timingDelayConstraintSatisfied */ false,
/* isDeviceIdle */ false,
/* hasConnectivityConstraintSatisfied */ false,
- /* hasContentTriggerConstraintSatisfied */ false);
+ /* hasContentTriggerConstraintSatisfied */ false,
+ 0);
// If the job is immediately ready to run, then we can just immediately
// put it in the pending list and try to schedule it. This is especially
@@ -1894,7 +1856,8 @@ public class JobSchedulerService extends com.android.server.SystemService
cancelled.isConstraintSatisfied(JobStatus.CONSTRAINT_TIMING_DELAY),
cancelled.isConstraintSatisfied(JobInfo.CONSTRAINT_FLAG_DEVICE_IDLE),
cancelled.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY),
- cancelled.isConstraintSatisfied(JobStatus.CONSTRAINT_CONTENT_TRIGGER));
+ cancelled.isConstraintSatisfied(JobStatus.CONSTRAINT_CONTENT_TRIGGER),
+ 0);
}
// If this is a replacement, bring in the new version of the job
if (incomingJob != null) {
@@ -3289,7 +3252,7 @@ public class JobSchedulerService extends com.android.server.SystemService
if (job.shouldTreatAsUserInitiatedJob()
&& checkRunUserInitiatedJobsPermission(
job.getSourceUid(), job.getSourcePackageName())) {
- if (job.getJob().isDataTransfer()) {
+ if (job.getJob().getRequiredNetwork() != null) { // UI+DT
final long estimatedTransferTimeMs =
mConnectivityController.getEstimatedTransferTimeMs(job);
if (estimatedTransferTimeMs == ConnectivityController.UNKNOWN_TIME) {
@@ -3306,9 +3269,6 @@ public class JobSchedulerService extends com.android.server.SystemService
));
}
return mConstants.RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS;
- } else if (job.getJob().isDataTransfer()) {
- // For now, don't increase a bg data transfer's minimum guarantee.
- return mConstants.RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS;
} else if (job.shouldTreatAsExpeditedJob()) {
// Don't guarantee RESTRICTED jobs more than 5 minutes.
return job.getEffectiveStandbyBucket() != RESTRICTED_INDEX
@@ -3326,7 +3286,7 @@ public class JobSchedulerService extends com.android.server.SystemService
final boolean allowLongerJob = job.shouldTreatAsUserInitiatedJob()
&& checkRunUserInitiatedJobsPermission(
job.getSourceUid(), job.getSourcePackageName());
- if (job.getJob().isDataTransfer() && allowLongerJob) { // UI+DT
+ if (job.getJob().getRequiredNetwork() != null && allowLongerJob) { // UI+DT
return mConstants.RUNTIME_USER_INITIATED_DATA_TRANSFER_LIMIT_MS;
}
if (allowLongerJob) { // UI with LRJ permission
@@ -3335,9 +3295,6 @@ public class JobSchedulerService extends com.android.server.SystemService
if (job.shouldTreatAsUserInitiatedJob()) {
return mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS;
}
- if (job.getJob().isDataTransfer()) {
- return mConstants.RUNTIME_DATA_TRANSFER_LIMIT_MS;
- }
return Math.min(mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
mConstants.USE_TARE_POLICY
? mTareController.getMaxJobExecutionTimeMsLocked(job)
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
index 1d0fdd908f2c..4357d4f39dce 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
@@ -670,6 +670,7 @@ public final class JobSchedulerShellCommand extends BasicShellCommandHandler {
+ " [PACKAGE] [JOB_ID]");
pw.println(" Trigger immediate timeout of currently executing jobs, as if their");
pw.println(" execution timeout had expired.");
+ pw.println(" This is the equivalent of calling `stop -s 3 -i 3`.");
pw.println(" Options:");
pw.println(" -u or --user: specify which user's job is to be run; the default is");
pw.println(" all users");
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
index ceb47eaa6906..e60ed4ade9b7 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
@@ -461,7 +461,8 @@ public final class JobServiceContext implements ServiceConnection {
job.isConstraintSatisfied(JobStatus.CONSTRAINT_TIMING_DELAY),
job.isConstraintSatisfied(JobInfo.CONSTRAINT_FLAG_DEVICE_IDLE),
job.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY),
- job.isConstraintSatisfied(JobStatus.CONSTRAINT_CONTENT_TRIGGER));
+ job.isConstraintSatisfied(JobStatus.CONSTRAINT_CONTENT_TRIGGER),
+ mExecutionStartTimeElapsed - job.enqueueTime);
if (Trace.isTagEnabled(Trace.TRACE_TAG_SYSTEM_SERVER)) {
// Use the context's ID to distinguish traces since there'll only be one job
// running per context.
@@ -726,8 +727,11 @@ public final class JobServiceContext implements ServiceConnection {
// Exception-throwing-can down the road to JobParameters.completeWork >:(
return true;
}
- mService.mJobs.touchJob(mRunningJob);
- return mRunningJob.completeWorkLocked(workId);
+ if (mRunningJob.completeWorkLocked(workId)) {
+ mService.mJobs.touchJob(mRunningJob);
+ return true;
+ }
+ return false;
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -1356,7 +1360,8 @@ public final class JobServiceContext implements ServiceConnection {
completedJob.isConstraintSatisfied(JobStatus.CONSTRAINT_TIMING_DELAY),
completedJob.isConstraintSatisfied(JobInfo.CONSTRAINT_FLAG_DEVICE_IDLE),
completedJob.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY),
- completedJob.isConstraintSatisfied(JobStatus.CONSTRAINT_CONTENT_TRIGGER));
+ completedJob.isConstraintSatisfied(JobStatus.CONSTRAINT_CONTENT_TRIGGER),
+ 0);
if (Trace.isTagEnabled(Trace.TRACE_TAG_SYSTEM_SERVER)) {
Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_SYSTEM_SERVER, "JobScheduler",
getId());
@@ -1373,7 +1378,7 @@ public final class JobServiceContext implements ServiceConnection {
JobSchedulerEconomicPolicy.ACTION_JOB_TIMEOUT,
String.valueOf(mRunningJob.getJobId()));
}
- mNotificationCoordinator.removeNotificationAssociation(this);
+ mNotificationCoordinator.removeNotificationAssociation(this, reschedulingStopReason);
if (mWakeLock != null) {
mWakeLock.release();
}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
index 1971a11ca98a..537a67039a82 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
@@ -828,6 +828,10 @@ public final class JobStatus {
}
}
+ /**
+ * Returns {@code true} if the JobWorkItem queue was updated,
+ * and {@code false} if nothing changed.
+ */
public boolean completeWorkLocked(int workId) {
if (executingWork != null) {
final int N = executingWork.size();
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java
index 9ada8dc3ef32..47b7e13446b8 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java
@@ -24,6 +24,7 @@ import android.util.Log;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
+import com.android.server.JobSchedulerBackgroundThread;
import com.android.server.am.ActivityManagerService;
import com.android.server.job.JobSchedulerService;
import com.android.server.job.StateControllerProto;
@@ -50,7 +51,7 @@ public final class CarIdlenessTracker extends BroadcastReceiver implements Idlen
public static final String ACTION_UNFORCE_IDLE = "com.android.server.jobscheduler.UNFORCE_IDLE";
// After construction, mutations of idle/screen-on state will only happen
- // on the main looper thread, either in onReceive() or in an alarm callback.
+ // on the JobScheduler thread, either in onReceive() or in an alarm callback.
private boolean mIdle;
private boolean mGarageModeOn;
private boolean mForced;
@@ -90,7 +91,7 @@ public final class CarIdlenessTracker extends BroadcastReceiver implements Idlen
filter.addAction(ACTION_UNFORCE_IDLE);
filter.addAction(ActivityManagerService.ACTION_TRIGGER_IDLE);
- context.registerReceiver(this, filter);
+ context.registerReceiver(this, filter, null, JobSchedulerBackgroundThread.getHandler());
}
@Override
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java
index 140cca679e14..15d67662130f 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java
@@ -31,6 +31,7 @@ import android.util.Log;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
+import com.android.server.JobSchedulerBackgroundThread;
import com.android.server.am.ActivityManagerService;
import com.android.server.job.JobSchedulerService;
import com.android.server.job.StateControllerProto;
@@ -47,8 +48,8 @@ public final class DeviceIdlenessTracker extends BroadcastReceiver implements Id
private AlarmManager mAlarm;
private PowerManager mPowerManager;
- // After construction, mutations of idle/screen-on state will only happen
- // on the main looper thread, either in onReceive() or in an alarm callback.
+ // After construction, mutations of idle/screen-on/projection states will only happen
+ // on the JobScheduler thread, either in onReceive(), in an alarm callback, or in on.*Changed.
private long mInactivityIdleThreshold;
private long mIdleWindowSlop;
private boolean mIdle;
@@ -101,12 +102,10 @@ public final class DeviceIdlenessTracker extends BroadcastReceiver implements Id
filter.addAction(Intent.ACTION_DOCK_IDLE);
filter.addAction(Intent.ACTION_DOCK_ACTIVE);
- context.registerReceiver(this, filter);
+ context.registerReceiver(this, filter, null, JobSchedulerBackgroundThread.getHandler());
- // TODO(b/172579710): Move the callbacks off the main executor and on to
- // JobSchedulerBackgroundThread.getExecutor() once synchronization is fixed in this class.
context.getSystemService(UiModeManager.class).addOnProjectionStateChangedListener(
- UiModeManager.PROJECTION_TYPE_ALL, context.getMainExecutor(),
+ UiModeManager.PROJECTION_TYPE_ALL, JobSchedulerBackgroundThread.getExecutor(),
mOnProjectionStateChangedListener);
}
@@ -226,7 +225,8 @@ public final class DeviceIdlenessTracker extends BroadcastReceiver implements Id
Slog.v(TAG, "Scheduling idle : " + reason + " now:" + nowElapsed + " when=" + when);
}
mAlarm.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP,
- when, mIdleWindowSlop, "JS idleness", mIdleAlarmListener, null);
+ when, mIdleWindowSlop, "JS idleness",
+ JobSchedulerBackgroundThread.getExecutor(), mIdleAlarmListener);
}
}
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING b/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING
index a6a3aafdb4f4..6a4a52a5658b 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING
+++ b/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING
@@ -4,6 +4,7 @@
"name": "CtsUsageStatsTestCases",
"options": [
{"include-filter": "android.app.usage.cts.UsageStatsTest"},
+ {"include-filter": "android.app.usage.cts.BroadcastResponseStatsTest"},
{"exclude-annotation": "android.platform.test.annotations.FlakyTest"},
{"exclude-annotation": "androidx.test.filters.FlakyTest"},
{"exclude-annotation": "androidx.test.filters.MediumTest"},
@@ -19,18 +20,6 @@
]
}
],
- "presubmit-large": [
- {
- "name": "CtsUsageStatsTestCases",
- "options": [
- {"include-filter": "android.app.usage.cts.BroadcastResponseStatsTest"},
- {"exclude-annotation": "android.platform.test.annotations.FlakyTest"},
- {"exclude-annotation": "androidx.test.filters.FlakyTest"},
- {"exclude-annotation": "androidx.test.filters.MediumTest"},
- {"exclude-annotation": "androidx.test.filters.LargeTest"}
- ]
- }
- ],
"postsubmit": [
{
"name": "CtsUsageStatsTestCases"
diff --git a/core/api/current.txt b/core/api/current.txt
index 82b3c14ad366..f625a73f222d 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -375,7 +375,7 @@ package android {
public static final class R.attr {
ctor public R.attr();
field public static final int absListViewStyle = 16842858; // 0x101006a
- field public static final int accessibilityDataPrivate;
+ field public static final int accessibilityDataSensitive;
field public static final int accessibilityEventTypes = 16843648; // 0x1010380
field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
field public static final int accessibilityFlags = 16843652; // 0x1010384
@@ -5279,8 +5279,8 @@ package android.app {
}
public class BroadcastOptions {
+ ctor public BroadcastOptions();
method public boolean isShareIdentityEnabled();
- method @NonNull public static android.app.BroadcastOptions makeBasic();
method @NonNull public android.app.BroadcastOptions setShareIdentityEnabled(boolean);
method @NonNull public android.os.Bundle toBundle();
}
@@ -6784,7 +6784,7 @@ package android.app {
method public boolean areNotificationsEnabled();
method public boolean areNotificationsPaused();
method public boolean canNotifyAsPackage(@NonNull String);
- method public boolean canSendFullScreenIntent();
+ method public boolean canUseFullScreenIntent();
method public void cancel(int);
method public void cancel(@Nullable String, int);
method public void cancelAll();
@@ -7269,6 +7269,13 @@ package android.app {
method public void onSharedElementsReady();
}
+ public final class StartForegroundCalledOnStoppedServiceException extends java.lang.IllegalStateException implements android.os.Parcelable {
+ ctor public StartForegroundCalledOnStoppedServiceException(@NonNull String);
+ method public int describeContents();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.StartForegroundCalledOnStoppedServiceException> CREATOR;
+ }
+
public class StatusBarManager {
method @RequiresPermission(android.Manifest.permission.LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE) public boolean canLaunchCaptureContentActivityForNote(@NonNull android.app.Activity);
method public void requestAddTileService(@NonNull android.content.ComponentName, @NonNull CharSequence, @NonNull android.graphics.drawable.Icon, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
@@ -8733,7 +8740,6 @@ package android.app.job {
method public long getTriggerContentMaxDelay();
method public long getTriggerContentUpdateDelay();
method @Nullable public android.app.job.JobInfo.TriggerContentUri[] getTriggerContentUris();
- method public boolean isDataTransfer();
method public boolean isExpedited();
method public boolean isImportantWhileForeground();
method public boolean isPeriodic();
@@ -8770,7 +8776,6 @@ package android.app.job {
method public android.app.job.JobInfo build();
method public android.app.job.JobInfo.Builder setBackoffCriteria(long, int);
method public android.app.job.JobInfo.Builder setClipData(@Nullable android.content.ClipData, int);
- method @NonNull public android.app.job.JobInfo.Builder setDataTransfer(boolean);
method public android.app.job.JobInfo.Builder setEstimatedNetworkBytes(long, long);
method @NonNull public android.app.job.JobInfo.Builder setExpedited(boolean);
method public android.app.job.JobInfo.Builder setExtras(@NonNull android.os.PersistableBundle);
@@ -9576,8 +9581,6 @@ package android.companion.virtual {
public final class VirtualDeviceManager {
method @NonNull public java.util.List<android.companion.virtual.VirtualDevice> getVirtualDevices();
- field public static final int DEVICE_ID_DEFAULT = 0; // 0x0
- field public static final int DEVICE_ID_INVALID = -1; // 0xffffffff
}
}
@@ -10354,6 +10357,8 @@ package android.content {
field public static final int CONTEXT_RESTRICTED = 4; // 0x4
field public static final String CREDENTIAL_SERVICE = "credential";
field public static final String CROSS_PROFILE_APPS_SERVICE = "crossprofileapps";
+ field public static final int DEVICE_ID_DEFAULT = 0; // 0x0
+ field public static final int DEVICE_ID_INVALID = -1; // 0xffffffff
field public static final String DEVICE_LOCK_SERVICE = "device_lock";
field public static final String DEVICE_POLICY_SERVICE = "device_policy";
field public static final String DISPLAY_HASH_SERVICE = "display_hash";
@@ -12448,7 +12453,7 @@ package android.content.pm {
method @Nullable public abstract android.graphics.drawable.Drawable getActivityBanner(@NonNull android.content.Intent) throws android.content.pm.PackageManager.NameNotFoundException;
method @NonNull public abstract android.graphics.drawable.Drawable getActivityIcon(@NonNull android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
method @NonNull public abstract android.graphics.drawable.Drawable getActivityIcon(@NonNull android.content.Intent) throws android.content.pm.PackageManager.NameNotFoundException;
- method @Deprecated @NonNull public abstract android.content.pm.ActivityInfo getActivityInfo(@NonNull android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+ method @NonNull public abstract android.content.pm.ActivityInfo getActivityInfo(@NonNull android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
method @NonNull public android.content.pm.ActivityInfo getActivityInfo(@NonNull android.content.ComponentName, @NonNull android.content.pm.PackageManager.ComponentInfoFlags) throws android.content.pm.PackageManager.NameNotFoundException;
method @Nullable public abstract android.graphics.drawable.Drawable getActivityLogo(@NonNull android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
method @Nullable public abstract android.graphics.drawable.Drawable getActivityLogo(@NonNull android.content.Intent) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -12458,7 +12463,7 @@ package android.content.pm {
method public abstract int getApplicationEnabledSetting(@NonNull String);
method @NonNull public abstract android.graphics.drawable.Drawable getApplicationIcon(@NonNull android.content.pm.ApplicationInfo);
method @NonNull public abstract android.graphics.drawable.Drawable getApplicationIcon(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
- method @Deprecated @NonNull public abstract android.content.pm.ApplicationInfo getApplicationInfo(@NonNull String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+ method @NonNull public abstract android.content.pm.ApplicationInfo getApplicationInfo(@NonNull String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method @NonNull public android.content.pm.ApplicationInfo getApplicationInfo(@NonNull String, @NonNull android.content.pm.PackageManager.ApplicationInfoFlags) throws android.content.pm.PackageManager.NameNotFoundException;
method @NonNull public abstract CharSequence getApplicationLabel(@NonNull android.content.pm.ApplicationInfo);
method @Nullable public abstract android.graphics.drawable.Drawable getApplicationLogo(@NonNull android.content.pm.ApplicationInfo);
@@ -12470,10 +12475,10 @@ package android.content.pm {
method @Nullable public abstract android.graphics.drawable.Drawable getDrawable(@NonNull String, @DrawableRes int, @Nullable android.content.pm.ApplicationInfo);
method public void getGroupOfPlatformPermission(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.String>);
method @NonNull public android.content.pm.InstallSourceInfo getInstallSourceInfo(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
- method @Deprecated @NonNull public abstract java.util.List<android.content.pm.ApplicationInfo> getInstalledApplications(int);
+ method @NonNull public abstract java.util.List<android.content.pm.ApplicationInfo> getInstalledApplications(int);
method @NonNull public java.util.List<android.content.pm.ApplicationInfo> getInstalledApplications(@NonNull android.content.pm.PackageManager.ApplicationInfoFlags);
method @NonNull public java.util.List<android.content.pm.ModuleInfo> getInstalledModules(int);
- method @Deprecated @NonNull public abstract java.util.List<android.content.pm.PackageInfo> getInstalledPackages(int);
+ method @NonNull public abstract java.util.List<android.content.pm.PackageInfo> getInstalledPackages(int);
method @NonNull public java.util.List<android.content.pm.PackageInfo> getInstalledPackages(@NonNull android.content.pm.PackageManager.PackageInfoFlags);
method @Deprecated @Nullable public abstract String getInstallerPackageName(@NonNull String);
method @NonNull public abstract byte[] getInstantAppCookie();
@@ -12485,20 +12490,20 @@ package android.content.pm {
method @NonNull public java.util.Set<java.lang.String> getMimeGroup(@NonNull String);
method @NonNull public android.content.pm.ModuleInfo getModuleInfo(@NonNull String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method @Nullable public abstract String getNameForUid(int);
- method @Deprecated @Nullable public android.content.pm.PackageInfo getPackageArchiveInfo(@NonNull String, int);
+ method @Nullable public android.content.pm.PackageInfo getPackageArchiveInfo(@NonNull String, int);
method @Nullable public android.content.pm.PackageInfo getPackageArchiveInfo(@NonNull String, @NonNull android.content.pm.PackageManager.PackageInfoFlags);
method public abstract int[] getPackageGids(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
- method @Deprecated public abstract int[] getPackageGids(@NonNull String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public abstract int[] getPackageGids(@NonNull String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method @Nullable public int[] getPackageGids(@NonNull String, @NonNull android.content.pm.PackageManager.PackageInfoFlags) throws android.content.pm.PackageManager.NameNotFoundException;
- method @Deprecated public abstract android.content.pm.PackageInfo getPackageInfo(@NonNull String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public abstract android.content.pm.PackageInfo getPackageInfo(@NonNull String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method @NonNull public android.content.pm.PackageInfo getPackageInfo(@NonNull String, @NonNull android.content.pm.PackageManager.PackageInfoFlags) throws android.content.pm.PackageManager.NameNotFoundException;
- method @Deprecated public abstract android.content.pm.PackageInfo getPackageInfo(@NonNull android.content.pm.VersionedPackage, int) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public abstract android.content.pm.PackageInfo getPackageInfo(@NonNull android.content.pm.VersionedPackage, int) throws android.content.pm.PackageManager.NameNotFoundException;
method @NonNull public android.content.pm.PackageInfo getPackageInfo(@NonNull android.content.pm.VersionedPackage, @NonNull android.content.pm.PackageManager.PackageInfoFlags) throws android.content.pm.PackageManager.NameNotFoundException;
method @NonNull public abstract android.content.pm.PackageInstaller getPackageInstaller();
- method @Deprecated public abstract int getPackageUid(@NonNull String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public abstract int getPackageUid(@NonNull String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method public int getPackageUid(@NonNull String, @NonNull android.content.pm.PackageManager.PackageInfoFlags) throws android.content.pm.PackageManager.NameNotFoundException;
method @Nullable public abstract String[] getPackagesForUid(int);
- method @Deprecated @NonNull public abstract java.util.List<android.content.pm.PackageInfo> getPackagesHoldingPermissions(@NonNull String[], int);
+ method @NonNull public abstract java.util.List<android.content.pm.PackageInfo> getPackagesHoldingPermissions(@NonNull String[], int);
method @NonNull public java.util.List<android.content.pm.PackageInfo> getPackagesHoldingPermissions(@NonNull String[], @NonNull android.content.pm.PackageManager.PackageInfoFlags);
method @NonNull public abstract android.content.pm.PermissionGroupInfo getPermissionGroupInfo(@NonNull String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method public abstract android.content.pm.PermissionInfo getPermissionInfo(@NonNull String, int) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -12507,17 +12512,17 @@ package android.content.pm {
method @Deprecated @NonNull public abstract java.util.List<android.content.pm.PackageInfo> getPreferredPackages(int);
method @NonNull public android.content.pm.PackageManager.Property getProperty(@NonNull String, @NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
method @NonNull public android.content.pm.PackageManager.Property getProperty(@NonNull String, @NonNull android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
- method @Deprecated @NonNull public abstract android.content.pm.ProviderInfo getProviderInfo(@NonNull android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+ method @NonNull public abstract android.content.pm.ProviderInfo getProviderInfo(@NonNull android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
method @NonNull public android.content.pm.ProviderInfo getProviderInfo(@NonNull android.content.ComponentName, @NonNull android.content.pm.PackageManager.ComponentInfoFlags) throws android.content.pm.PackageManager.NameNotFoundException;
- method @Deprecated @NonNull public abstract android.content.pm.ActivityInfo getReceiverInfo(@NonNull android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+ method @NonNull public abstract android.content.pm.ActivityInfo getReceiverInfo(@NonNull android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
method @NonNull public android.content.pm.ActivityInfo getReceiverInfo(@NonNull android.content.ComponentName, @NonNull android.content.pm.PackageManager.ComponentInfoFlags) throws android.content.pm.PackageManager.NameNotFoundException;
method @NonNull public abstract android.content.res.Resources getResourcesForActivity(@NonNull android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
method @NonNull public abstract android.content.res.Resources getResourcesForApplication(@NonNull android.content.pm.ApplicationInfo) throws android.content.pm.PackageManager.NameNotFoundException;
method @NonNull public android.content.res.Resources getResourcesForApplication(@NonNull android.content.pm.ApplicationInfo, @Nullable android.content.res.Configuration) throws android.content.pm.PackageManager.NameNotFoundException;
method @NonNull public abstract android.content.res.Resources getResourcesForApplication(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
- method @Deprecated @NonNull public abstract android.content.pm.ServiceInfo getServiceInfo(@NonNull android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+ method @NonNull public abstract android.content.pm.ServiceInfo getServiceInfo(@NonNull android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
method @NonNull public android.content.pm.ServiceInfo getServiceInfo(@NonNull android.content.ComponentName, @NonNull android.content.pm.PackageManager.ComponentInfoFlags) throws android.content.pm.PackageManager.NameNotFoundException;
- method @Deprecated @NonNull public abstract java.util.List<android.content.pm.SharedLibraryInfo> getSharedLibraries(int);
+ method @NonNull public abstract java.util.List<android.content.pm.SharedLibraryInfo> getSharedLibraries(int);
method @NonNull public java.util.List<android.content.pm.SharedLibraryInfo> getSharedLibraries(@NonNull android.content.pm.PackageManager.PackageInfoFlags);
method @Nullable public android.os.Bundle getSuspendedPackageAppExtras();
method public boolean getSyntheticAppDetailsActivityEnabled(@NonNull String);
@@ -12546,18 +12551,18 @@ package android.content.pm {
method public abstract boolean isSafeMode();
method @NonNull public java.util.List<android.content.pm.PackageManager.Property> queryActivityProperty(@NonNull String);
method @NonNull public java.util.List<android.content.pm.PackageManager.Property> queryApplicationProperty(@NonNull String);
- method @Deprecated @NonNull public abstract java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(@NonNull android.content.Intent, int);
+ method @NonNull public abstract java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(@NonNull android.content.Intent, int);
method @NonNull public java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(@NonNull android.content.Intent, @NonNull android.content.pm.PackageManager.ResolveInfoFlags);
- method @Deprecated @NonNull public abstract java.util.List<android.content.pm.ProviderInfo> queryContentProviders(@Nullable String, int, int);
+ method @NonNull public abstract java.util.List<android.content.pm.ProviderInfo> queryContentProviders(@Nullable String, int, int);
method @NonNull public java.util.List<android.content.pm.ProviderInfo> queryContentProviders(@Nullable String, int, @NonNull android.content.pm.PackageManager.ComponentInfoFlags);
method @NonNull public abstract java.util.List<android.content.pm.InstrumentationInfo> queryInstrumentation(@NonNull String, int);
- method @Deprecated @NonNull public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentActivities(@NonNull android.content.Intent, int);
+ method @NonNull public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentActivities(@NonNull android.content.Intent, int);
method @NonNull public java.util.List<android.content.pm.ResolveInfo> queryIntentActivities(@NonNull android.content.Intent, @NonNull android.content.pm.PackageManager.ResolveInfoFlags);
- method @Deprecated @NonNull public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentActivityOptions(@Nullable android.content.ComponentName, @Nullable android.content.Intent[], @NonNull android.content.Intent, int);
+ method @NonNull public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentActivityOptions(@Nullable android.content.ComponentName, @Nullable android.content.Intent[], @NonNull android.content.Intent, int);
method @NonNull public java.util.List<android.content.pm.ResolveInfo> queryIntentActivityOptions(@Nullable android.content.ComponentName, @Nullable java.util.List<android.content.Intent>, @NonNull android.content.Intent, @NonNull android.content.pm.PackageManager.ResolveInfoFlags);
- method @Deprecated @NonNull public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentContentProviders(@NonNull android.content.Intent, int);
+ method @NonNull public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentContentProviders(@NonNull android.content.Intent, int);
method @NonNull public java.util.List<android.content.pm.ResolveInfo> queryIntentContentProviders(@NonNull android.content.Intent, @NonNull android.content.pm.PackageManager.ResolveInfoFlags);
- method @Deprecated @NonNull public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentServices(@NonNull android.content.Intent, int);
+ method @NonNull public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentServices(@NonNull android.content.Intent, int);
method @NonNull public java.util.List<android.content.pm.ResolveInfo> queryIntentServices(@NonNull android.content.Intent, @NonNull android.content.pm.PackageManager.ResolveInfoFlags);
method @NonNull public abstract java.util.List<android.content.pm.PermissionInfo> queryPermissionsByGroup(@Nullable String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method @NonNull public java.util.List<android.content.pm.PackageManager.Property> queryProviderProperty(@NonNull String);
@@ -12568,11 +12573,11 @@ package android.content.pm {
method public abstract void removePermission(@NonNull String);
method @RequiresPermission(value="android.permission.WHITELIST_RESTRICTED_PERMISSIONS", conditional=true) public boolean removeWhitelistedRestrictedPermission(@NonNull String, @NonNull String, int);
method public void requestChecksums(@NonNull String, boolean, int, @NonNull java.util.List<java.security.cert.Certificate>, @NonNull android.content.pm.PackageManager.OnChecksumsReadyListener) throws java.security.cert.CertificateEncodingException, android.content.pm.PackageManager.NameNotFoundException;
- method @Deprecated @Nullable public abstract android.content.pm.ResolveInfo resolveActivity(@NonNull android.content.Intent, int);
+ method @Nullable public abstract android.content.pm.ResolveInfo resolveActivity(@NonNull android.content.Intent, int);
method @Nullable public android.content.pm.ResolveInfo resolveActivity(@NonNull android.content.Intent, @NonNull android.content.pm.PackageManager.ResolveInfoFlags);
- method @Deprecated @Nullable public abstract android.content.pm.ProviderInfo resolveContentProvider(@NonNull String, int);
+ method @Nullable public abstract android.content.pm.ProviderInfo resolveContentProvider(@NonNull String, int);
method @Nullable public android.content.pm.ProviderInfo resolveContentProvider(@NonNull String, @NonNull android.content.pm.PackageManager.ComponentInfoFlags);
- method @Deprecated @Nullable public abstract android.content.pm.ResolveInfo resolveService(@NonNull android.content.Intent, int);
+ method @Nullable public abstract android.content.pm.ResolveInfo resolveService(@NonNull android.content.Intent, int);
method @Nullable public android.content.pm.ResolveInfo resolveService(@NonNull android.content.Intent, @NonNull android.content.pm.PackageManager.ResolveInfoFlags);
method public abstract void setApplicationCategoryHint(@NonNull String, int);
method @RequiresPermission(value=android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE, conditional=true) public abstract void setApplicationEnabledSetting(@NonNull String, int, int);
@@ -13577,17 +13582,25 @@ package android.credentials {
}
public final class CreateCredentialRequest implements android.os.Parcelable {
- ctor public CreateCredentialRequest(@NonNull String, @NonNull android.os.Bundle, @NonNull android.os.Bundle, boolean, boolean);
method public boolean alwaysSendAppInfoToProvider();
method public int describeContents();
method @NonNull public android.os.Bundle getCandidateQueryData();
method @NonNull public android.os.Bundle getCredentialData();
+ method @Nullable public String getOrigin();
method @NonNull public String getType();
method public boolean isSystemProviderRequired();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.credentials.CreateCredentialRequest> CREATOR;
}
+ public static final class CreateCredentialRequest.Builder {
+ ctor public CreateCredentialRequest.Builder(@NonNull String, @NonNull android.os.Bundle, @NonNull android.os.Bundle);
+ method @NonNull public android.credentials.CreateCredentialRequest build();
+ method @NonNull public android.credentials.CreateCredentialRequest.Builder setAlwaysSendAppInfoToProvider(boolean);
+ method @NonNull public android.credentials.CreateCredentialRequest.Builder setIsSystemProviderRequired(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.CREDENTIAL_MANAGER_SET_ORIGIN) public android.credentials.CreateCredentialRequest.Builder setOrigin(@NonNull String);
+ }
+
public final class CreateCredentialResponse implements android.os.Parcelable {
ctor public CreateCredentialResponse(@NonNull android.os.Bundle);
method public int describeContents();
@@ -13619,9 +13632,7 @@ package android.credentials {
public final class CredentialManager {
method public void clearCredentialState(@NonNull android.credentials.ClearCredentialStateRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.credentials.ClearCredentialStateException>);
method public void createCredential(@NonNull android.credentials.CreateCredentialRequest, @NonNull android.app.Activity, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.credentials.CreateCredentialResponse,android.credentials.CreateCredentialException>);
- method @RequiresPermission(android.Manifest.permission.CREDENTIAL_MANAGER_SET_ORIGIN) public void createCredentialWithOrigin(@NonNull android.credentials.CreateCredentialRequest, @Nullable String, @NonNull android.app.Activity, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.credentials.CreateCredentialResponse,android.credentials.CreateCredentialException>);
method public void getCredential(@NonNull android.credentials.GetCredentialRequest, @NonNull android.app.Activity, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.credentials.GetCredentialResponse,android.credentials.GetCredentialException>);
- method @RequiresPermission(android.Manifest.permission.CREDENTIAL_MANAGER_SET_ORIGIN) public void getCredentialWithOrigin(@NonNull android.credentials.GetCredentialRequest, @Nullable String, @NonNull android.app.Activity, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.credentials.GetCredentialResponse,android.credentials.GetCredentialException>);
method public boolean isEnabledCredentialProviderService(@NonNull android.content.ComponentName);
method public void registerCredentialDescription(@NonNull android.credentials.RegisterCredentialDescriptionRequest);
method public void unregisterCredentialDescription(@NonNull android.credentials.UnregisterCredentialDescriptionRequest);
@@ -13656,6 +13667,7 @@ package android.credentials {
method public int describeContents();
method @NonNull public java.util.List<android.credentials.CredentialOption> getCredentialOptions();
method @NonNull public android.os.Bundle getData();
+ method @Nullable public String getOrigin();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.credentials.GetCredentialRequest> CREATOR;
}
@@ -13666,6 +13678,7 @@ package android.credentials {
method @NonNull public android.credentials.GetCredentialRequest build();
method @NonNull public android.credentials.GetCredentialRequest.Builder setAlwaysSendAppInfoToProvider(boolean);
method @NonNull public android.credentials.GetCredentialRequest.Builder setCredentialOptions(@NonNull java.util.List<android.credentials.CredentialOption>);
+ method @NonNull @RequiresPermission(android.Manifest.permission.CREDENTIAL_MANAGER_SET_ORIGIN) public android.credentials.GetCredentialRequest.Builder setOrigin(@NonNull String);
}
public final class GetCredentialResponse implements android.os.Parcelable {
@@ -19361,7 +19374,7 @@ package android.hardware.camera2.params {
public final class OutputConfiguration implements android.os.Parcelable {
ctor public OutputConfiguration(@NonNull android.view.Surface);
ctor public OutputConfiguration(int, @NonNull android.view.Surface);
- ctor public OutputConfiguration(@NonNull android.util.Size, @NonNull Class<T>);
+ ctor public <T> OutputConfiguration(@NonNull android.util.Size, @NonNull Class<T>);
method public void addSensorPixelModeUsed(int);
method public void addSurface(@NonNull android.view.Surface);
method @NonNull public static java.util.Collection<android.hardware.camera2.params.OutputConfiguration> createInstancesForMultiResolutionOutput(@NonNull android.hardware.camera2.MultiResolutionImageReader);
@@ -19520,9 +19533,9 @@ package android.hardware.display {
public final class DisplayManager {
method public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull String, @IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, @Nullable android.view.Surface, int);
- method @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull String, @IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, float, @Nullable android.view.Surface, int);
method public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull String, @IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, @Nullable android.view.Surface, int, @Nullable android.hardware.display.VirtualDisplay.Callback, @Nullable android.os.Handler);
- method @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull String, @IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, float, @Nullable android.view.Surface, int, @Nullable android.os.Handler, @Nullable android.hardware.display.VirtualDisplay.Callback);
+ method @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull android.hardware.display.VirtualDisplayConfig);
+ method @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull android.hardware.display.VirtualDisplayConfig, @Nullable android.os.Handler, @Nullable android.hardware.display.VirtualDisplay.Callback);
method public android.view.Display getDisplay(int);
method public android.view.Display[] getDisplays();
method public android.view.Display[] getDisplays(String);
@@ -19577,6 +19590,30 @@ package android.hardware.display {
method public void onStopped();
}
+ public final class VirtualDisplayConfig implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getDensityDpi();
+ method @NonNull public java.util.List<java.lang.String> getDisplayCategories();
+ method public int getFlags();
+ method public int getHeight();
+ method @NonNull public String getName();
+ method public float getRequestedRefreshRate();
+ method @Nullable public android.view.Surface getSurface();
+ method public int getWidth();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.hardware.display.VirtualDisplayConfig> CREATOR;
+ }
+
+ public static final class VirtualDisplayConfig.Builder {
+ ctor public VirtualDisplayConfig.Builder(@NonNull String, @IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int);
+ method @NonNull public android.hardware.display.VirtualDisplayConfig.Builder addDisplayCategory(@NonNull String);
+ method @NonNull public android.hardware.display.VirtualDisplayConfig build();
+ method @NonNull public android.hardware.display.VirtualDisplayConfig.Builder setDisplayCategories(@NonNull java.util.List<java.lang.String>);
+ method @NonNull public android.hardware.display.VirtualDisplayConfig.Builder setFlags(int);
+ method @NonNull public android.hardware.display.VirtualDisplayConfig.Builder setRequestedRefreshRate(@FloatRange(from=0.0f) float);
+ method @NonNull public android.hardware.display.VirtualDisplayConfig.Builder setSurface(@Nullable android.view.Surface);
+ }
+
}
package android.hardware.fingerprint {
@@ -20351,7 +20388,7 @@ package android.location {
public final class GnssCapabilities implements android.os.Parcelable {
method public int describeContents();
method @NonNull public java.util.List<android.location.GnssSignalType> getGnssSignalTypes();
- method public boolean hasAccumulatedDeltaRange();
+ method public int hasAccumulatedDeltaRange();
method public boolean hasAntennaInfo();
method public boolean hasGeofencing();
method @Deprecated public boolean hasGnssAntennaInfo();
@@ -20377,8 +20414,10 @@ package android.location {
method public boolean hasSatellitePvt();
method public boolean hasScheduling();
method public boolean hasSingleShotFix();
- method public boolean isAccumulatedDeltaRangeCapabilityKnown();
method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int CAPABILITY_SUPPORTED = 1; // 0x1
+ field public static final int CAPABILITY_UNKNOWN = 0; // 0x0
+ field public static final int CAPABILITY_UNSUPPORTED = 2; // 0x2
field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssCapabilities> CREATOR;
}
@@ -20386,9 +20425,8 @@ package android.location {
ctor public GnssCapabilities.Builder();
ctor public GnssCapabilities.Builder(@NonNull android.location.GnssCapabilities);
method @NonNull public android.location.GnssCapabilities build();
- method @NonNull public android.location.GnssCapabilities.Builder clearIsAccumulatedDeltaRangeCapabilityKnown();
method @NonNull public android.location.GnssCapabilities.Builder setGnssSignalTypes(@NonNull java.util.List<android.location.GnssSignalType>);
- method @NonNull public android.location.GnssCapabilities.Builder setHasAccumulatedDeltaRange(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasAccumulatedDeltaRange(int);
method @NonNull public android.location.GnssCapabilities.Builder setHasAntennaInfo(boolean);
method @NonNull public android.location.GnssCapabilities.Builder setHasGeofencing(boolean);
method @NonNull public android.location.GnssCapabilities.Builder setHasLowPowerMode(boolean);
@@ -32404,6 +32442,8 @@ package android.os {
field public static final int BATTERY_STATUS_NOT_CHARGING = 4; // 0x4
field public static final int BATTERY_STATUS_UNKNOWN = 1; // 0x1
field public static final String EXTRA_BATTERY_LOW = "battery_low";
+ field public static final String EXTRA_CHARGING_STATUS = "android.os.extra.CHARGING_STATUS";
+ field public static final String EXTRA_CYCLE_COUNT = "android.os.extra.CYCLE_COUNT";
field public static final String EXTRA_HEALTH = "health";
field public static final String EXTRA_ICON_SMALL = "icon-small";
field public static final String EXTRA_LEVEL = "level";
@@ -33794,6 +33834,7 @@ package android.os {
method public android.os.Bundle getUserRestrictions();
method @RequiresPermission(anyOf={"android.permission.MANAGE_USERS", "android.permission.INTERACT_ACROSS_USERS"}, conditional=true) public android.os.Bundle getUserRestrictions(android.os.UserHandle);
method public boolean hasUserRestriction(String);
+ method public boolean isAdminUser();
method public boolean isDemoUser();
method public static boolean isHeadlessSystemUserMode();
method public boolean isManagedProfile();
@@ -39821,6 +39862,7 @@ package android.service.autofill {
field public static final int TYPE_DATASET_AUTHENTICATION_SELECTED = 1; // 0x1
field public static final int TYPE_DATASET_SELECTED = 0; // 0x0
field public static final int TYPE_SAVE_SHOWN = 3; // 0x3
+ field public static final int TYPE_VIEW_REQUESTED_AUTOFILL = 6; // 0x6
field public static final int UI_TYPE_DIALOG = 3; // 0x3
field public static final int UI_TYPE_INLINE = 2; // 0x2
field public static final int UI_TYPE_MENU = 1; // 0x1
@@ -40497,7 +40539,7 @@ package android.service.credentials {
ctor public BeginCreateCredentialResponse();
method public int describeContents();
method @NonNull public java.util.List<android.service.credentials.CreateEntry> getCreateEntries();
- method @Nullable public android.service.credentials.CreateEntry getRemoteCreateEntry();
+ method @Nullable public android.service.credentials.RemoteEntry getRemoteCreateEntry();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.BeginCreateCredentialResponse> CREATOR;
}
@@ -40507,7 +40549,7 @@ package android.service.credentials {
method @NonNull public android.service.credentials.BeginCreateCredentialResponse.Builder addCreateEntry(@NonNull android.service.credentials.CreateEntry);
method @NonNull public android.service.credentials.BeginCreateCredentialResponse build();
method @NonNull public android.service.credentials.BeginCreateCredentialResponse.Builder setCreateEntries(@NonNull java.util.List<android.service.credentials.CreateEntry>);
- method @NonNull public android.service.credentials.BeginCreateCredentialResponse.Builder setRemoteCreateEntry(@Nullable android.service.credentials.CreateEntry);
+ method @NonNull public android.service.credentials.BeginCreateCredentialResponse.Builder setRemoteCreateEntry(@Nullable android.service.credentials.RemoteEntry);
}
public class BeginGetCredentialOption implements android.os.Parcelable {
@@ -40542,7 +40584,7 @@ package android.service.credentials {
method @NonNull public java.util.List<android.service.credentials.Action> getActions();
method @NonNull public java.util.List<android.service.credentials.Action> getAuthenticationActions();
method @NonNull public java.util.List<android.service.credentials.CredentialEntry> getCredentialEntries();
- method @Nullable public android.service.credentials.CredentialEntry getRemoteCredentialEntry();
+ method @Nullable public android.service.credentials.RemoteEntry getRemoteCredentialEntry();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.BeginGetCredentialResponse> CREATOR;
}
@@ -40556,12 +40598,14 @@ package android.service.credentials {
method @NonNull public android.service.credentials.BeginGetCredentialResponse.Builder setActions(@NonNull java.util.List<android.service.credentials.Action>);
method @NonNull public android.service.credentials.BeginGetCredentialResponse.Builder setAuthenticationActions(@NonNull java.util.List<android.service.credentials.Action>);
method @NonNull public android.service.credentials.BeginGetCredentialResponse.Builder setCredentialEntries(@NonNull java.util.List<android.service.credentials.CredentialEntry>);
- method @NonNull public android.service.credentials.BeginGetCredentialResponse.Builder setRemoteCredentialEntry(@Nullable android.service.credentials.CredentialEntry);
+ method @NonNull public android.service.credentials.BeginGetCredentialResponse.Builder setRemoteCredentialEntry(@Nullable android.service.credentials.RemoteEntry);
}
public final class CallingAppInfo implements android.os.Parcelable {
ctor public CallingAppInfo(@NonNull String, @NonNull android.content.pm.SigningInfo);
+ ctor public CallingAppInfo(@NonNull String, @NonNull android.content.pm.SigningInfo, @Nullable String);
method public int describeContents();
+ method @Nullable public String getOrigin();
method @NonNull public String getPackageName();
method @NonNull public android.content.pm.SigningInfo getSigningInfo();
method public void writeToParcel(@NonNull android.os.Parcel, int);
@@ -40624,14 +40668,22 @@ package android.service.credentials {
}
public final class GetCredentialRequest implements android.os.Parcelable {
- ctor public GetCredentialRequest(@NonNull android.service.credentials.CallingAppInfo, @NonNull android.credentials.CredentialOption);
+ ctor public GetCredentialRequest(@NonNull android.service.credentials.CallingAppInfo, @NonNull java.util.List<android.credentials.CredentialOption>);
method public int describeContents();
method @NonNull public android.service.credentials.CallingAppInfo getCallingAppInfo();
- method @NonNull public android.credentials.CredentialOption getCredentialOption();
+ method @NonNull public java.util.List<android.credentials.CredentialOption> getCredentialOptions();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.GetCredentialRequest> CREATOR;
}
+ public class RemoteEntry implements android.os.Parcelable {
+ ctor public RemoteEntry(@NonNull android.app.slice.Slice);
+ method public int describeContents();
+ method @NonNull public android.app.slice.Slice getSlice();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.RemoteEntry> CREATOR;
+ }
+
}
package android.service.dreams {
@@ -41442,9 +41494,9 @@ package android.speech {
method public void writeToParcel(@NonNull android.os.Parcel, int);
field public static final int CONFIDENCE_LEVEL_HIGH = 5; // 0x5
field public static final int CONFIDENCE_LEVEL_LOW = 1; // 0x1
- field public static final int CONFIDENCE_LEVEL_LOW_MEDIUM = 2; // 0x2
field public static final int CONFIDENCE_LEVEL_MEDIUM = 3; // 0x3
field public static final int CONFIDENCE_LEVEL_MEDIUM_HIGH = 4; // 0x4
+ field public static final int CONFIDENCE_LEVEL_MEDIUM_LOW = 2; // 0x2
field public static final int CONFIDENCE_LEVEL_UNKNOWN = 0; // 0x0
field @NonNull public static final android.os.Parcelable.Creator<android.speech.RecognitionPart> CREATOR;
}
@@ -42053,9 +42105,11 @@ package android.telecom {
}
public final class CallControl {
+ method public void answer(int, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallException>);
method public void disconnect(@NonNull android.telecom.DisconnectCause, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallException>);
method @NonNull public android.os.ParcelUuid getCallId();
method public void requestCallEndpointChange(@NonNull android.telecom.CallEndpoint, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallException>);
+ method public void sendEvent(@NonNull String, @NonNull android.os.Bundle);
method public void setActive(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallException>);
method public void setInactive(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallException>);
method public void startCallStreaming(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallException>);
@@ -42064,8 +42118,7 @@ package android.telecom {
public interface CallControlCallback {
method public void onAnswer(int, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method public void onCallStreamingStarted(@NonNull java.util.function.Consumer<java.lang.Boolean>);
- method public void onDisconnect(@NonNull java.util.function.Consumer<java.lang.Boolean>);
- method public void onReject(@NonNull java.util.function.Consumer<java.lang.Boolean>);
+ method public void onDisconnect(@NonNull android.telecom.DisconnectCause, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method public void onSetActive(@NonNull java.util.function.Consumer<java.lang.Boolean>);
method public void onSetInactive(@NonNull java.util.function.Consumer<java.lang.Boolean>);
}
@@ -42102,6 +42155,7 @@ package android.telecom {
method public void onAvailableCallEndpointsChanged(@NonNull java.util.List<android.telecom.CallEndpoint>);
method public void onCallEndpointChanged(@NonNull android.telecom.CallEndpoint);
method public void onCallStreamingFailed(int);
+ method public void onEvent(@NonNull String, @NonNull android.os.Bundle);
method public void onMuteStateChanged(boolean);
}
@@ -50381,12 +50435,6 @@ package android.view {
field public static final int VERTICAL_GRAVITY_MASK = 112; // 0x70
}
- public class HandwritingDelegateConfiguration {
- ctor public HandwritingDelegateConfiguration(@IdRes int, @NonNull Runnable);
- method public int getDelegatorViewId();
- method @NonNull public Runnable getInitiationCallback();
- }
-
public class HapticFeedbackConstants {
field public static final int CLOCK_TICK = 4; // 0x4
field public static final int CONFIRM = 16; // 0x10
@@ -51395,7 +51443,7 @@ package android.view {
public final class MotionPredictor {
ctor public MotionPredictor(@NonNull android.content.Context);
method public boolean isPredictionAvailable(int, int);
- method @NonNull public java.util.List<android.view.MotionEvent> predict(long);
+ method @Nullable public android.view.MotionEvent predict(long);
method public void record(@NonNull android.view.MotionEvent);
}
@@ -51984,6 +52032,8 @@ package android.view {
method @Nullable public CharSequence getAccessibilityPaneTitle();
method @IdRes public int getAccessibilityTraversalAfter();
method @IdRes public int getAccessibilityTraversalBefore();
+ method @Nullable public String getAllowedHandwritingDelegatePackageName();
+ method @Nullable public String getAllowedHandwritingDelegatorPackageName();
method public float getAlpha();
method public android.view.animation.Animation getAnimation();
method @Nullable public android.graphics.Matrix getAnimationMatrix();
@@ -52039,7 +52089,7 @@ package android.view {
method public float getHandwritingBoundsOffsetLeft();
method public float getHandwritingBoundsOffsetRight();
method public float getHandwritingBoundsOffsetTop();
- method @Nullable public android.view.HandwritingDelegateConfiguration getHandwritingDelegateConfiguration();
+ method @Nullable public Runnable getHandwritingDelegatorCallback();
method public final boolean getHasOverlappingRendering();
method public final int getHeight();
method public void getHitRect(android.graphics.Rect);
@@ -52177,7 +52227,7 @@ package android.view {
method public void invalidate();
method public void invalidateDrawable(@NonNull android.graphics.drawable.Drawable);
method public void invalidateOutline();
- method public boolean isAccessibilityDataPrivate();
+ method public boolean isAccessibilityDataSensitive();
method public boolean isAccessibilityFocused();
method public boolean isAccessibilityHeading();
method public boolean isActivated();
@@ -52195,6 +52245,7 @@ package android.view {
method public boolean isFocused();
method public final boolean isFocusedByDefault();
method public boolean isForceDarkAllowed();
+ method public boolean isHandwritingDelegate();
method public boolean isHapticFeedbackEnabled();
method public boolean isHardwareAccelerated();
method public boolean isHorizontalFadingEdgeEnabled();
@@ -52356,7 +52407,7 @@ package android.view {
method public void scrollTo(int, int);
method public void sendAccessibilityEvent(int);
method public void sendAccessibilityEventUnchecked(android.view.accessibility.AccessibilityEvent);
- method public void setAccessibilityDataPrivate(int);
+ method public void setAccessibilityDataSensitive(int);
method public void setAccessibilityDelegate(@Nullable android.view.View.AccessibilityDelegate);
method public void setAccessibilityHeading(boolean);
method public void setAccessibilityLiveRegion(int);
@@ -52365,6 +52416,8 @@ package android.view {
method public void setAccessibilityTraversalBefore(@IdRes int);
method public void setActivated(boolean);
method public void setAllowClickWhenDisabled(boolean);
+ method public void setAllowedHandwritingDelegatePackage(@Nullable String);
+ method public void setAllowedHandwritingDelegatorPackage(@Nullable String);
method public void setAlpha(@FloatRange(from=0.0, to=1.0) float);
method public void setAnimation(android.view.animation.Animation);
method public void setAnimationMatrix(@Nullable android.graphics.Matrix);
@@ -52407,7 +52460,7 @@ package android.view {
method public void setForegroundTintList(@Nullable android.content.res.ColorStateList);
method public void setForegroundTintMode(@Nullable android.graphics.PorterDuff.Mode);
method public void setHandwritingBoundsOffsets(float, float, float, float);
- method public void setHandwritingDelegateConfiguration(@Nullable android.view.HandwritingDelegateConfiguration);
+ method public void setHandwritingDelegatorCallback(@Nullable Runnable);
method public void setHapticFeedbackEnabled(boolean);
method public void setHasTransientState(boolean);
method public void setHorizontalFadingEdgeEnabled(boolean);
@@ -52420,6 +52473,7 @@ package android.view {
method public void setImportantForAutofill(int);
method public void setImportantForContentCapture(int);
method public void setIsCredential(boolean);
+ method public void setIsHandwritingDelegate(boolean);
method public void setKeepScreenOn(boolean);
method public void setKeyboardNavigationCluster(boolean);
method public void setLabelFor(@IdRes int);
@@ -52539,9 +52593,9 @@ package android.view {
method @CallSuper protected boolean verifyDrawable(@NonNull android.graphics.drawable.Drawable);
method @Deprecated public boolean willNotCacheDrawing();
method public boolean willNotDraw();
- field public static final int ACCESSIBILITY_DATA_PRIVATE_AUTO = 0; // 0x0
- field public static final int ACCESSIBILITY_DATA_PRIVATE_NO = 2; // 0x2
- field public static final int ACCESSIBILITY_DATA_PRIVATE_YES = 1; // 0x1
+ field public static final int ACCESSIBILITY_DATA_SENSITIVE_AUTO = 0; // 0x0
+ field public static final int ACCESSIBILITY_DATA_SENSITIVE_NO = 2; // 0x2
+ field public static final int ACCESSIBILITY_DATA_SENSITIVE_YES = 1; // 0x1
field public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 2; // 0x2
field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
field public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 1; // 0x1
@@ -54011,11 +54065,11 @@ package android.view.accessibility {
method public int getSpeechStateChangeTypes();
method public int getWindowChanges();
method public void initFromParcel(android.os.Parcel);
- method public boolean isAccessibilityDataPrivate();
+ method public boolean isAccessibilityDataSensitive();
method @Deprecated public static android.view.accessibility.AccessibilityEvent obtain(int);
method @Deprecated public static android.view.accessibility.AccessibilityEvent obtain(android.view.accessibility.AccessibilityEvent);
method @Deprecated public static android.view.accessibility.AccessibilityEvent obtain();
- method public void setAccessibilityDataPrivate(boolean);
+ method public void setAccessibilityDataSensitive(boolean);
method public void setAction(int);
method public void setContentChangeTypes(int);
method public void setEventTime(long);
@@ -54206,6 +54260,7 @@ package android.view.accessibility {
method public int getWindowId();
method public boolean hasRequestInitialAccessibilityFocus();
method public boolean hasRequestTouchPassthrough();
+ method public boolean isAccessibilityDataSensitive();
method public boolean isAccessibilityFocused();
method public boolean isCheckable();
method public boolean isChecked();
@@ -54242,6 +54297,7 @@ package android.view.accessibility {
method public boolean removeAction(android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction);
method public boolean removeChild(android.view.View);
method public boolean removeChild(android.view.View, int);
+ method public void setAccessibilityDataSensitive(boolean);
method public void setAccessibilityFocused(boolean);
method public void setAvailableExtraData(java.util.List<java.lang.String>);
method @Deprecated public void setBoundsInParent(android.graphics.Rect);
@@ -55618,6 +55674,8 @@ package android.view.inputmethod {
}
public final class InputMethodManager {
+ method public boolean acceptStylusHandwritingDelegation(@NonNull android.view.View);
+ method public boolean acceptStylusHandwritingDelegation(@NonNull android.view.View, @NonNull String);
method public void dispatchKeyEventFromInputMethod(@Nullable android.view.View, @NonNull android.view.KeyEvent);
method public void displayCompletions(android.view.View, android.view.inputmethod.CompletionInfo[]);
method @Nullable public android.view.inputmethod.InputMethodInfo getCurrentInputMethodInfo();
@@ -55639,6 +55697,8 @@ package android.view.inputmethod {
method public boolean isInputMethodSuppressingSpellChecker();
method public boolean isStylusHandwritingAvailable();
method @Deprecated public boolean isWatchingCursor(android.view.View);
+ method public void prepareStylusHandwritingDelegation(@NonNull android.view.View);
+ method public void prepareStylusHandwritingDelegation(@NonNull android.view.View, @NonNull String);
method public void restartInput(android.view.View);
method public void sendAppPrivateCommand(android.view.View, String, android.os.Bundle);
method @Deprecated public void setAdditionalInputMethodSubtypes(@NonNull String, @NonNull android.view.inputmethod.InputMethodSubtype[]);
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index c14de7029a16..05f31a5a8a86 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -173,6 +173,7 @@ package android {
field public static final String MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED = "android.permission.MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED";
field public static final String MANAGE_CARRIER_OEM_UNLOCK_STATE = "android.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE";
field public static final String MANAGE_CA_CERTIFICATES = "android.permission.MANAGE_CA_CERTIFICATES";
+ field public static final String MANAGE_CLIPBOARD_ACCESS_NOTIFICATION = "android.permission.MANAGE_CLIPBOARD_ACCESS_NOTIFICATION";
field public static final String MANAGE_CLOUDSEARCH = "android.permission.MANAGE_CLOUDSEARCH";
field public static final String MANAGE_CONTENT_CAPTURE = "android.permission.MANAGE_CONTENT_CAPTURE";
field public static final String MANAGE_CONTENT_SUGGESTIONS = "android.permission.MANAGE_CONTENT_SUGGESTIONS";
@@ -587,6 +588,7 @@ package android.app {
method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setMode(@NonNull String, int, @Nullable String, int);
method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setUidMode(@NonNull String, int, int);
method @RequiresPermission(value="android.permission.WATCH_APPOPS", conditional=true) public void startWatchingNoted(@NonNull String[], @NonNull android.app.AppOpsManager.OnOpNotedListener);
+ method @RequiresPermission(value="android.permission.WATCH_APPOPS", conditional=true) public void startWatchingNoted(@NonNull String[], @NonNull java.util.concurrent.Executor, @NonNull android.app.AppOpsManager.OnOpNotedListener);
method public void stopWatchingNoted(@NonNull android.app.AppOpsManager.OnOpNotedListener);
field public static final int HISTORY_FLAGS_ALL = 3; // 0x3
field public static final int HISTORY_FLAG_AGGREGATE = 1; // 0x1
@@ -842,6 +844,7 @@ package android.app {
method public int getPendingIntentBackgroundActivityStartMode();
method public boolean isDeferUntilActive();
method @Deprecated public boolean isPendingIntentBackgroundActivityLaunchAllowed();
+ method @Deprecated @NonNull public static android.app.BroadcastOptions makeBasic();
method @RequiresPermission(android.Manifest.permission.ACCESS_BROADCAST_RESPONSE_STATS) public void recordResponseEventWhileInBackground(@IntRange(from=0) long);
method @RequiresPermission(android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND) public void setBackgroundActivityStartsAllowed(boolean);
method @NonNull public android.app.BroadcastOptions setDeferUntilActive(boolean);
@@ -1696,7 +1699,7 @@ package android.app.backup {
method @RequiresPermission(android.Manifest.permission.BACKUP) public boolean isBackupEnabled();
method @RequiresPermission(android.Manifest.permission.BACKUP) public boolean isBackupServiceActive(android.os.UserHandle);
method @RequiresPermission(android.Manifest.permission.BACKUP) public String[] listAllTransports();
- method @NonNull public void reportDelayedRestoreResult(@NonNull android.app.backup.BackupRestoreEventLogger);
+ method public void reportDelayedRestoreResult(@NonNull android.app.backup.BackupRestoreEventLogger);
method @RequiresPermission(android.Manifest.permission.BACKUP) public int requestBackup(String[], android.app.backup.BackupObserver);
method @RequiresPermission(android.Manifest.permission.BACKUP) public int requestBackup(String[], android.app.backup.BackupObserver, android.app.backup.BackupManagerMonitor, int);
method @Deprecated public int requestRestore(android.app.backup.RestoreObserver, android.app.backup.BackupManagerMonitor);
@@ -3214,8 +3217,8 @@ package android.companion.virtual {
method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void close();
method @NonNull public android.content.Context createContext();
method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.companion.virtual.audio.VirtualAudioDevice createVirtualAudioDevice(@NonNull android.hardware.display.VirtualDisplay, @Nullable java.util.concurrent.Executor, @Nullable android.companion.virtual.audio.VirtualAudioDevice.AudioConfigurationChangeCallback);
- method @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, @Nullable android.view.Surface, int, @Nullable java.util.concurrent.Executor, @Nullable android.hardware.display.VirtualDisplay.Callback);
- method @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, @NonNull java.util.List<java.lang.String>, @Nullable android.view.Surface, int, @Nullable java.util.concurrent.Executor, @Nullable android.hardware.display.VirtualDisplay.Callback);
+ method @Deprecated @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, @Nullable android.view.Surface, int, @Nullable java.util.concurrent.Executor, @Nullable android.hardware.display.VirtualDisplay.Callback);
+ method @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull android.hardware.display.VirtualDisplayConfig, @Nullable java.util.concurrent.Executor, @Nullable android.hardware.display.VirtualDisplay.Callback);
method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualDpad createVirtualDpad(@NonNull android.hardware.input.VirtualDpadConfig);
method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualKeyboard createVirtualKeyboard(@NonNull android.hardware.input.VirtualKeyboardConfig);
method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualKeyboard createVirtualKeyboard(@NonNull android.hardware.display.VirtualDisplay, @NonNull String, int, int);
@@ -3244,7 +3247,6 @@ package android.companion.virtual {
method @NonNull public java.util.Set<android.content.ComponentName> getBlockedCrossTaskNavigations();
method public int getDefaultActivityPolicy();
method public int getDefaultNavigationPolicy();
- method public int getDefaultRecentsPolicy();
method public int getDevicePolicy(int);
method public int getLockState();
method @Nullable public String getName();
@@ -3261,8 +3263,8 @@ package android.companion.virtual {
field public static final int NAVIGATION_POLICY_DEFAULT_ALLOWED = 0; // 0x0
field public static final int NAVIGATION_POLICY_DEFAULT_BLOCKED = 1; // 0x1
field public static final int POLICY_TYPE_AUDIO = 1; // 0x1
+ field public static final int POLICY_TYPE_RECENTS = 2; // 0x2
field public static final int POLICY_TYPE_SENSORS = 0; // 0x0
- field public static final int RECENTS_POLICY_ALLOW_IN_HOST_DEVICE_RECENTS = 1; // 0x1
}
public static final class VirtualDeviceParams.Builder {
@@ -3275,7 +3277,6 @@ package android.companion.virtual {
method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setAudioRecordingSessionId(int);
method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setBlockedActivities(@NonNull java.util.Set<android.content.ComponentName>);
method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setBlockedCrossTaskNavigations(@NonNull java.util.Set<android.content.ComponentName>);
- method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setDefaultRecentsPolicy(int);
method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setDevicePolicy(int, int);
method @NonNull @RequiresPermission(value=android.Manifest.permission.ADD_ALWAYS_UNLOCKED_DISPLAY, conditional=true) public android.companion.virtual.VirtualDeviceParams.Builder setLockState(int);
method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setName(@NonNull String);
@@ -3344,10 +3345,15 @@ package android.companion.virtual.sensor {
public interface VirtualSensorCallback {
method public void onConfigurationChanged(@NonNull android.companion.virtual.sensor.VirtualSensor, boolean, @NonNull java.time.Duration, @NonNull java.time.Duration);
+ method public default void onDirectChannelConfigured(@IntRange(from=1) int, @NonNull android.companion.virtual.sensor.VirtualSensor, int, @IntRange(from=1) int);
+ method public default void onDirectChannelCreated(@IntRange(from=1) int, @NonNull android.os.SharedMemory);
+ method public default void onDirectChannelDestroyed(@IntRange(from=1) int);
}
public final class VirtualSensorConfig implements android.os.Parcelable {
method public int describeContents();
+ method public int getDirectChannelTypesSupported();
+ method public int getHighestDirectReportRateLevel();
method @NonNull public String getName();
method public int getType();
method @Nullable public String getVendor();
@@ -3358,6 +3364,8 @@ package android.companion.virtual.sensor {
public static final class VirtualSensorConfig.Builder {
ctor public VirtualSensorConfig.Builder(int, @NonNull String);
method @NonNull public android.companion.virtual.sensor.VirtualSensorConfig build();
+ method @NonNull public android.companion.virtual.sensor.VirtualSensorConfig.Builder setDirectChannelTypesSupported(int);
+ method @NonNull public android.companion.virtual.sensor.VirtualSensorConfig.Builder setHighestDirectReportRateLevel(int);
method @NonNull public android.companion.virtual.sensor.VirtualSensorConfig.Builder setVendor(@Nullable String);
}
@@ -3399,6 +3407,8 @@ package android.content {
}
public class ClipboardManager extends android.text.ClipboardManager {
+ method @RequiresPermission(android.Manifest.permission.MANAGE_CLIPBOARD_ACCESS_NOTIFICATION) public boolean areClipboardAccessNotificationsEnabled();
+ method @RequiresPermission(android.Manifest.permission.MANAGE_CLIPBOARD_ACCESS_NOTIFICATION) public void setClipboardAccessNotificationsEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.SET_CLIP_SOURCE) public void setPrimaryClipAsPackage(@NonNull android.content.ClipData, @NonNull String);
}
@@ -3860,15 +3870,15 @@ package android.content.pm {
method @NonNull public boolean canUserUninstall(@NonNull String, @NonNull android.os.UserHandle);
method @NonNull public abstract java.util.List<android.content.IntentFilter> getAllIntentFilters(@NonNull String);
method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_METADATA) public android.os.PersistableBundle getAppMetadata(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
- method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.pm.ApplicationInfo getApplicationInfoAsUser(@NonNull String, int, @NonNull android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException;
+ method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.pm.ApplicationInfo getApplicationInfoAsUser(@NonNull String, int, @NonNull android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException;
method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.pm.ApplicationInfo getApplicationInfoAsUser(@NonNull String, @NonNull android.content.pm.PackageManager.ApplicationInfoFlags, @NonNull android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException;
method @NonNull public android.content.pm.dex.ArtManager getArtManager();
- method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_SHARED_LIBRARIES) public java.util.List<android.content.pm.SharedLibraryInfo> getDeclaredSharedLibraries(@NonNull String, int);
+ method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_SHARED_LIBRARIES) public java.util.List<android.content.pm.SharedLibraryInfo> getDeclaredSharedLibraries(@NonNull String, int);
method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_SHARED_LIBRARIES) public java.util.List<android.content.pm.SharedLibraryInfo> getDeclaredSharedLibraries(@NonNull String, @NonNull android.content.pm.PackageManager.PackageInfoFlags);
method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public abstract String getDefaultBrowserPackageNameAsUser(int);
method @Nullable @RequiresPermission(android.Manifest.permission.SET_HARMFUL_APP_WARNINGS) public CharSequence getHarmfulAppWarning(@NonNull String);
method @Nullable public String getIncidentReportApproverPackageName();
- method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public abstract java.util.List<android.content.pm.PackageInfo> getInstalledPackagesAsUser(int, int);
+ method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public abstract java.util.List<android.content.pm.PackageInfo> getInstalledPackagesAsUser(int, int);
method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public java.util.List<android.content.pm.PackageInfo> getInstalledPackagesAsUser(@NonNull android.content.pm.PackageManager.PackageInfoFlags, int);
method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_INSTANT_APPS) public abstract android.graphics.drawable.Drawable getInstantAppIcon(String);
method @Nullable public abstract android.content.ComponentName getInstantAppInstallerComponent();
@@ -3882,13 +3892,13 @@ package android.content.pm {
method @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) public abstract void grantRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
method @Deprecated public abstract int installExistingPackage(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
method @Deprecated public abstract int installExistingPackage(@NonNull String, int) throws android.content.pm.PackageManager.NameNotFoundException;
- method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceiversAsUser(@NonNull android.content.Intent, int, android.os.UserHandle);
+ method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceiversAsUser(@NonNull android.content.Intent, int, android.os.UserHandle);
method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceiversAsUser(@NonNull android.content.Intent, @NonNull android.content.pm.PackageManager.ResolveInfoFlags, @NonNull android.os.UserHandle);
- method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryIntentActivitiesAsUser(@NonNull android.content.Intent, int, @NonNull android.os.UserHandle);
+ method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryIntentActivitiesAsUser(@NonNull android.content.Intent, int, @NonNull android.os.UserHandle);
method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryIntentActivitiesAsUser(@NonNull android.content.Intent, @NonNull android.content.pm.PackageManager.ResolveInfoFlags, @NonNull android.os.UserHandle);
- method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryIntentContentProvidersAsUser(@NonNull android.content.Intent, int, @NonNull android.os.UserHandle);
+ method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryIntentContentProvidersAsUser(@NonNull android.content.Intent, int, @NonNull android.os.UserHandle);
method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryIntentContentProvidersAsUser(@NonNull android.content.Intent, @NonNull android.content.pm.PackageManager.ResolveInfoFlags, @NonNull android.os.UserHandle);
- method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryIntentServicesAsUser(@NonNull android.content.Intent, int, @NonNull android.os.UserHandle);
+ method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryIntentServicesAsUser(@NonNull android.content.Intent, int, @NonNull android.os.UserHandle);
method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryIntentServicesAsUser(@NonNull android.content.Intent, @NonNull android.content.pm.PackageManager.ResolveInfoFlags, @NonNull android.os.UserHandle);
method public abstract void registerDexModule(@NonNull String, @Nullable android.content.pm.PackageManager.DexModuleRegisterCallback);
method @RequiresPermission("android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS") public abstract void removeOnPermissionsChangeListener(@NonNull android.content.pm.PackageManager.OnPermissionsChangedListener);
@@ -5117,7 +5127,7 @@ package android.hardware.input {
method @NonNull public android.hardware.input.VirtualTouchEvent build();
method @NonNull public android.hardware.input.VirtualTouchEvent.Builder setAction(int);
method @NonNull public android.hardware.input.VirtualTouchEvent.Builder setMajorAxisSize(@FloatRange(from=0.0f) float);
- method @NonNull public android.hardware.input.VirtualTouchEvent.Builder setPointerId(int);
+ method @NonNull public android.hardware.input.VirtualTouchEvent.Builder setPointerId(@IntRange(from=0, to=0x10 - 1) int);
method @NonNull public android.hardware.input.VirtualTouchEvent.Builder setPressure(@FloatRange(from=0.0f) float);
method @NonNull public android.hardware.input.VirtualTouchEvent.Builder setToolType(int);
method @NonNull public android.hardware.input.VirtualTouchEvent.Builder setX(float);
@@ -9111,8 +9121,7 @@ package android.media.tv.tuner.frontend {
method public int getProtocolCapability();
}
- public class IptvFrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings {
- method @NonNull public static android.media.tv.tuner.frontend.IptvFrontendSettings.Builder builder();
+ public final class IptvFrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings {
method @IntRange(from=0) public long getBitrate();
method @NonNull public String getContentUrl();
method @NonNull @Size(min=4, max=16) public byte[] getDstIpAddress();
@@ -9133,6 +9142,7 @@ package android.media.tv.tuner.frontend {
}
public static final class IptvFrontendSettings.Builder {
+ ctor public IptvFrontendSettings.Builder();
method @NonNull public android.media.tv.tuner.frontend.IptvFrontendSettings build();
method @NonNull public android.media.tv.tuner.frontend.IptvFrontendSettings.Builder setBitrate(@IntRange(from=0) long);
method @NonNull public android.media.tv.tuner.frontend.IptvFrontendSettings.Builder setContentUrl(@NonNull String);
@@ -9145,8 +9155,7 @@ package android.media.tv.tuner.frontend {
method @NonNull public android.media.tv.tuner.frontend.IptvFrontendSettings.Builder setSrcPort(int);
}
- public class IptvFrontendSettingsFec {
- method @NonNull public static android.media.tv.tuner.frontend.IptvFrontendSettingsFec.Builder builder();
+ public final class IptvFrontendSettingsFec {
method @IntRange(from=0) public int getFecColNum();
method @IntRange(from=0) public int getFecRowNum();
method public int getFecType();
@@ -9157,6 +9166,7 @@ package android.media.tv.tuner.frontend {
}
public static final class IptvFrontendSettingsFec.Builder {
+ ctor public IptvFrontendSettingsFec.Builder();
method @NonNull public android.media.tv.tuner.frontend.IptvFrontendSettingsFec build();
method @NonNull public android.media.tv.tuner.frontend.IptvFrontendSettingsFec.Builder setFecColNum(@IntRange(from=0) int);
method @NonNull public android.media.tv.tuner.frontend.IptvFrontendSettingsFec.Builder setFecRowNum(@IntRange(from=0) int);
@@ -9989,49 +9999,81 @@ package android.net.wifi.nl80211 {
package android.net.wifi.sharedconnectivity.app {
- public final class DeviceInfo implements android.os.Parcelable {
+ public final class HotspotNetwork implements android.os.Parcelable {
method public int describeContents();
- method @IntRange(from=0, to=100) public int getBatteryPercentage();
- method @IntRange(from=0, to=3) public int getConnectionStrength();
- method @NonNull public String getDeviceName();
- method public int getDeviceType();
- method @NonNull public String getModelName();
+ method public long getDeviceId();
+ method public int getHostNetworkType();
+ method @Nullable public String getHotspotBssid();
+ method @NonNull public java.util.Set<java.lang.Integer> getHotspotSecurityTypes();
+ method @Nullable public String getHotspotSsid();
+ method @NonNull public String getNetworkName();
+ method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo getNetworkProviderInfo();
method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.sharedconnectivity.app.DeviceInfo> CREATOR;
- field public static final int DEVICE_TYPE_LAPTOP = 3; // 0x3
- field public static final int DEVICE_TYPE_PHONE = 1; // 0x1
- field public static final int DEVICE_TYPE_TABLET = 2; // 0x2
- field public static final int DEVICE_TYPE_UNKNOWN = 0; // 0x0
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.sharedconnectivity.app.HotspotNetwork> CREATOR;
+ field public static final int NETWORK_TYPE_CELLULAR = 1; // 0x1
+ field public static final int NETWORK_TYPE_ETHERNET = 3; // 0x3
+ field public static final int NETWORK_TYPE_UNKNOWN = 0; // 0x0
+ field public static final int NETWORK_TYPE_WIFI = 2; // 0x2
}
- public static final class DeviceInfo.Builder {
- ctor public DeviceInfo.Builder();
- method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo build();
- method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo.Builder setBatteryPercentage(@IntRange(from=0, to=100) int);
- method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo.Builder setConnectionStrength(@IntRange(from=0, to=3) int);
- method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo.Builder setDeviceName(@NonNull String);
- method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo.Builder setDeviceType(int);
- method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo.Builder setModelName(@NonNull String);
+ public static final class HotspotNetwork.Builder {
+ ctor public HotspotNetwork.Builder();
+ method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder addHotspotSecurityType(int);
+ method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork build();
+ method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder setDeviceId(long);
+ method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder setHostNetworkType(int);
+ method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder setHotspotBssid(@NonNull String);
+ method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder setHotspotSsid(@NonNull String);
+ method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder setNetworkName(@NonNull String);
+ method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder setNetworkProviderInfo(@NonNull android.net.wifi.sharedconnectivity.app.NetworkProviderInfo);
+ }
+
+ public final class HotspotNetworkConnectionStatus implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public android.os.Bundle getExtras();
+ method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork getHotspotNetwork();
+ method public int getStatus();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int CONNECTION_STATUS_CONNECT_TO_HOTSPOT_FAILED = 9; // 0x9
+ field public static final int CONNECTION_STATUS_ENABLING_HOTSPOT = 1; // 0x1
+ field public static final int CONNECTION_STATUS_ENABLING_HOTSPOT_FAILED = 7; // 0x7
+ field public static final int CONNECTION_STATUS_ENABLING_HOTSPOT_TIMEOUT = 8; // 0x8
+ field public static final int CONNECTION_STATUS_NO_CELL_DATA = 6; // 0x6
+ field public static final int CONNECTION_STATUS_PROVISIONING_FAILED = 3; // 0x3
+ field public static final int CONNECTION_STATUS_TETHERING_TIMEOUT = 4; // 0x4
+ field public static final int CONNECTION_STATUS_TETHERING_UNSUPPORTED = 5; // 0x5
+ field public static final int CONNECTION_STATUS_UNKNOWN = 0; // 0x0
+ field public static final int CONNECTION_STATUS_UNKNOWN_ERROR = 2; // 0x2
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus> CREATOR;
+ }
+
+ public static final class HotspotNetworkConnectionStatus.Builder {
+ ctor public HotspotNetworkConnectionStatus.Builder();
+ method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus build();
+ method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus.Builder setExtras(@NonNull android.os.Bundle);
+ method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus.Builder setHotspotNetwork(@NonNull android.net.wifi.sharedconnectivity.app.HotspotNetwork);
+ method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus.Builder setStatus(int);
}
public final class KnownNetwork implements android.os.Parcelable {
method public int describeContents();
- method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo getDeviceInfo();
+ method @Nullable public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo getNetworkProviderInfo();
method public int getNetworkSource();
- method @NonNull public int[] getSecurityTypes();
+ method @NonNull public java.util.Set<java.lang.Integer> getSecurityTypes();
method @NonNull public String getSsid();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.sharedconnectivity.app.KnownNetwork> CREATOR;
- field public static final int NETWORK_SOURCE_CLOUD_SELF = 1; // 0x1
- field public static final int NETWORK_SOURCE_NEARBY_SELF = 0; // 0x0
+ field public static final int NETWORK_SOURCE_CLOUD_SELF = 2; // 0x2
+ field public static final int NETWORK_SOURCE_NEARBY_SELF = 1; // 0x1
+ field public static final int NETWORK_SOURCE_UNKNOWN = 0; // 0x0
}
public static final class KnownNetwork.Builder {
ctor public KnownNetwork.Builder();
+ method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetwork.Builder addSecurityType(int);
method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetwork build();
- method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetwork.Builder setDeviceInfo(@NonNull android.net.wifi.sharedconnectivity.app.DeviceInfo);
+ method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetwork.Builder setNetworkProviderInfo(@Nullable android.net.wifi.sharedconnectivity.app.NetworkProviderInfo);
method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetwork.Builder setNetworkSource(int);
- method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetwork.Builder setSecurityTypes(@NonNull int[]);
method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetwork.Builder setSsid(@NonNull String);
}
@@ -10055,24 +10097,56 @@ package android.net.wifi.sharedconnectivity.app {
method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus.Builder setStatus(int);
}
+ public final class NetworkProviderInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method @IntRange(from=0, to=100) public int getBatteryPercentage();
+ method @IntRange(from=0, to=3) public int getConnectionStrength();
+ method @NonNull public String getDeviceName();
+ method public int getDeviceType();
+ method @NonNull public String getModelName();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.sharedconnectivity.app.NetworkProviderInfo> CREATOR;
+ field public static final int DEVICE_TYPE_AUTO = 5; // 0x5
+ field public static final int DEVICE_TYPE_LAPTOP = 3; // 0x3
+ field public static final int DEVICE_TYPE_PHONE = 1; // 0x1
+ field public static final int DEVICE_TYPE_TABLET = 2; // 0x2
+ field public static final int DEVICE_TYPE_UNKNOWN = 0; // 0x0
+ field public static final int DEVICE_TYPE_WATCH = 4; // 0x4
+ }
+
+ public static final class NetworkProviderInfo.Builder {
+ ctor public NetworkProviderInfo.Builder(@NonNull String, @NonNull String);
+ method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo build();
+ method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.Builder setBatteryPercentage(@IntRange(from=0, to=100) int);
+ method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.Builder setConnectionStrength(@IntRange(from=0, to=3) int);
+ method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.Builder setDeviceName(@NonNull String);
+ method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.Builder setDeviceType(int);
+ method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.Builder setModelName(@NonNull String);
+ }
+
public interface SharedConnectivityClientCallback {
+ method public void onHotspotNetworkConnectionStatusChanged(@NonNull android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus);
+ method public void onHotspotNetworksUpdated(@NonNull java.util.List<android.net.wifi.sharedconnectivity.app.HotspotNetwork>);
method public void onKnownNetworkConnectionStatusChanged(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus);
method public void onKnownNetworksUpdated(@NonNull java.util.List<android.net.wifi.sharedconnectivity.app.KnownNetwork>);
method public void onRegisterCallbackFailed(@NonNull Exception);
method public void onServiceConnected();
method public void onServiceDisconnected();
method public void onSharedConnectivitySettingsChanged(@NonNull android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState);
- method public void onTetherNetworkConnectionStatusChanged(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus);
- method public void onTetherNetworksUpdated(@NonNull java.util.List<android.net.wifi.sharedconnectivity.app.TetherNetwork>);
}
public class SharedConnectivityManager {
- method public boolean connectKnownNetwork(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetwork);
- method public boolean connectTetherNetwork(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetwork);
- method public boolean disconnectTetherNetwork(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetwork);
- method public boolean forgetKnownNetwork(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetwork);
- method public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.sharedconnectivity.app.SharedConnectivityClientCallback);
- method public boolean unregisterCallback(@NonNull android.net.wifi.sharedconnectivity.app.SharedConnectivityClientCallback);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public boolean connectHotspotNetwork(@NonNull android.net.wifi.sharedconnectivity.app.HotspotNetwork);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public boolean connectKnownNetwork(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetwork);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public boolean disconnectHotspotNetwork(@NonNull android.net.wifi.sharedconnectivity.app.HotspotNetwork);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public boolean forgetKnownNetwork(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetwork);
+ method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus getHotspotNetworkConnectionStatus();
+ method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.List<android.net.wifi.sharedconnectivity.app.HotspotNetwork> getHotspotNetworks();
+ method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus getKnownNetworkConnectionStatus();
+ method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.List<android.net.wifi.sharedconnectivity.app.KnownNetwork> getKnownNetworks();
+ method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState getSettingsState();
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.sharedconnectivity.app.SharedConnectivityClientCallback);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public boolean unregisterCallback(@NonNull android.net.wifi.sharedconnectivity.app.SharedConnectivityClientCallback);
}
public final class SharedConnectivitySettingsState implements android.os.Parcelable {
@@ -10090,62 +10164,6 @@ package android.net.wifi.sharedconnectivity.app {
method @NonNull public android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState.Builder setInstantTetherEnabled(boolean);
}
- public final class TetherNetwork implements android.os.Parcelable {
- method public int describeContents();
- method public long getDeviceId();
- method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo getDeviceInfo();
- method @Nullable public String getHotspotBssid();
- method @Nullable public int[] getHotspotSecurityTypes();
- method @Nullable public String getHotspotSsid();
- method @NonNull public String getNetworkName();
- method public int getNetworkType();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.sharedconnectivity.app.TetherNetwork> CREATOR;
- field public static final int NETWORK_TYPE_CELLULAR = 1; // 0x1
- field public static final int NETWORK_TYPE_ETHERNET = 3; // 0x3
- field public static final int NETWORK_TYPE_UNKNOWN = 0; // 0x0
- field public static final int NETWORK_TYPE_WIFI = 2; // 0x2
- }
-
- public static final class TetherNetwork.Builder {
- ctor public TetherNetwork.Builder();
- method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork build();
- method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork.Builder setDeviceId(long);
- method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork.Builder setDeviceInfo(@NonNull android.net.wifi.sharedconnectivity.app.DeviceInfo);
- method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork.Builder setHotspotBssid(@NonNull String);
- method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork.Builder setHotspotSecurityTypes(@NonNull int[]);
- method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork.Builder setHotspotSsid(@NonNull String);
- method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork.Builder setNetworkName(@NonNull String);
- method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork.Builder setNetworkType(int);
- }
-
- public final class TetherNetworkConnectionStatus implements android.os.Parcelable {
- method public int describeContents();
- method @NonNull public android.os.Bundle getExtras();
- method public int getStatus();
- method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork getTetherNetwork();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field public static final int CONNECTION_STATUS_CONNECT_TO_HOTSPOT_FAILED = 9; // 0x9
- field public static final int CONNECTION_STATUS_ENABLING_HOTSPOT = 1; // 0x1
- field public static final int CONNECTION_STATUS_ENABLING_HOTSPOT_FAILED = 7; // 0x7
- field public static final int CONNECTION_STATUS_ENABLING_HOTSPOT_TIMEOUT = 8; // 0x8
- field public static final int CONNECTION_STATUS_NO_CELL_DATA = 6; // 0x6
- field public static final int CONNECTION_STATUS_PROVISIONING_FAILED = 3; // 0x3
- field public static final int CONNECTION_STATUS_TETHERING_TIMEOUT = 4; // 0x4
- field public static final int CONNECTION_STATUS_TETHERING_UNSUPPORTED = 5; // 0x5
- field public static final int CONNECTION_STATUS_UNKNOWN = 0; // 0x0
- field public static final int CONNECTION_STATUS_UNKNOWN_ERROR = 2; // 0x2
- field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus> CREATOR;
- }
-
- public static final class TetherNetworkConnectionStatus.Builder {
- ctor public TetherNetworkConnectionStatus.Builder();
- method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus build();
- method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus.Builder setExtras(@NonNull android.os.Bundle);
- method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus.Builder setStatus(int);
- method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus.Builder setTetherNetwork(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetwork);
- }
-
}
package android.net.wifi.sharedconnectivity.service {
@@ -10153,15 +10171,15 @@ package android.net.wifi.sharedconnectivity.service {
public abstract class SharedConnectivityService extends android.app.Service {
ctor public SharedConnectivityService();
method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
+ method public abstract void onConnectHotspotNetwork(@NonNull android.net.wifi.sharedconnectivity.app.HotspotNetwork);
method public abstract void onConnectKnownNetwork(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetwork);
- method public abstract void onConnectTetherNetwork(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetwork);
- method public abstract void onDisconnectTetherNetwork(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetwork);
+ method public abstract void onDisconnectHotspotNetwork(@NonNull android.net.wifi.sharedconnectivity.app.HotspotNetwork);
method public abstract void onForgetKnownNetwork(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetwork);
+ method public final void setHotspotNetworks(@NonNull java.util.List<android.net.wifi.sharedconnectivity.app.HotspotNetwork>);
method public final void setKnownNetworks(@NonNull java.util.List<android.net.wifi.sharedconnectivity.app.KnownNetwork>);
method public final void setSettingsState(@NonNull android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState);
- method public final void setTetherNetworks(@NonNull java.util.List<android.net.wifi.sharedconnectivity.app.TetherNetwork>);
+ method public final void updateHotspotNetworkConnectionStatus(@NonNull android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus);
method public final void updateKnownNetworkConnectionStatus(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus);
- method public final void updateTetherNetworkConnectionStatus(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus);
}
}
@@ -10202,6 +10220,14 @@ package android.os {
public class BatteryManager {
method @RequiresPermission(android.Manifest.permission.POWER_SAVER) public boolean setChargingStateUpdateDelayMillis(int);
+ field @RequiresPermission(android.Manifest.permission.BATTERY_STATS) public static final int BATTERY_PROPERTY_CHARGING_POLICY = 9; // 0x9
+ field @RequiresPermission(android.Manifest.permission.BATTERY_STATS) public static final int BATTERY_PROPERTY_FIRST_USAGE_DATE = 8; // 0x8
+ field @RequiresPermission(android.Manifest.permission.BATTERY_STATS) public static final int BATTERY_PROPERTY_MANUFACTURING_DATE = 7; // 0x7
+ field @RequiresPermission(android.Manifest.permission.BATTERY_STATS) public static final int BATTERY_PROPERTY_STATE_OF_HEALTH = 10; // 0xa
+ field public static final int CHARGING_POLICY_ADAPTIVE_AC = 3; // 0x3
+ field public static final int CHARGING_POLICY_ADAPTIVE_AON = 2; // 0x2
+ field public static final int CHARGING_POLICY_ADAPTIVE_LONGLIFE = 4; // 0x4
+ field public static final int CHARGING_POLICY_DEFAULT = 1; // 0x1
field public static final String EXTRA_EVENTS = "android.os.extra.EVENTS";
field public static final String EXTRA_EVENT_TIMESTAMP = "android.os.extra.EVENT_TIMESTAMP";
}
@@ -10934,7 +10960,6 @@ package android.os {
method @NonNull @RequiresPermission(anyOf={"android.permission.INTERACT_ACROSS_USERS", "android.permission.MANAGE_USERS"}) public java.util.Set<android.os.UserHandle> getVisibleUsers();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean hasRestrictedProfiles();
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean hasUserRestrictionForUser(@NonNull String, @NonNull android.os.UserHandle);
- method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isAdminUser();
method public boolean isCloneProfile();
method @Deprecated public boolean isCredentialSharableWithParent();
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isGuestUser();
@@ -13141,7 +13166,7 @@ package android.service.voice {
method @NonNull public android.service.voice.HotwordDetectedResult.Builder setScore(int);
}
- public abstract class HotwordDetectionService extends android.app.Service implements android.service.voice.SandboxedDetectionServiceBase {
+ public abstract class HotwordDetectionService extends android.app.Service implements android.service.voice.SandboxedDetectionInitializer {
ctor public HotwordDetectionService();
method @Deprecated public static int getMaxCustomInitializationStatus();
method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
@@ -13213,7 +13238,7 @@ package android.service.voice {
method @NonNull public android.service.voice.HotwordRejectedResult.Builder setConfidenceLevel(int);
}
- public interface SandboxedDetectionServiceBase {
+ public interface SandboxedDetectionInitializer {
method public static int getMaxCustomInitializationStatus();
method public void onUpdateState(@Nullable android.os.PersistableBundle, @Nullable android.os.SharedMemory, long, @Nullable java.util.function.IntConsumer);
field public static final int INITIALIZATION_STATUS_SUCCESS = 0; // 0x0
@@ -13235,24 +13260,20 @@ package android.service.voice {
field @NonNull public static final android.os.Parcelable.Creator<android.service.voice.UnknownFailure> CREATOR;
}
- public abstract class VisualQueryDetectionService extends android.app.Service implements android.service.voice.SandboxedDetectionServiceBase {
+ public abstract class VisualQueryDetectionService extends android.app.Service implements android.service.voice.SandboxedDetectionInitializer {
ctor public VisualQueryDetectionService();
+ method public final void finishQuery() throws java.lang.IllegalStateException;
+ method public final void gainedAttention();
+ method public final void lostAttention();
method @Nullable public android.os.IBinder onBind(@NonNull android.content.Intent);
- method public void onStartDetection(@NonNull android.service.voice.VisualQueryDetectionService.Callback);
+ method public void onStartDetection();
method public void onStopDetection();
method public void onUpdateState(@Nullable android.os.PersistableBundle, @Nullable android.os.SharedMemory, long, @Nullable java.util.function.IntConsumer);
+ method public final void rejectQuery() throws java.lang.IllegalStateException;
+ method public final void streamQuery(@NonNull String) throws java.lang.IllegalStateException;
field public static final String SERVICE_INTERFACE = "android.service.voice.VisualQueryDetectionService";
}
- public static final class VisualQueryDetectionService.Callback {
- ctor public VisualQueryDetectionService.Callback();
- method public void onAttentionGained();
- method public void onAttentionLost();
- method public void onQueryDetected(@NonNull String) throws java.lang.IllegalStateException;
- method public void onQueryFinished() throws java.lang.IllegalStateException;
- method public void onQueryRejected() throws java.lang.IllegalStateException;
- }
-
public final class VisualQueryDetectionServiceFailure extends android.service.voice.DetectorFailure {
method public int getErrorCode();
method public int getSuggestedAction();
@@ -13767,7 +13788,7 @@ package android.telecom {
field public static final String EXTRA_CALL_HAS_IN_BAND_RINGTONE = "android.telecom.extra.CALL_HAS_IN_BAND_RINGTONE";
field public static final String EXTRA_CALL_SOURCE = "android.telecom.extra.CALL_SOURCE";
field public static final String EXTRA_CALL_TECHNOLOGY_TYPE = "android.telecom.extra.CALL_TECHNOLOGY_TYPE";
- field public static final String EXTRA_CLEAR_MISSED_CALLS_INTENT = "android.telecom.extra.CLEAR_MISSED_CALLS_INTENT";
+ field @Deprecated public static final String EXTRA_CLEAR_MISSED_CALLS_INTENT = "android.telecom.extra.CLEAR_MISSED_CALLS_INTENT";
field public static final String EXTRA_CONNECTION_SERVICE = "android.telecom.extra.CONNECTION_SERVICE";
field public static final String EXTRA_CURRENT_TTY_MODE = "android.telecom.extra.CURRENT_TTY_MODE";
field public static final String EXTRA_IS_USER_INTENT_EMERGENCY_CALL = "android.telecom.extra.IS_USER_INTENT_EMERGENCY_CALL";
@@ -17265,9 +17286,9 @@ package android.view.accessibility {
public final class AccessibilityManager {
method public int getAccessibilityWindowId(@Nullable android.os.IBinder);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY) public void performAccessibilityShortcut();
- method @RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY) public boolean registerDisplayProxy(@NonNull android.view.accessibility.AccessibilityDisplayProxy);
+ method @RequiresPermission(allOf={android.Manifest.permission.MANAGE_ACCESSIBILITY, android.Manifest.permission.CREATE_VIRTUAL_DEVICE}) public boolean registerDisplayProxy(@NonNull android.view.accessibility.AccessibilityDisplayProxy);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY) public void registerSystemAction(@NonNull android.app.RemoteAction, int);
- method @RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY) public boolean unregisterDisplayProxy(@NonNull android.view.accessibility.AccessibilityDisplayProxy);
+ method @RequiresPermission(allOf={android.Manifest.permission.MANAGE_ACCESSIBILITY, android.Manifest.permission.CREATE_VIRTUAL_DEVICE}) public boolean unregisterDisplayProxy(@NonNull android.view.accessibility.AccessibilityDisplayProxy);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY) public void unregisterSystemAction(int);
}
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 675324fe6c28..777faa7fe5aa 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -145,7 +145,8 @@ package android.app {
method @RequiresPermission(android.Manifest.permission.DUMP) public void waitForBroadcastIdle();
field public static final long LOCK_DOWN_CLOSE_SYSTEM_DIALOGS = 174664365L; // 0xa692aadL
field public static final int PROCESS_CAPABILITY_ALL_IMPLICIT = 6; // 0x6
- field public static final int PROCESS_CAPABILITY_NETWORK = 8; // 0x8
+ field @Deprecated public static final int PROCESS_CAPABILITY_NETWORK = 8; // 0x8
+ field public static final int PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK = 8; // 0x8
field public static final int PROCESS_STATE_FOREGROUND_SERVICE = 4; // 0x4
field public static final int PROCESS_STATE_TOP = 2; // 0x2
field public static final int STOP_USER_ON_SWITCH_DEFAULT = -1; // 0xffffffff
@@ -725,6 +726,14 @@ package android.app.contentsuggestions {
}
+package android.app.job {
+
+ public class JobParameters implements android.os.Parcelable {
+ field public static final int INTERNAL_STOP_REASON_USER_UI_STOP = 11; // 0xb
+ }
+
+}
+
package android.app.prediction {
public final class AppPredictor {
@@ -922,7 +931,7 @@ package android.content.pm {
method @Nullable public String getDefaultTextClassifierPackageName();
method @RequiresPermission(android.Manifest.permission.INJECT_EVENTS) public android.os.IBinder getHoldLockToken();
method public abstract int getInstallReason(@NonNull String, @NonNull android.os.UserHandle);
- method @Deprecated @NonNull public abstract java.util.List<android.content.pm.ApplicationInfo> getInstalledApplicationsAsUser(int, int);
+ method @NonNull public abstract java.util.List<android.content.pm.ApplicationInfo> getInstalledApplicationsAsUser(int, int);
method @NonNull public java.util.List<android.content.pm.ApplicationInfo> getInstalledApplicationsAsUser(@NonNull android.content.pm.PackageManager.ApplicationInfoFlags, int);
method @Nullable public abstract String[] getNamesForUids(int[]);
method @NonNull public String getPermissionControllerPackageName();
@@ -1444,6 +1453,7 @@ package android.hardware.display {
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setUserDisabledHdrTypes(@NonNull int[]);
method @RequiresPermission(android.Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS) public boolean shouldAlwaysRespectAppRequestedMode();
field public static final String DISPLAY_CATEGORY_REAR = "android.hardware.display.category.REAR";
+ field public static final String HDR_OUTPUT_CONTROL_FLAG = "enable_hdr_output_control";
field public static final int SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS = 2; // 0x2
field public static final int SWITCHING_TYPE_NONE = 0; // 0x0
field public static final int SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY = 3; // 0x3
@@ -1947,12 +1957,21 @@ package android.net {
package android.net.wifi.sharedconnectivity.app {
public class SharedConnectivityManager {
+ method @Nullable public static android.net.wifi.sharedconnectivity.app.SharedConnectivityManager create(@NonNull android.content.Context, @NonNull String, @NonNull String);
method @Nullable public android.content.ServiceConnection getServiceConnection();
method public void setService(@Nullable android.os.IInterface);
}
}
+package android.net.wifi.sharedconnectivity.service {
+
+ public abstract class SharedConnectivityService extends android.app.Service {
+ method public void onBind();
+ }
+
+}
+
package android.os {
public final class BatteryStatsManager {
@@ -2162,6 +2181,7 @@ package android.os {
method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.content.pm.UserInfo createRestrictedProfile(@Nullable String);
method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.content.pm.UserInfo createUser(@Nullable String, @NonNull String, int);
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.os.UserHandle getBootUser();
+ method public int getDisplayIdAssignedToUser();
method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public java.util.Set<java.lang.String> getPreInstallableSystemPackages(@NonNull String);
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public String getUserType();
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public java.util.List<android.content.pm.UserInfo> getUsers(boolean, boolean, boolean);
@@ -2792,7 +2812,7 @@ package android.service.voice {
method @NonNull public android.service.voice.AlwaysOnHotwordDetector.EventPayload.Builder setKeyphraseRecognitionExtras(@NonNull java.util.List<android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionExtra>);
}
- public abstract class HotwordDetectionService extends android.app.Service implements android.service.voice.SandboxedDetectionServiceBase {
+ public abstract class HotwordDetectionService extends android.app.Service implements android.service.voice.SandboxedDetectionInitializer {
field public static final boolean ENABLE_PROXIMITY_RESULT = true;
}
@@ -3322,6 +3342,7 @@ package android.view {
field public static final int DISPLAY_IME_POLICY_FALLBACK_DISPLAY = 1; // 0x1
field public static final int DISPLAY_IME_POLICY_HIDE = 2; // 0x2
field public static final int DISPLAY_IME_POLICY_LOCAL = 0; // 0x0
+ field public static final int LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP = 600; // 0x258
}
public static class WindowManager.LayoutParams extends android.view.ViewGroup.LayoutParams implements android.os.Parcelable {
@@ -3528,6 +3549,8 @@ package android.view.inputmethod {
public final class InputMethodInfo implements android.os.Parcelable {
ctor public InputMethodInfo(@NonNull String, @NonNull String, @NonNull CharSequence, @NonNull String, boolean, @NonNull String);
ctor public InputMethodInfo(@NonNull String, @NonNull String, @NonNull CharSequence, @NonNull String, int);
+ field public static final int COMPONENT_NAME_MAX_LENGTH = 1000; // 0x3e8
+ field public static final int MAX_IMES_PER_PACKAGE = 20; // 0x14
}
public final class InputMethodManager {
@@ -3750,6 +3773,7 @@ package android.window {
public final class TaskFragmentInfo implements android.os.Parcelable {
method public boolean equalsForTaskFragmentOrganizer(@Nullable android.window.TaskFragmentInfo);
method @NonNull public java.util.List<android.os.IBinder> getActivities();
+ method @NonNull public java.util.List<android.os.IBinder> getActivitiesRequestedInTaskFragment();
method @NonNull public android.content.res.Configuration getConfiguration();
method @NonNull public android.os.IBinder getFragmentToken();
method @NonNull public android.graphics.Point getPositionInParent();
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 6422865c043a..3615435b7d75 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -198,6 +198,26 @@ import java.util.function.Consumer;
* possible for a node to contain outdated information because the window content may change at any
* time.
* </p>
+ * <h3>Drawing Accessibility Overlays</h3>
+ * <p>Accessibility services can draw overlays on top of existing screen contents.
+ * Accessibility overlays can be used to visually highlight items on the screen
+ * e.g. indicate the current item with accessibility focus.
+ * Overlays can also offer the user a way to interact with the service directly and quickly
+ * customize the service's behavior.</p>
+ * <p>Accessibility overlays can be attached to a particular window or to the display itself.
+ * Attaching an overlay to a window allows the overly to move, grow and shrink as the window does.
+ * The overlay will maintain the same relative position within the window bounds as the window
+ * moves. The overlay will also maintain the same relative position within the window bounds if
+ * the window is resized.
+ * To attach an overlay to a window, use {@link attachAccessibilityOverlayToWindow}.
+ * Attaching an overlay to the display means that the overlay is independent of the active
+ * windows on that display.
+ * To attach an overlay to a display, use {@link attachAccessibilityOverlayToDisplay}. </p>
+ * <p> When positioning an overlay that is attached to a window, the service must use window
+ * coordinates. In order to position an overlay on top of an existing UI element it is necessary
+ * to know the bounds of that element in window coordinates. To find the bounds in window
+ * coordinates of an element, find the corresponding {@link AccessibilityNodeInfo} as discussed
+ * above and call {@link AccessibilityNodeInfo#getBoundsInWindow}. </p>
* <h3>Notification strategy</h3>
* <p>
* All accessibility services are notified of all events they have requested, regardless of their
@@ -3421,22 +3441,28 @@ public abstract class AccessibilityService extends Service {
}
/**
- * Attaches a {@link android.view.SurfaceControl} containing an accessibility
+ * <p>Attaches a {@link android.view.SurfaceControl} containing an accessibility
* overlay to the
* specified display. This type of overlay should be used for content that does
* not need to
* track the location and size of Views in the currently active app e.g. service
* configuration
- * or general service UI. To remove this overlay and free the associated
+ * or general service UI.</p>
+ * <p>Generally speaking, an accessibility overlay will be a {@link android.view.View}.
+ * To embed the View into a {@link android.view.SurfaceControl}, create a
+ * {@link android.view.SurfaceControlViewHost} and attach the View using
+ * {@link android.view.SurfaceControlViewHost#setView}. Then obtain the SurfaceControl by
+ * calling <code> viewHost.getSurfacePackage().getSurfaceControl()</code>.</p>
+ * <p>To remove this overlay and free the associated
* resources, use
- * <code> new SurfaceControl.Transaction().reparent(sc, null).apply();</code>.
- * If the specified overlay has already been attached to the specified display
+ * <code> new SurfaceControl.Transaction().reparent(sc, null).apply();</code>.</p>
+ * <p>If the specified overlay has already been attached to the specified display
* this method does nothing.
* If the specified overlay has already been attached to a previous display this
* function will transfer the overlay to the new display.
* Services can attach multiple overlays. Use
* <code> new SurfaceControl.Transaction().setLayer(sc, layer).apply();</code>.
- * to coordinate the order of the overlays on screen.
+ * to coordinate the order of the overlays on screen.</p>
*
* @param displayId the display to which the SurfaceControl should be attached.
* @param sc the SurfaceControl containing the overlay content
@@ -3456,20 +3482,24 @@ public abstract class AccessibilityService extends Service {
}
/**
- * Attaches an accessibility overlay {@link android.view.SurfaceControl} to the
+ * <p>Attaches an accessibility overlay {@link android.view.SurfaceControl} to the
* specified
* window. This method should be used when you want the overlay to move and
- * resize as the parent
- * window moves and resizes. To remove this overlay and free the associated
- * resources, use
- * <code> new SurfaceControl.Transaction().reparent(sc, null).apply();</code>.
- * If the specified overlay has already been attached to the specified window
+ * resize as the parent window moves and resizes.</p>
+ * <p>Generally speaking, an accessibility overlay will be a {@link android.view.View}.
+ * To embed the View into a {@link android.view.SurfaceControl}, create a
+ * {@link android.view.SurfaceControlViewHost} and attach the View using
+ * {@link android.view.SurfaceControlViewHost#setView}. Then obtain the SurfaceControl by
+ * calling <code> viewHost.getSurfacePackage().getSurfaceControl()</code>.</p>
+ * <p>To remove this overlay and free the associated resources, use
+ * <code> new SurfaceControl.Transaction().reparent(sc, null).apply();</code>.</p>
+ * <p>If the specified overlay has already been attached to the specified window
* this method does nothing.
* If the specified overlay has already been attached to a previous window this
* function will transfer the overlay to the new window.
* Services can attach multiple overlays. Use
* <code> new SurfaceControl.Transaction().setLayer(sc, layer).apply();</code>.
- * to coordinate the order of the overlays on screen.
+ * to coordinate the order of the overlays on screen.</p>
*
* @param accessibilityWindowId The window id, from
* {@link AccessibilityWindowInfo#getId()}.
diff --git a/core/java/android/app/ActivityClient.java b/core/java/android/app/ActivityClient.java
index 44327af928cb..b35e87b541d3 100644
--- a/core/java/android/app/ActivityClient.java
+++ b/core/java/android/app/ActivityClient.java
@@ -598,6 +598,23 @@ public class ActivityClient {
}
/**
+ * Returns {@code true} if the activity was explicitly requested to be launched in the
+ * TaskFragment.
+ *
+ * @param activityToken The token of the Activity.
+ * @param taskFragmentToken The token of the TaskFragment.
+ */
+ public boolean isRequestedToLaunchInTaskFragment(IBinder activityToken,
+ IBinder taskFragmentToken) {
+ try {
+ return getActivityClientController().isRequestedToLaunchInTaskFragment(activityToken,
+ taskFragmentToken);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Shows or hides a Camera app compat toggle for stretched issues with the requested state.
*
* @param token The token for the window that needs a control.
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 8b6d7cbaa449..87fe215edd85 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -630,7 +630,7 @@ public class ActivityManager {
PROCESS_CAPABILITY_FOREGROUND_LOCATION,
PROCESS_CAPABILITY_FOREGROUND_CAMERA,
PROCESS_CAPABILITY_FOREGROUND_MICROPHONE,
- PROCESS_CAPABILITY_NETWORK,
+ PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK,
PROCESS_CAPABILITY_BFSL,
})
@Retention(RetentionPolicy.SOURCE)
@@ -751,9 +751,17 @@ public class ActivityManager {
@SystemApi
public static final int PROCESS_CAPABILITY_FOREGROUND_MICROPHONE = 1 << 2;
- /** @hide Process can access network despite any power saving resrictions */
+ /** @hide Process can access network despite any power saving restrictions */
@TestApi
- public static final int PROCESS_CAPABILITY_NETWORK = 1 << 3;
+ public static final int PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK = 1 << 3;
+ /**
+ * @hide
+ * @deprecated Use {@link #PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK} instead.
+ */
+ @TestApi
+ @Deprecated
+ public static final int PROCESS_CAPABILITY_NETWORK =
+ PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
/**
* Flag used to indicate whether an app is allowed to start a foreground service from the
@@ -783,7 +791,7 @@ public class ActivityManager {
public static final int PROCESS_CAPABILITY_ALL = PROCESS_CAPABILITY_FOREGROUND_LOCATION
| PROCESS_CAPABILITY_FOREGROUND_CAMERA
| PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
- | PROCESS_CAPABILITY_NETWORK
+ | PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK
| PROCESS_CAPABILITY_BFSL;
/**
@@ -802,7 +810,7 @@ public class ActivityManager {
pw.print((caps & PROCESS_CAPABILITY_FOREGROUND_LOCATION) != 0 ? 'L' : '-');
pw.print((caps & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0 ? 'C' : '-');
pw.print((caps & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0 ? 'M' : '-');
- pw.print((caps & PROCESS_CAPABILITY_NETWORK) != 0 ? 'N' : '-');
+ pw.print((caps & PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK) != 0 ? 'N' : '-');
pw.print((caps & PROCESS_CAPABILITY_BFSL) != 0 ? 'F' : '-');
}
@@ -811,7 +819,7 @@ public class ActivityManager {
sb.append((caps & PROCESS_CAPABILITY_FOREGROUND_LOCATION) != 0 ? 'L' : '-');
sb.append((caps & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0 ? 'C' : '-');
sb.append((caps & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0 ? 'M' : '-');
- sb.append((caps & PROCESS_CAPABILITY_NETWORK) != 0 ? 'N' : '-');
+ sb.append((caps & PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK) != 0 ? 'N' : '-');
sb.append((caps & PROCESS_CAPABILITY_BFSL) != 0 ? 'F' : '-');
}
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index b9f38d3c8907..d810f055e96e 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -968,14 +968,6 @@ public abstract class ActivityManagerInternal {
public abstract void stopForegroundServiceDelegate(@NonNull ServiceConnection connection);
/**
- * Called by PowerManager. Return whether a given procstate is allowed to hold
- * wake locks in deep doze. Because it's called with the power manager lock held, we can't
- * hold AM locks in it.
- * @hide
- */
- public abstract boolean canHoldWakeLocksInDeepDoze(int uid, int procstate);
-
- /**
* Same as {@link android.app.IActivityManager#startProfile(int userId)}, but it would succeed
* even if the profile is disabled - it should only be called by
* {@link com.android.server.devicepolicy.DevicePolicyManagerService} when starting a profile
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index b50245d14d3b..a3ada763265a 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -36,6 +36,7 @@ import static android.window.ConfigurationHelper.isDifferentDisplay;
import static android.window.ConfigurationHelper.shouldUpdateResources;
import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
+import static com.android.internal.os.SafeZipPathValidatorCallback.VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -49,6 +50,7 @@ import android.app.assist.AssistStructure;
import android.app.backup.BackupAgent;
import android.app.backup.BackupAnnotations.BackupDestination;
import android.app.backup.BackupAnnotations.OperationType;
+import android.app.compat.CompatChanges;
import android.app.servertransaction.ActivityLifecycleItem;
import android.app.servertransaction.ActivityLifecycleItem.LifecycleState;
import android.app.servertransaction.ActivityRelaunchItem;
@@ -206,6 +208,7 @@ import com.android.internal.content.ReferrerIntent;
import com.android.internal.os.BinderCallsStats;
import com.android.internal.os.BinderInternal;
import com.android.internal.os.RuntimeInit;
+import com.android.internal.os.SafeZipPathValidatorCallback;
import com.android.internal.os.SomeArgs;
import com.android.internal.policy.DecorView;
import com.android.internal.util.ArrayUtils;
@@ -219,6 +222,7 @@ import dalvik.system.AppSpecializationHooks;
import dalvik.system.CloseGuard;
import dalvik.system.VMDebug;
import dalvik.system.VMRuntime;
+import dalvik.system.ZipPathValidator;
import libcore.io.ForwardingOs;
import libcore.io.IoUtils;
@@ -554,9 +558,6 @@ public final class ActivityThread extends ClientTransactionHandler
boolean hideForNow;
Configuration createdConfig;
Configuration overrideConfig;
- // TODO(b/263402465): pass deviceId directly in LaunchActivityItem#execute
- // The deviceId assigned by the server when this activity was first started.
- int mDeviceId;
// Used for consolidating configs before sending on to Activity.
private Configuration tmpConfig = new Configuration();
// Callback used for updating activity override config and camera compat control state.
@@ -619,7 +620,7 @@ public final class ActivityThread extends ClientTransactionHandler
}
public ActivityClientRecord(IBinder token, Intent intent, int ident,
- ActivityInfo info, Configuration overrideConfig, int deviceId,
+ ActivityInfo info, Configuration overrideConfig,
String referrer, IVoiceInteractor voiceInteractor, Bundle state,
PersistableBundle persistentState, List<ResultInfo> pendingResults,
List<ReferrerIntent> pendingNewIntents, ActivityOptions activityOptions,
@@ -641,7 +642,6 @@ public final class ActivityThread extends ClientTransactionHandler
this.isForward = isForward;
this.profilerInfo = profilerInfo;
this.overrideConfig = overrideConfig;
- this.mDeviceId = deviceId;
this.packageInfo = client.getPackageInfoNoCheck(activityInfo.applicationInfo);
mActivityOptions = activityOptions;
mLaunchedFromBubble = launchedFromBubble;
@@ -1154,6 +1154,11 @@ public final class ActivityThread extends ClientTransactionHandler
}
@Override
+ public final void schedulePing(RemoteCallback pong) {
+ sendMessage(H.PING, pong);
+ }
+
+ @Override
public final void bindApplication(String processName, ApplicationInfo appInfo,
String sdkSandboxClientAppVolumeUuid, String sdkSandboxClientAppPackage,
ProviderInfoList providerList, ComponentName instrumentationName,
@@ -2154,6 +2159,7 @@ public final class ActivityThread extends ClientTransactionHandler
public static final int DUMP_GFXINFO = 165;
public static final int DUMP_RESOURCES = 166;
public static final int TIMEOUT_SERVICE = 167;
+ public static final int PING = 168;
public static final int INSTRUMENT_WITHOUT_RESTART = 170;
public static final int FINISH_INSTRUMENTATION_WITHOUT_RESTART = 171;
@@ -2209,6 +2215,7 @@ public final class ActivityThread extends ClientTransactionHandler
return "FINISH_INSTRUMENTATION_WITHOUT_RESTART";
case DUMP_RESOURCES: return "DUMP_RESOURCES";
case TIMEOUT_SERVICE: return "TIMEOUT_SERVICE";
+ case PING: return "PING";
}
}
return Integer.toString(code);
@@ -2292,6 +2299,9 @@ public final class ActivityThread extends ClientTransactionHandler
handleTimeoutService((IBinder) msg.obj, msg.arg1);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
+ case PING:
+ ((RemoteCallback) msg.obj).sendResult(null);
+ break;
case CONFIGURATION_CHANGED:
mConfigurationController.handleConfigurationChanged((Configuration) msg.obj);
break;
@@ -3872,7 +3882,7 @@ public final class ActivityThread extends ClientTransactionHandler
*/
@Override
public Activity handleLaunchActivity(ActivityClientRecord r,
- PendingTransactionActions pendingActions, Intent customIntent) {
+ PendingTransactionActions pendingActions, int deviceId, Intent customIntent) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
@@ -3885,7 +3895,7 @@ public final class ActivityThread extends ClientTransactionHandler
// Make sure we are running with the most recent config.
mConfigurationController.handleConfigurationChanged(null, null);
- updateDeviceIdForNonUIContexts(r.mDeviceId);
+ updateDeviceIdForNonUIContexts(deviceId);
if (localLOGV) Slog.v(
TAG, "Handling launch of " + r);
@@ -4621,7 +4631,7 @@ public final class ActivityThread extends ClientTransactionHandler
ActivityManager.getService());
if (!service.isUiContext()) { // WindowProviderService is a UI Context.
VirtualDeviceManager vdm = context.getSystemService(VirtualDeviceManager.class);
- if (mLastReportedDeviceId == VirtualDeviceManager.DEVICE_ID_DEFAULT
+ if (mLastReportedDeviceId == Context.DEVICE_ID_DEFAULT
|| vdm.isValidVirtualDeviceId(mLastReportedDeviceId)) {
service.updateDeviceId(mLastReportedDeviceId);
}
@@ -5942,7 +5952,7 @@ public final class ActivityThread extends ClientTransactionHandler
r.startsNotResumed = startsNotResumed;
r.overrideConfig = overrideConfig;
- handleLaunchActivity(r, pendingActions, customIntent);
+ handleLaunchActivity(r, pendingActions, mLastReportedDeviceId, customIntent);
}
@Override
@@ -6149,7 +6159,7 @@ public final class ActivityThread extends ClientTransactionHandler
private void updateDeviceIdForNonUIContexts(int deviceId) {
// Invalid device id is treated as a no-op.
- if (deviceId == VirtualDeviceManager.DEVICE_ID_INVALID) {
+ if (deviceId == Context.DEVICE_ID_INVALID) {
return;
}
if (deviceId == mLastReportedDeviceId) {
@@ -6703,6 +6713,11 @@ public final class ActivityThread extends ClientTransactionHandler
// Let libcore handle any compat changes after installing the list of compat changes.
AppSpecializationHooks.handleCompatChangesBeforeBindingApplication();
+ // Initialize the zip path validator callback depending on the targetSdk.
+ // This has to be after AppCompatCallbacks#install() so that the Compat
+ // checks work accordingly.
+ initZipPathValidatorCallback();
+
mBoundApplication = data;
mConfigurationController.setConfiguration(data.config);
mConfigurationController.setCompatConfiguration(data.config);
@@ -7070,6 +7085,18 @@ public final class ActivityThread extends ClientTransactionHandler
}
}
+ /**
+ * If targetSDK >= U: set the safe zip path validator callback which disallows dangerous zip
+ * entry names.
+ * Otherwise: clear the callback to the default validation.
+ */
+ private void initZipPathValidatorCallback() {
+ if (CompatChanges.isChangeEnabled(VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL)) {
+ ZipPathValidator.setCallback(new SafeZipPathValidatorCallback());
+ } else {
+ ZipPathValidator.clearCallback();
+ }
+ }
private void handleSetContentCaptureOptionsCallback(String packageName) {
if (mContentCaptureOptionsCallback != null) {
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 40ed269f57fd..9bf9e0c8eec3 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -25,6 +25,7 @@ import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.StringDef;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
@@ -1464,6 +1465,149 @@ public class AppOpsManager {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public static final int _NUM_OP = 134;
+ /**
+ * All app ops represented as strings.
+ *
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @StringDef(prefix = { "OPSTR_" }, value = {
+ OPSTR_COARSE_LOCATION,
+ OPSTR_FINE_LOCATION,
+ OPSTR_MONITOR_LOCATION,
+ OPSTR_MONITOR_HIGH_POWER_LOCATION,
+ OPSTR_GET_USAGE_STATS,
+ OPSTR_ACTIVATE_VPN,
+ OPSTR_READ_CONTACTS,
+ OPSTR_WRITE_CONTACTS,
+ OPSTR_READ_CALL_LOG,
+ OPSTR_WRITE_CALL_LOG,
+ OPSTR_READ_CALENDAR,
+ OPSTR_WRITE_CALENDAR,
+ OPSTR_CALL_PHONE,
+ OPSTR_READ_SMS,
+ OPSTR_RECEIVE_SMS,
+ OPSTR_RECEIVE_MMS,
+ OPSTR_RECEIVE_WAP_PUSH,
+ OPSTR_SEND_SMS,
+ OPSTR_CAMERA,
+ OPSTR_RECORD_AUDIO,
+ OPSTR_READ_PHONE_STATE,
+ OPSTR_ADD_VOICEMAIL,
+ OPSTR_USE_SIP,
+ OPSTR_PROCESS_OUTGOING_CALLS,
+ OPSTR_USE_FINGERPRINT,
+ OPSTR_BODY_SENSORS,
+ OPSTR_READ_CELL_BROADCASTS,
+ OPSTR_MOCK_LOCATION,
+ OPSTR_READ_EXTERNAL_STORAGE,
+ OPSTR_WRITE_EXTERNAL_STORAGE,
+ OPSTR_SYSTEM_ALERT_WINDOW,
+ OPSTR_WRITE_SETTINGS,
+ OPSTR_GET_ACCOUNTS,
+ OPSTR_READ_PHONE_NUMBERS,
+ OPSTR_PICTURE_IN_PICTURE,
+ OPSTR_INSTANT_APP_START_FOREGROUND,
+ OPSTR_ANSWER_PHONE_CALLS,
+ OPSTR_ACCEPT_HANDOVER,
+ OPSTR_GPS,
+ OPSTR_VIBRATE,
+ OPSTR_WIFI_SCAN,
+ OPSTR_POST_NOTIFICATION,
+ OPSTR_NEIGHBORING_CELLS,
+ OPSTR_WRITE_SMS,
+ OPSTR_RECEIVE_EMERGENCY_BROADCAST,
+ OPSTR_READ_ICC_SMS,
+ OPSTR_WRITE_ICC_SMS,
+ OPSTR_ACCESS_NOTIFICATIONS,
+ OPSTR_PLAY_AUDIO,
+ OPSTR_READ_CLIPBOARD,
+ OPSTR_WRITE_CLIPBOARD,
+ OPSTR_TAKE_MEDIA_BUTTONS,
+ OPSTR_TAKE_AUDIO_FOCUS,
+ OPSTR_AUDIO_MASTER_VOLUME,
+ OPSTR_AUDIO_VOICE_VOLUME,
+ OPSTR_AUDIO_RING_VOLUME,
+ OPSTR_AUDIO_MEDIA_VOLUME,
+ OPSTR_AUDIO_ALARM_VOLUME,
+ OPSTR_AUDIO_NOTIFICATION_VOLUME,
+ OPSTR_AUDIO_BLUETOOTH_VOLUME,
+ OPSTR_WAKE_LOCK,
+ OPSTR_MUTE_MICROPHONE,
+ OPSTR_TOAST_WINDOW,
+ OPSTR_PROJECT_MEDIA,
+ OPSTR_WRITE_WALLPAPER,
+ OPSTR_ASSIST_STRUCTURE,
+ OPSTR_ASSIST_SCREENSHOT,
+ OPSTR_TURN_SCREEN_ON,
+ OPSTR_RUN_IN_BACKGROUND,
+ OPSTR_AUDIO_ACCESSIBILITY_VOLUME,
+ OPSTR_REQUEST_INSTALL_PACKAGES,
+ OPSTR_RUN_ANY_IN_BACKGROUND,
+ OPSTR_CHANGE_WIFI_STATE,
+ OPSTR_REQUEST_DELETE_PACKAGES,
+ OPSTR_BIND_ACCESSIBILITY_SERVICE,
+ OPSTR_MANAGE_IPSEC_TUNNELS,
+ OPSTR_START_FOREGROUND,
+ OPSTR_BLUETOOTH_SCAN,
+ OPSTR_BLUETOOTH_CONNECT,
+ OPSTR_BLUETOOTH_ADVERTISE,
+ OPSTR_USE_BIOMETRIC,
+ OPSTR_ACTIVITY_RECOGNITION,
+ OPSTR_SMS_FINANCIAL_TRANSACTIONS,
+ OPSTR_READ_MEDIA_AUDIO,
+ OPSTR_WRITE_MEDIA_AUDIO,
+ OPSTR_READ_MEDIA_VIDEO,
+ OPSTR_WRITE_MEDIA_VIDEO,
+ OPSTR_READ_MEDIA_IMAGES,
+ OPSTR_WRITE_MEDIA_IMAGES,
+ OPSTR_LEGACY_STORAGE,
+ OPSTR_ACCESS_MEDIA_LOCATION,
+ OPSTR_ACCESS_ACCESSIBILITY,
+ OPSTR_READ_DEVICE_IDENTIFIERS,
+ OPSTR_QUERY_ALL_PACKAGES,
+ OPSTR_MANAGE_EXTERNAL_STORAGE,
+ OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED,
+ OPSTR_AUTO_REVOKE_MANAGED_BY_INSTALLER,
+ OPSTR_INTERACT_ACROSS_PROFILES,
+ OPSTR_ACTIVATE_PLATFORM_VPN,
+ OPSTR_LOADER_USAGE_STATS,
+ OPSTR_MANAGE_ONGOING_CALLS,
+ OPSTR_NO_ISOLATED_STORAGE,
+ OPSTR_PHONE_CALL_MICROPHONE,
+ OPSTR_PHONE_CALL_CAMERA,
+ OPSTR_RECORD_AUDIO_HOTWORD,
+ OPSTR_MANAGE_CREDENTIALS,
+ OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER,
+ OPSTR_RECORD_AUDIO_OUTPUT,
+ OPSTR_SCHEDULE_EXACT_ALARM,
+ OPSTR_FINE_LOCATION_SOURCE,
+ OPSTR_COARSE_LOCATION_SOURCE,
+ OPSTR_MANAGE_MEDIA,
+ OPSTR_UWB_RANGING,
+ OPSTR_NEARBY_WIFI_DEVICES,
+ OPSTR_ACTIVITY_RECOGNITION_SOURCE,
+ OPSTR_RECORD_INCOMING_PHONE_AUDIO,
+ OPSTR_ESTABLISH_VPN_SERVICE,
+ OPSTR_ESTABLISH_VPN_MANAGER,
+ OPSTR_ACCESS_RESTRICTED_SETTINGS,
+ OPSTR_RECEIVE_AMBIENT_TRIGGER_AUDIO,
+ OPSTR_READ_MEDIA_VISUAL_USER_SELECTED,
+ OPSTR_READ_WRITE_HEALTH_DATA,
+ OPSTR_RECEIVE_EXPLICIT_USER_INTERACTION_AUDIO,
+ OPSTR_RUN_USER_INITIATED_JOBS,
+ OPSTR_SYSTEM_EXEMPT_FROM_SUSPENSION,
+ OPSTR_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS,
+ OPSTR_FOREGROUND_SERVICE_SPECIAL_USE,
+ OPSTR_SYSTEM_EXEMPT_FROM_POWER_RESTRICTIONS,
+ OPSTR_SYSTEM_EXEMPT_FROM_HIBERNATION,
+ OPSTR_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION,
+ OPSTR_CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD,
+ OPSTR_BODY_SENSORS_WRIST_TEMPERATURE,
+ OPSTR_USE_FULL_SCREEN_INTENT,
+ })
+ public @interface AppOpString {}
+
/** Access to coarse location information. */
public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
/** Access to fine location information. */
@@ -7736,18 +7880,19 @@ public class AppOpsManager {
}
/**
- * Start watching for noted app ops. An app op may be immediate or long running.
- * Immediate ops are noted while long running ones are started and stopped. This
- * method allows registering a listener to be notified when an app op is noted. If
- * an op is being noted by any package you will get a callback. To change the
- * watched ops for a registered callback you need to unregister and register it again.
+ * Start watching for noted app ops.
*
- * <p> If you don't hold the {@link android.Manifest.permission#WATCH_APPOPS} permission
- * you can watch changes only for your UID.
+ * <p> Similar to {@link #startWatchingNoted(String[], Executor, OnOpNotedListener)}, but
+ * without an executor parameter.
*
- * @param ops The ops to watch.
- * @param callback Where to report changes.
+ * <p> Note that the listener will be called on the main thread using
+ * {@link Context.getMainThread()}. To specify the execution thread, use
+ * {@link #startWatchingNoted(String[], Executor, OnOpNotedListener)}.
+ *
+ * @param ops the ops to watch
+ * @param listener listener to notify when an app op is noted
*
+ * @see #startWatchingNoted(String[], Executor, OnOpNotedListener)
* @see #stopWatchingNoted(OnOpNotedListener)
* @see #noteOp(String, int, String, String, String)
*
@@ -7755,40 +7900,111 @@ public class AppOpsManager {
*/
@SystemApi
@RequiresPermission(value=Manifest.permission.WATCH_APPOPS, conditional=true)
- public void startWatchingNoted(@NonNull String[] ops, @NonNull OnOpNotedListener callback) {
+ public void startWatchingNoted(@NonNull @AppOpString String[] ops,
+ @NonNull OnOpNotedListener listener) {
final int[] intOps = new int[ops.length];
for (int i = 0; i < ops.length; i++) {
intOps[i] = strOpToOp(ops[i]);
}
- startWatchingNoted(intOps, callback);
+ startWatchingNoted(intOps, listener);
}
/**
- * Start watching for noted app ops. An app op may be immediate or long running.
- * Immediate ops are noted while long running ones are started and stopped. This
- * method allows registering a listener to be notified when an app op is noted. If
- * an op is being noted by any package you will get a callback. To change the
- * watched ops for a registered callback you need to unregister and register it again.
+ * Start watching for noted app ops.
*
- * <p> If you don't hold the {@link android.Manifest.permission#WATCH_APPOPS} permission
- * you can watch changes only for your UID.
+ * <p> An app op may be immediate or long-running. Immediate ops are noted while long-running
+ * ones are started and stopped.
*
- * This allows observing noted ops by their raw op codes instead of string op names.
+ * <p> This method allows registering a listener to be notified when an app op is noted. To
+ * change the watched ops for a registered callback you need to unregister and register it
+ * again.
*
- * @param ops The ops to watch.
- * @param callback Where to report changes.
+ * <p> If you don't hold the {@link android.Manifest.permission#WATCH_APPOPS} permission you can
+ * watch changes only for your UID.
+ *
+ * @param ops the ops to watch
+ * @param executor the executor on which the listener will be notified
+ * @param listener listener to notify when an app op is noted
+ *
+ * @see #startWatchingNoted(String[], OnOpNotedListener)
+ * @see #stopWatchingNoted(OnOpNotedListener)
+ * @see #noteOp(String, int, String, String, String)
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(value=Manifest.permission.WATCH_APPOPS, conditional=true)
+ public void startWatchingNoted(@NonNull @AppOpString String[] ops,
+ @CallbackExecutor @NonNull Executor executor, @NonNull OnOpNotedListener listener) {
+ final int[] intOps = new int[ops.length];
+ for (int i = 0; i < ops.length; i++) {
+ intOps[i] = strOpToOp(ops[i]);
+ }
+ startWatchingNoted(intOps, executor, listener);
+ }
+
+ /**
+ * Start watching for noted app ops.
+ *
+ * <p> Similar to {@link #startWatchingNoted(int[], Executor, OnOpNotedListener)}, but without
+ * an executor parameter.
+ *
+ * <p> This method is also similar to {@link #startWatchingNoted(String[], OnOpNotedListener)},
+ * but allows observing noted ops by their raw op codes instead of string op names.
+ *
+ * <p> Note that the listener will be called on the main thread using
+ * {@link Context.getMainThread()}. To specify the execution thread, use
+ * {@link {@link #startWatchingNoted(String[], Executor, OnOpNotedListener)}.
+ *
+ * @param ops the ops to watch
+ * @param listener listener to notify when an app op is noted
*
* @see #startWatchingActive(int[], OnOpActiveChangedListener)
* @see #startWatchingStarted(int[], OnOpStartedListener)
* @see #startWatchingNoted(String[], OnOpNotedListener)
+ * @see #startWatchingNoted(int[], Executor, OnOpNotedListener)
*
* @hide
*/
@RequiresPermission(value=Manifest.permission.WATCH_APPOPS, conditional=true)
- public void startWatchingNoted(@NonNull int[] ops, @NonNull OnOpNotedListener callback) {
+ public void startWatchingNoted(@NonNull int[] ops, @NonNull OnOpNotedListener listener) {
+ startWatchingNoted(ops, mContext.getMainExecutor(), listener);
+ }
+
+ /**
+ * Start watching for noted app ops.
+ *
+ * <p> This method is similar to
+ * {@link #startWatchingNoted(String[], Executor, OnOpNotedListener)}, but allows observing
+ * noted ops by their raw op codes instead of string op names.
+ *
+ * <p> An app op may be immediate or long-running. Immediate ops are noted while long-running
+ * ones are started and stopped.
+ *
+ * <p> This method allows registering a listener to be notified when an app op is noted. To
+ * change the watched ops for a registered callback you need to unregister and register it
+ * again.
+ *
+ * <p> If you don't hold the {@link android.Manifest.permission#WATCH_APPOPS} permission you
+ * can watch changes only for your UID.
+ *
+ * @param ops the ops to watch
+ * @param executor the executor on which the listener will be notified
+ * @param listener listener to notify when an app op is noted
+ *
+ * @see #startWatchingActive(int[], OnOpActiveChangedListener)
+ * @see #startWatchingStarted(int[], OnOpStartedListener)
+ * @see #startWatchingNoted(int[], Executor, OnOpNotedListener)
+ * @see #startWatchingNoted(String[], OnOpNotedListener)
+ *
+ * @hide
+ */
+ @RequiresPermission(value=Manifest.permission.WATCH_APPOPS, conditional=true)
+ public void startWatchingNoted(@NonNull int[] ops,
+ @CallbackExecutor @NonNull Executor executor, @NonNull OnOpNotedListener listener) {
IAppOpsNotedCallback cb;
synchronized (mNotedWatchers) {
- cb = mNotedWatchers.get(callback);
+ cb = mNotedWatchers.get(listener);
if (cb != null) {
return;
}
@@ -7796,13 +8012,21 @@ public class AppOpsManager {
@Override
public void opNoted(int op, int uid, String packageName, String attributionTag,
int flags, int mode) {
- if (sAppOpInfos[op].name != null) {
- callback.onOpNoted(sAppOpInfos[op].name, uid, packageName, attributionTag,
- flags, mode);
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> {
+ if (sAppOpInfos[op].name != null) {
+ listener.onOpNoted(sAppOpInfos[op].name, uid, packageName,
+ attributionTag,
+ flags, mode);
+ }
+ });
+ } finally {
+ Binder.restoreCallingIdentity(identity);
}
}
};
- mNotedWatchers.put(callback, cb);
+ mNotedWatchers.put(listener, cb);
}
try {
mService.startWatchingNoted(ops, cb);
diff --git a/core/java/android/app/ApplicationExitInfo.java b/core/java/android/app/ApplicationExitInfo.java
index c628ec4cc56c..d859f3f9e175 100644
--- a/core/java/android/app/ApplicationExitInfo.java
+++ b/core/java/android/app/ApplicationExitInfo.java
@@ -451,6 +451,15 @@ public final class ApplicationExitInfo implements Parcelable {
*/
public static final int SUBREASON_SDK_SANDBOX_DIED = 27;
+ /**
+ * The process was killed because it was an SDK sandbox process that was either not usable or
+ * was no longer being used; this would be set only when the reason is {@link #REASON_OTHER}.
+ *
+ * For internal use only.
+ * @hide
+ */
+ public static final int SUBREASON_SDK_SANDBOX_NOT_NEEDED = 28;
+
// If there is any OEM code which involves additional app kill reasons, it should
// be categorized in {@link #REASON_OTHER}, with subreason code starting from 1000.
diff --git a/core/java/android/app/BroadcastOptions.java b/core/java/android/app/BroadcastOptions.java
index f35bdfb83ca3..f48181b95892 100644
--- a/core/java/android/app/BroadcastOptions.java
+++ b/core/java/android/app/BroadcastOptions.java
@@ -60,7 +60,6 @@ public class BroadcastOptions extends ComponentOptions {
private String[] mRequireNoneOfPermissions;
private long mRequireCompatChangeId = CHANGE_INVALID;
private long mIdForResponseEvent;
- private @Nullable IntentFilter mRemoveMatchingFilter;
private @DeliveryGroupPolicy int mDeliveryGroupPolicy;
private @Nullable String mDeliveryGroupMatchingKey;
private @Nullable BundleMerger mDeliveryGroupExtrasMerger;
@@ -190,12 +189,6 @@ public class BroadcastOptions extends ComponentOptions {
"android:broadcast.idForResponseEvent";
/**
- * Corresponds to {@link #setRemoveMatchingFilter}.
- */
- private static final String KEY_REMOVE_MATCHING_FILTER =
- "android:broadcast.removeMatchingFilter";
-
- /**
* Corresponds to {@link #setDeliveryGroupPolicy(int)}.
*/
private static final String KEY_DELIVERY_GROUP_POLICY =
@@ -262,25 +255,21 @@ public class BroadcastOptions extends ComponentOptions {
* Creates a basic {@link BroadcastOptions} with no options initially set.
*
* @return an instance of {@code BroadcastOptions} against which options can be set
+ *
+ * @deprecated Use {@link BroadcastOptions#BroadcastOptions()} instead.
+ * @hide
*/
+ @Deprecated
+ @SystemApi
public static @NonNull BroadcastOptions makeBasic() {
BroadcastOptions opts = new BroadcastOptions();
return opts;
}
/**
- * {@hide}
- * @deprecated use {@link #setDeliveryGroupMatchingFilter(IntentFilter)} instead.
+ * Creates a new {@code BroadcastOptions} with no options initially set.
*/
- @Deprecated
- public static @NonNull BroadcastOptions makeRemovingMatchingFilter(
- @NonNull IntentFilter removeMatchingFilter) {
- BroadcastOptions opts = new BroadcastOptions();
- opts.setRemoveMatchingFilter(removeMatchingFilter);
- return opts;
- }
-
- private BroadcastOptions() {
+ public BroadcastOptions() {
super();
resetTemporaryAppAllowlist();
}
@@ -307,8 +296,6 @@ public class BroadcastOptions extends ComponentOptions {
mRequireNoneOfPermissions = opts.getStringArray(KEY_REQUIRE_NONE_OF_PERMISSIONS);
mRequireCompatChangeId = opts.getLong(KEY_REQUIRE_COMPAT_CHANGE_ID, CHANGE_INVALID);
mIdForResponseEvent = opts.getLong(KEY_ID_FOR_RESPONSE_EVENT);
- mRemoveMatchingFilter = opts.getParcelable(KEY_REMOVE_MATCHING_FILTER,
- IntentFilter.class);
mDeliveryGroupPolicy = opts.getInt(KEY_DELIVERY_GROUP_POLICY,
DELIVERY_GROUP_POLICY_ALL);
mDeliveryGroupMatchingKey = opts.getString(KEY_DELIVERY_GROUP_KEY);
@@ -789,31 +776,6 @@ public class BroadcastOptions extends ComponentOptions {
}
/**
- * When enqueuing this broadcast, remove all pending broadcasts previously
- * sent by this app which match the given filter.
- * <p>
- * For example, sending {@link Intent#ACTION_SCREEN_ON} would typically want
- * to remove any pending {@link Intent#ACTION_SCREEN_OFF} broadcasts.
- *
- * @hide
- * @deprecated use {@link #setDeliveryGroupMatchingFilter(IntentFilter)} instead.
- */
- @Deprecated
- public void setRemoveMatchingFilter(@NonNull IntentFilter removeMatchingFilter) {
- mRemoveMatchingFilter = Objects.requireNonNull(removeMatchingFilter);
- }
-
- /** @hide */
- public void clearRemoveMatchingFilter() {
- mRemoveMatchingFilter = null;
- }
-
- /** @hide */
- public @Nullable IntentFilter getRemoveMatchingFilter() {
- return mRemoveMatchingFilter;
- }
-
- /**
* Set delivery group policy for this broadcast to specify how multiple broadcasts belonging to
* the same delivery group has to be handled.
*
@@ -1084,9 +1046,6 @@ public class BroadcastOptions extends ComponentOptions {
if (mIdForResponseEvent != 0) {
b.putLong(KEY_ID_FOR_RESPONSE_EVENT, mIdForResponseEvent);
}
- if (mRemoveMatchingFilter != null) {
- b.putParcelable(KEY_REMOVE_MATCHING_FILTER, mRemoveMatchingFilter);
- }
if (mDeliveryGroupPolicy != DELIVERY_GROUP_POLICY_ALL) {
b.putInt(KEY_DELIVERY_GROUP_POLICY, mDeliveryGroupPolicy);
}
diff --git a/core/java/android/app/ClientTransactionHandler.java b/core/java/android/app/ClientTransactionHandler.java
index 6bb38e7294b0..49fb794a0a25 100644
--- a/core/java/android/app/ClientTransactionHandler.java
+++ b/core/java/android/app/ClientTransactionHandler.java
@@ -188,7 +188,7 @@ public abstract class ClientTransactionHandler {
/** Perform activity launch. */
public abstract Activity handleLaunchActivity(@NonNull ActivityClientRecord r,
- PendingTransactionActions pendingActions, Intent customIntent);
+ PendingTransactionActions pendingActions, int deviceId, Intent customIntent);
/** Perform activity start. */
public abstract void handleStartActivity(@NonNull ActivityClientRecord r,
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index a203ae241d39..4713a3135976 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -245,7 +245,7 @@ class ContextImpl extends Context {
@UnsupportedAppUsage
private @NonNull Resources mResources;
private @Nullable Display mDisplay; // may be null if invalid display or not initialized yet.
- private int mDeviceId = VirtualDeviceManager.DEVICE_ID_DEFAULT;
+ private int mDeviceId = Context.DEVICE_ID_DEFAULT;
/**
* If set to {@code true} the resources for this context will be configured for mDisplay which
@@ -1923,6 +1923,7 @@ class ContextImpl extends Context {
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
UserHandle user) {
+ // Keep this in sync with ActivityManagerLocal.startSdkSandboxService
try {
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
@@ -1964,6 +1965,7 @@ class ContextImpl extends Context {
}
private boolean stopServiceCommon(Intent service, UserHandle user) {
+ // // Keep this in sync with ActivityManagerLocal.stopSdkSandboxService
try {
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
@@ -2810,9 +2812,9 @@ class ContextImpl extends Context {
@Override
public @NonNull Context createDeviceContext(int deviceId) {
- if (deviceId != VirtualDeviceManager.DEVICE_ID_DEFAULT) {
+ if (deviceId != Context.DEVICE_ID_DEFAULT) {
VirtualDeviceManager vdm = getSystemService(VirtualDeviceManager.class);
- if (!vdm.isValidVirtualDeviceId(deviceId)) {
+ if (vdm == null || !vdm.isValidVirtualDeviceId(deviceId)) {
throw new IllegalArgumentException(
"Not a valid ID of the default device or any virtual device: " + deviceId);
}
@@ -3090,7 +3092,7 @@ class ContextImpl extends Context {
@Override
public void updateDeviceId(int updatedDeviceId) {
- if (updatedDeviceId != VirtualDeviceManager.DEVICE_ID_DEFAULT) {
+ if (updatedDeviceId != Context.DEVICE_ID_DEFAULT) {
VirtualDeviceManager vdm = getSystemService(VirtualDeviceManager.class);
if (!vdm.isValidVirtualDeviceId(updatedDeviceId)) {
throw new IllegalArgumentException(
diff --git a/core/java/android/app/IActivityClientController.aidl b/core/java/android/app/IActivityClientController.aidl
index 5136b2033d1c..a3c5e1c67e1b 100644
--- a/core/java/android/app/IActivityClientController.aidl
+++ b/core/java/android/app/IActivityClientController.aidl
@@ -181,4 +181,14 @@ interface IActivityClientController {
* that started the task.
*/
void enableTaskLocaleOverride(in IBinder token);
+
+ /**
+ * Return {@code true} if the activity was explicitly requested to be launched in the
+ * TaskFragment.
+ *
+ * @param activityToken The token of the Activity.
+ * @param taskFragmentToken The token of the TaskFragment.
+ */
+ boolean isRequestedToLaunchInTaskFragment(in IBinder activityToken,
+ in IBinder taskFragmentToken);
}
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index f653e132f7e3..5c38c42fe21f 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -341,12 +341,6 @@ interface IActivityManager {
in String message, boolean force, int exceptionTypeId);
void crashApplicationWithTypeWithExtras(int uid, int initialPid, in String packageName,
int userId, in String message, boolean force, int exceptionTypeId, in Bundle extras);
- /** @deprecated -- use getProviderMimeTypeAsync */
- @UnsupportedAppUsage(maxTargetSdk = 29, publicAlternatives =
- "Use {@link android.content.ContentResolver#getType} public API instead.")
- String getProviderMimeType(in Uri uri, int userId);
-
- oneway void getProviderMimeTypeAsync(in Uri uri, int userId, in RemoteCallback resultCallback);
oneway void getMimeTypeFilterAsync(in Uri uri, int userId, in RemoteCallback resultCallback);
// Cause the specified process to dump the specified heap.
boolean dumpHeap(in String process, int userId, boolean managed, boolean mallocInfo,
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index e97e711167b2..d62e15a94f89 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -65,12 +65,12 @@ import android.os.Debug;
import android.os.IBinder;
import android.os.IProgressListener;
import android.os.ParcelFileDescriptor;
+import android.os.RemoteCallback;
import android.os.StrictMode;
import android.os.WorkSource;
import android.service.voice.IVoiceInteractionSession;
import android.view.IRecentsAnimationRunner;
import android.view.IRemoteAnimationRunner;
-import android.view.IWindowFocusObserver;
import android.view.RemoteAnimationDefinition;
import android.view.RemoteAnimationAdapter;
import android.window.IWindowOrganizerController;
@@ -349,12 +349,13 @@ interface IActivityTaskManager {
/**
* Prepare the back navigation in the server. This setups the leashed for sysui to animate
* the back gesture and returns the data needed for the animation.
- * @param focusObserver a remote callback to nofify shell when the focused window lost focus.
+ * @param navigationObserver a remote callback to nofify shell when the focused window is gone,
+ or an unexpected transition has happened on the navigation target.
* @param adaptor a remote animation to be run for the back navigation plays the animation.
* @return Returns the back navigation info.
*/
android.window.BackNavigationInfo startBackNavigation(
- in IWindowFocusObserver focusObserver, in BackAnimationAdapter adaptor);
+ in RemoteCallback navigationObserver, in BackAnimationAdapter adaptor);
/**
* registers a callback to be invoked when the screen is captured.
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index dad9b435e9e7..4f77203c8c6f 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -172,4 +172,5 @@ oneway interface IApplicationThread {
in TranslationSpec targetSpec, in List<AutofillId> viewIds,
in UiTranslationSpec uiTranslationSpec);
void scheduleTimeoutService(IBinder token, int startId);
+ void schedulePing(in RemoteCallback pong);
}
diff --git a/core/java/android/app/LocaleConfig.java b/core/java/android/app/LocaleConfig.java
index 69693fc3977b..97cc706fbab6 100644
--- a/core/java/android/app/LocaleConfig.java
+++ b/core/java/android/app/LocaleConfig.java
@@ -38,7 +38,10 @@ import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.HashSet;
+import java.util.List;
import java.util.Locale;
import java.util.Set;
@@ -55,10 +58,10 @@ import java.util.Set;
*
* @attr ref android.R.styleable#LocaleConfig_Locale_name
* @attr ref android.R.styleable#AndroidManifestApplication_localeConfig
- *
- * <p>For more information about the LocaleConfig overridden by the application, see
- * TODO(b/261528306): add link to guide
*/
+// Add following to last Note: when guide is written:
+// For more information about the LocaleConfig overridden by the application, see TODO(b/261528306):
+// add link to guide
public class LocaleConfig implements Parcelable {
private static final String TAG = "LocaleConfig";
public static final String TAG_LOCALE_CONFIG = "locale-config";
@@ -263,6 +266,43 @@ public class LocaleConfig implements Parcelable {
};
/**
+ * Compare whether the LocaleConfig is the same.
+ *
+ * <p>If the elements of {@code mLocales} in LocaleConfig are the same but arranged in different
+ * positions, they are also considered to be the same LocaleConfig.
+ *
+ * @param other The {@link LocaleConfig} to compare for.
+ *
+ * @return true if the LocaleConfig is the same, false otherwise.
+ *
+ * @hide
+ */
+ public boolean isSameLocaleConfig(@Nullable LocaleConfig other) {
+ if (other == this) {
+ return true;
+ }
+
+ if (other != null) {
+ if (mStatus != other.mStatus) {
+ return false;
+ }
+ LocaleList otherLocales = other.mLocales;
+ if (mLocales == null && otherLocales == null) {
+ return true;
+ } else if (mLocales != null && otherLocales != null) {
+ List<String> hostStrList = Arrays.asList(mLocales.toLanguageTags().split(","));
+ List<String> targetStrList = Arrays.asList(
+ otherLocales.toLanguageTags().split(","));
+ Collections.sort(hostStrList);
+ Collections.sort(targetStrList);
+ return hostStrList.equals(targetStrList);
+ }
+ }
+
+ return false;
+ }
+
+ /**
* Compare whether the locale is existed in the {@code mLocales} of the LocaleConfig.
*
* @param locale The {@link Locale} to compare for.
diff --git a/core/java/android/app/LocaleManager.java b/core/java/android/app/LocaleManager.java
index b62f7664c760..bb9a95c03ba5 100644
--- a/core/java/android/app/LocaleManager.java
+++ b/core/java/android/app/LocaleManager.java
@@ -198,13 +198,14 @@ public class LocaleManager {
* the override config, and stored in a system file for future access.
*
* <p><b>Note:</b> Using this function, applications can update their list of supported
- * locales while running, without an update of the application’s software. For more
- * information, see TODO(b/261528306): add link to guide.
+ * locales while running, without an update of the application’s software.
*
* <p>Applications can remove the override LocaleConfig with a {@code null} object.
*
* @param localeConfig the desired {@link LocaleConfig} for the calling app.
*/
+ // Add following to last Note: when guide is written:
+ // For more information, see TODO(b/261528306): add link to guide.
@UserHandleAware
public void setOverrideLocaleConfig(@Nullable LocaleConfig localeConfig) {
try {
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 87c77c2e8602..440ee202cc5b 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -5249,17 +5249,17 @@ public class Notification implements Parcelable
boolean hasSecondLine = showProgress;
if (p.hasTitle()) {
contentView.setViewVisibility(p.mTitleViewId, View.VISIBLE);
- contentView.setTextViewText(p.mTitleViewId, processTextSpans(p.title));
+ contentView.setTextViewText(p.mTitleViewId, processTextSpans(p.mTitle));
setTextViewColorPrimary(contentView, p.mTitleViewId, p);
} else if (p.mTitleViewId != R.id.title) {
// This alternate title view ID is not cleared by resetStandardTemplate
contentView.setViewVisibility(p.mTitleViewId, View.GONE);
contentView.setTextViewText(p.mTitleViewId, null);
}
- if (p.text != null && p.text.length() != 0
+ if (p.mText != null && p.mText.length() != 0
&& (!showProgress || p.mAllowTextWithProgress)) {
contentView.setViewVisibility(p.mTextViewId, View.VISIBLE);
- contentView.setTextViewText(p.mTextViewId, processTextSpans(p.text));
+ contentView.setTextViewText(p.mTextViewId, processTextSpans(p.mText));
setTextViewColorSecondary(contentView, p.mTextViewId, p);
hasSecondLine = true;
} else if (p.mTextViewId != R.id.text) {
@@ -5533,20 +5533,20 @@ public class Notification implements Parcelable
if (p.mHideSubText) {
return false;
}
- CharSequence summaryText = p.summaryText;
- if (summaryText == null && mStyle != null && mStyle.mSummaryTextSet
+ CharSequence headerText = p.mSubText;
+ if (headerText == null && mStyle != null && mStyle.mSummaryTextSet
&& mStyle.hasSummaryInHeader()) {
- summaryText = mStyle.mSummaryText;
+ headerText = mStyle.mSummaryText;
}
- if (summaryText == null
+ if (headerText == null
&& mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N
&& mN.extras.getCharSequence(EXTRA_INFO_TEXT) != null) {
- summaryText = mN.extras.getCharSequence(EXTRA_INFO_TEXT);
+ headerText = mN.extras.getCharSequence(EXTRA_INFO_TEXT);
}
- if (!TextUtils.isEmpty(summaryText)) {
+ if (!TextUtils.isEmpty(headerText)) {
// TODO: Remove the span entirely to only have the string with propper formating.
contentView.setTextViewText(R.id.header_text, processTextSpans(
- processLegacyText(summaryText)));
+ processLegacyText(headerText)));
setTextViewColorSecondary(contentView, R.id.header_text, p);
contentView.setViewVisibility(R.id.header_text, View.VISIBLE);
if (hasTextToLeft) {
@@ -5566,9 +5566,9 @@ public class Notification implements Parcelable
if (p.mHideSubText) {
return false;
}
- if (!TextUtils.isEmpty(p.headerTextSecondary)) {
+ if (!TextUtils.isEmpty(p.mHeaderTextSecondary)) {
contentView.setTextViewText(R.id.header_text_secondary, processTextSpans(
- processLegacyText(p.headerTextSecondary)));
+ processLegacyText(p.mHeaderTextSecondary)));
setTextViewColorSecondary(contentView, R.id.header_text_secondary, p);
contentView.setViewVisibility(R.id.header_text_secondary, View.VISIBLE);
if (hasTextToLeft) {
@@ -5758,7 +5758,7 @@ public class Notification implements Parcelable
List<Notification.Action> nonContextualActions = getNonContextualActions();
int numActions = Math.min(nonContextualActions.size(), MAX_ACTION_BUTTONS);
- boolean emphazisedMode = mN.fullScreenIntent != null
+ boolean emphasizedMode = mN.fullScreenIntent != null
|| p.mCallStyleActions
|| ((mN.flags & FLAG_FSI_REQUESTED_BUT_DENIED) != 0);
@@ -5771,7 +5771,7 @@ public class Notification implements Parcelable
big.setInt(R.id.actions, "setCollapsibleIndentDimen",
R.dimen.call_notification_collapsible_indent);
}
- big.setBoolean(R.id.actions, "setEmphasizedMode", emphazisedMode);
+ big.setBoolean(R.id.actions, "setEmphasizedMode", emphasizedMode);
if (numActions > 0 && !p.mHideActions) {
big.setViewVisibility(R.id.actions_container, View.VISIBLE);
big.setViewVisibility(R.id.actions, View.VISIBLE);
@@ -5783,12 +5783,12 @@ public class Notification implements Parcelable
boolean actionHasValidInput = hasValidRemoteInput(action);
validRemoteInput |= actionHasValidInput;
- final RemoteViews button = generateActionButton(action, emphazisedMode, p);
- if (actionHasValidInput && !emphazisedMode) {
+ final RemoteViews button = generateActionButton(action, emphasizedMode, p);
+ if (actionHasValidInput && !emphasizedMode) {
// Clear the drawable
button.setInt(R.id.action0, "setBackgroundResource", 0);
}
- if (emphazisedMode && i > 0) {
+ if (emphasizedMode && i > 0) {
// Clear start margin from non-first buttons to reduce the gap between them.
// (8dp remaining gap is from all buttons' standard 4dp inset).
button.setViewLayoutMarginDimen(R.id.action0, RemoteViews.MARGIN_START, 0);
@@ -6175,7 +6175,7 @@ public class Notification implements Parcelable
.viewType(StandardTemplateParams.VIEW_TYPE_MINIMIZED)
.highlightExpander(false)
.fillTextsFrom(this);
- if (!useRegularSubtext || TextUtils.isEmpty(p.summaryText)) {
+ if (!useRegularSubtext || TextUtils.isEmpty(p.mSubText)) {
p.summaryText(createSummaryText());
}
RemoteViews header = makeNotificationHeader(p);
@@ -7192,7 +7192,7 @@ public class Notification implements Parcelable
checkBuilder();
if (mBigContentTitle != null) {
- p.title = mBigContentTitle;
+ p.mTitle = mBigContentTitle;
}
return mBuilder.applyStandardTemplateWithActions(layoutId, p, result);
@@ -7475,10 +7475,10 @@ public class Notification implements Parcelable
Resources resources = context.getResources();
boolean isLowRam = ActivityManager.isLowRamDeviceStatic();
if (mPictureIcon != null) {
- int maxPictureWidth = resources.getDimensionPixelSize(isLowRam
+ int maxPictureHeight = resources.getDimensionPixelSize(isLowRam
? R.dimen.notification_big_picture_max_height_low_ram
: R.dimen.notification_big_picture_max_height);
- int maxPictureHeight = resources.getDimensionPixelSize(isLowRam
+ int maxPictureWidth = resources.getDimensionPixelSize(isLowRam
? R.dimen.notification_big_picture_max_width_low_ram
: R.dimen.notification_big_picture_max_width);
mPictureIcon.scaleDownIfNecessary(maxPictureWidth, maxPictureHeight);
@@ -12455,10 +12455,10 @@ public class Notification implements Parcelable
boolean mAllowTextWithProgress;
int mTitleViewId;
int mTextViewId;
- CharSequence title;
- CharSequence text;
- CharSequence headerTextSecondary;
- CharSequence summaryText;
+ @Nullable CharSequence mTitle;
+ @Nullable CharSequence mText;
+ @Nullable CharSequence mHeaderTextSecondary;
+ @Nullable CharSequence mSubText;
int maxRemoteInputHistory = Style.MAX_REMOTE_INPUT_HISTORY_LINES;
boolean allowColorization = true;
boolean mHighlightExpander = false;
@@ -12480,10 +12480,10 @@ public class Notification implements Parcelable
mAllowTextWithProgress = false;
mTitleViewId = R.id.title;
mTextViewId = R.id.text;
- title = null;
- text = null;
- summaryText = null;
- headerTextSecondary = null;
+ mTitle = null;
+ mText = null;
+ mSubText = null;
+ mHeaderTextSecondary = null;
maxRemoteInputHistory = Style.MAX_REMOTE_INPUT_HISTORY_LINES;
allowColorization = true;
mHighlightExpander = false;
@@ -12491,7 +12491,7 @@ public class Notification implements Parcelable
}
final boolean hasTitle() {
- return !TextUtils.isEmpty(title) && !mHideTitle;
+ return !TextUtils.isEmpty(mTitle) && !mHideTitle;
}
final StandardTemplateParams viewType(int viewType) {
@@ -12564,23 +12564,23 @@ public class Notification implements Parcelable
return this;
}
- final StandardTemplateParams title(CharSequence title) {
- this.title = title;
+ final StandardTemplateParams title(@Nullable CharSequence title) {
+ this.mTitle = title;
return this;
}
- final StandardTemplateParams text(CharSequence text) {
- this.text = text;
+ final StandardTemplateParams text(@Nullable CharSequence text) {
+ this.mText = text;
return this;
}
- final StandardTemplateParams summaryText(CharSequence text) {
- this.summaryText = text;
+ final StandardTemplateParams summaryText(@Nullable CharSequence text) {
+ this.mSubText = text;
return this;
}
- final StandardTemplateParams headerTextSecondary(CharSequence text) {
- this.headerTextSecondary = text;
+ final StandardTemplateParams headerTextSecondary(@Nullable CharSequence text) {
+ this.mHeaderTextSecondary = text;
return this;
}
@@ -12607,9 +12607,9 @@ public class Notification implements Parcelable
final StandardTemplateParams fillTextsFrom(Builder b) {
Bundle extras = b.mN.extras;
- this.title = b.processLegacyText(extras.getCharSequence(EXTRA_TITLE));
- this.text = b.processLegacyText(extras.getCharSequence(EXTRA_TEXT));
- this.summaryText = extras.getCharSequence(EXTRA_SUB_TEXT);
+ this.mTitle = b.processLegacyText(extras.getCharSequence(EXTRA_TITLE));
+ this.mText = b.processLegacyText(extras.getCharSequence(EXTRA_TEXT));
+ this.mSubText = extras.getCharSequence(EXTRA_SUB_TEXT);
return this;
}
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 91efa755e4c9..d2f2c3c4e95a 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -873,7 +873,7 @@ public class NotificationManager {
* permission to your manifest, and use
* {@link android.provider.Settings#ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT}.
*/
- public boolean canSendFullScreenIntent() {
+ public boolean canUseFullScreenIntent() {
final int result = PermissionChecker.checkPermissionForPreflight(mContext,
android.Manifest.permission.USE_FULL_SCREEN_INTENT,
mContext.getAttributionSource());
diff --git a/core/java/android/app/StartForegroundCalledOnStoppedServiceException.java b/core/java/android/app/StartForegroundCalledOnStoppedServiceException.java
new file mode 100644
index 000000000000..55885a65a265
--- /dev/null
+++ b/core/java/android/app/StartForegroundCalledOnStoppedServiceException.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.app;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Exception thrown when {@link Service#startForeground} is called on a service that's not
+ * actually started.
+ */
+public final class StartForegroundCalledOnStoppedServiceException
+ extends IllegalStateException implements Parcelable {
+ /**
+ * Constructor.
+ */
+ public StartForegroundCalledOnStoppedServiceException(@NonNull String message) {
+ super(message);
+ }
+
+ StartForegroundCalledOnStoppedServiceException(@NonNull Parcel source) {
+ super(source.readString());
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeString(getMessage());
+ }
+
+ public static final @NonNull Creator<StartForegroundCalledOnStoppedServiceException>
+ CREATOR = new Creator<StartForegroundCalledOnStoppedServiceException>() {
+ @NonNull
+ public StartForegroundCalledOnStoppedServiceException createFromParcel(
+ Parcel source) {
+ return new StartForegroundCalledOnStoppedServiceException(source);
+ }
+
+ @NonNull
+ public StartForegroundCalledOnStoppedServiceException[] newArray(int size) {
+ return new StartForegroundCalledOnStoppedServiceException[size];
+ }
+ };
+}
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 6d80a44d3d60..dbba0c6f5e50 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -509,7 +509,7 @@ public final class SystemServiceRegistry {
new ServiceFetcher<InputManager>() {
@Override
public InputManager getService(ContextImpl ctx) {
- return InputManager.getInstance(ctx);
+ return InputManager.getInstance(ctx.getOuterContext());
}});
registerService(Context.DISPLAY_SERVICE, DisplayManager.class,
@@ -877,6 +877,10 @@ public final class SystemServiceRegistry {
@Override
public VirtualDeviceManager createService(ContextImpl ctx)
throws ServiceNotFoundException {
+ if (!ctx.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_COMPANION_DEVICE_SETUP)) {
+ return null;
+ }
IVirtualDeviceManager service = IVirtualDeviceManager.Stub.asInterface(
ServiceManager.getServiceOrThrow(Context.VIRTUAL_DEVICE_SERVICE));
return new VirtualDeviceManager(service, ctx.getOuterContext());
@@ -1648,6 +1652,7 @@ public final class SystemServiceRegistry {
case Context.ETHERNET_SERVICE:
case Context.CONTEXTHUB_SERVICE:
case Context.VIRTUALIZATION_SERVICE:
+ case Context.VIRTUAL_DEVICE_SERVICE:
return null;
}
Slog.wtf(TAG, "Manager wrapper not available: " + name);
diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java
index 5a2f2616dc13..303ada0fec9c 100644
--- a/core/java/android/app/TaskInfo.java
+++ b/core/java/android/app/TaskInfo.java
@@ -453,6 +453,7 @@ public class TaskInfo {
&& Objects.equals(shouldDockBigOverlays, that.shouldDockBigOverlays)
&& Objects.equals(displayCutoutInsets, that.displayCutoutInsets)
&& getWindowingMode() == that.getWindowingMode()
+ && configuration.uiMode == that.configuration.uiMode
&& Objects.equals(taskDescription, that.taskDescription)
&& isFocused == that.isFocused
&& isVisible == that.isVisible
@@ -481,6 +482,7 @@ public class TaskInfo {
.equals(that.configuration.windowConfiguration.getBounds()))
&& (!hasCompatUI() || configuration.getLayoutDirection()
== that.configuration.getLayoutDirection())
+ && (!hasCompatUI() || configuration.uiMode == that.configuration.uiMode)
&& (!hasCompatUI() || isVisible == that.isVisible);
}
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index e750f498248a..5848521b3045 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -1091,7 +1091,6 @@ public class BackupManager {
*
* @hide
*/
- @NonNull
@SystemApi
public void reportDelayedRestoreResult(@NonNull BackupRestoreEventLogger logger) {
checkServiceBinder();
diff --git a/core/java/android/app/backup/BackupTransport.java b/core/java/android/app/backup/BackupTransport.java
index f56c8c3b0bdb..dcac59c19df4 100644
--- a/core/java/android/app/backup/BackupTransport.java
+++ b/core/java/android/app/backup/BackupTransport.java
@@ -656,11 +656,14 @@ public class BackupTransport {
}
/**
- * Ask the transport for a {@link IBackupManagerMonitor} instance which will be used by the
+ * Ask the transport for a {@link BackupManagerMonitor} instance which will be used by the
* framework to report logging events back to the transport.
*
* <p>Backups requested from outside the framework may pass in a monitor with the request,
* however backups initiated by the framework will call this method to retrieve one.
+ *
+ * @return {@link BackupManagerMonitor} or {@code null} if the transport implementation does not
+ * wish to receive the logging events.
*/
@Nullable
public BackupManagerMonitor getBackupManagerMonitor() {
diff --git a/core/java/android/app/servertransaction/LaunchActivityItem.java b/core/java/android/app/servertransaction/LaunchActivityItem.java
index 3d0aa2540068..5833f1b87254 100644
--- a/core/java/android/app/servertransaction/LaunchActivityItem.java
+++ b/core/java/android/app/servertransaction/LaunchActivityItem.java
@@ -96,11 +96,11 @@ public class LaunchActivityItem extends ClientTransactionItem {
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
- mOverrideConfig, mDeviceId, mReferrer, mVoiceInteractor, mState, mPersistentState,
+ mOverrideConfig, mReferrer, mVoiceInteractor, mState, mPersistentState,
mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo,
client, mAssistToken, mShareableActivityToken, mLaunchedFromBubble,
mTaskFragmentToken);
- client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
+ client.handleLaunchActivity(r, pendingActions, mDeviceId, null /* customIntent */);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
diff --git a/core/java/android/app/servertransaction/TransactionExecutor.java b/core/java/android/app/servertransaction/TransactionExecutor.java
index c8f7d100a398..bfab61f3ae90 100644
--- a/core/java/android/app/servertransaction/TransactionExecutor.java
+++ b/core/java/android/app/servertransaction/TransactionExecutor.java
@@ -32,6 +32,7 @@ import static android.app.servertransaction.TransactionExecutorHelper.transactio
import android.app.ActivityThread.ActivityClientRecord;
import android.app.ClientTransactionHandler;
+import android.content.Context;
import android.os.IBinder;
import android.util.IntArray;
import android.util.Slog;
@@ -218,7 +219,7 @@ public class TransactionExecutor {
switch (state) {
case ON_CREATE:
mTransactionHandler.handleLaunchActivity(r, mPendingActions,
- null /* customIntent */);
+ Context.DEVICE_ID_INVALID, null /* customIntent */);
break;
case ON_START:
mTransactionHandler.handleStartActivity(r, mPendingActions,
diff --git a/core/java/android/app/timedetector/TimeDetector.java b/core/java/android/app/timedetector/TimeDetector.java
index 50a7da1cede5..5ee10a50568d 100644
--- a/core/java/android/app/timedetector/TimeDetector.java
+++ b/core/java/android/app/timedetector/TimeDetector.java
@@ -115,6 +115,20 @@ public interface TimeDetector {
String SHELL_COMMAND_CONFIRM_TIME = "confirm_time";
/**
+ * A shell command that clears the network time signal used by {@link
+ * SystemClock#currentNetworkTimeClock()}.
+ * @hide
+ */
+ String SHELL_COMMAND_CLEAR_SYSTEM_CLOCK_NETWORK_TIME = "clear_system_clock_network_time";
+
+ /**
+ * A shell command that sets the network time signal used by {@link
+ * SystemClock#currentNetworkTimeClock()}.
+ * @hide
+ */
+ String SHELL_COMMAND_SET_SYSTEM_CLOCK_NETWORK_TIME = "set_system_clock_network_time";
+
+ /**
* A shared utility method to create a {@link ManualTimeSuggestion}.
*
* @hide
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index de4f619392c1..a522cc04eff1 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -801,6 +801,119 @@ public final class CompanionDeviceManager {
}
/**
+ * Listener for any changes to {@link com.android.server.companion.transport.Transport}.
+ *
+ * @hide
+ */
+ public interface OnTransportsChangedListener {
+ /**
+ * Invoked when a change occurs to any of the transports
+ *
+ * @param associations all the associations which have connected transports
+ */
+ void onTransportsChanged(@NonNull List<AssociationInfo> associations);
+ }
+
+ /**
+ * Register a listener for any changes to
+ * {@link com.android.server.companion.transport.Transport}. Your app will receive a callback to
+ * {@link OnTransportsChangedListener} immediately with all the existing transports.
+ *
+ * @hide
+ */
+ public void addOnTransportsChangedListener(
+ @NonNull Executor executor, @NonNull OnTransportsChangedListener listener) {
+ final OnTransportsChangedListenerProxy proxy = new OnTransportsChangedListenerProxy(
+ executor, listener);
+ try {
+ mService.addOnTransportsChangedListener(proxy);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Unregister a listener to stop receiving any changes to
+ * {@link com.android.server.companion.transport.Transport}.
+ *
+ * @hide
+ */
+ public void removeOnTransportsChangedListener(
+ @NonNull OnTransportsChangedListener listener) {
+ final OnTransportsChangedListenerProxy proxy = new OnTransportsChangedListenerProxy(
+ null, listener);
+ try {
+ mService.removeOnTransportsChangedListener(proxy);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Send a message to remote devices
+ *
+ * @hide
+ */
+ public void sendMessage(int messageType, byte[] data, int[] associationIds) {
+ try {
+ mService.sendMessage(messageType, data, associationIds);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Listener when a message is received for the registered message type
+ *
+ * @see #addOnMessageReceivedListener(Executor, int, OnMessageReceivedListener)
+ *
+ * @hide
+ */
+ public interface OnMessageReceivedListener {
+ /**
+ * Called when a message is received
+ */
+ void onMessageReceived(int associationId, byte[] data);
+ }
+
+ /**
+ * Register a listener to receive callbacks when a message is received by the given type
+ *
+ * @see com.android.server.companion.transport.Transport for supported message types
+ *
+ * @hide
+ */
+ public void addOnMessageReceivedListener(@NonNull Executor executor, int messageType,
+ OnMessageReceivedListener listener) {
+ final OnMessageReceivedListenerProxy proxy = new OnMessageReceivedListenerProxy(
+ executor, listener);
+ try {
+ mService.addOnMessageReceivedListener(messageType, proxy);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Unregister a listener to stop receiving callbacks when a message is received by the given
+ * type
+ *
+ * @see com.android.server.companion.transport.Transport for supported message types
+ *
+ * @hide
+ */
+ public void removeOnMessageReceivedListener(int messageType,
+ OnMessageReceivedListener listener) {
+ final OnMessageReceivedListenerProxy proxy = new OnMessageReceivedListenerProxy(
+ null, listener);
+ try {
+ mService.removeOnMessageReceivedListener(messageType, proxy);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Checks whether the bluetooth device represented by the mac address was recently associated
* with the companion app. This allows these devices to skip the Bluetooth pairing dialog if
* their pairing variant is {@link BluetoothDevice#PAIRING_VARIANT_CONSENT}.
@@ -1277,6 +1390,40 @@ public final class CompanionDeviceManager {
}
}
+ private static class OnTransportsChangedListenerProxy
+ extends IOnTransportsChangedListener.Stub {
+ private final Executor mExecutor;
+ private final OnTransportsChangedListener mListener;
+
+ private OnTransportsChangedListenerProxy(Executor executor,
+ OnTransportsChangedListener listener) {
+ mExecutor = executor;
+ mListener = listener;
+ }
+
+ @Override
+ public void onTransportsChanged(@NonNull List<AssociationInfo> associations) {
+ mExecutor.execute(() -> mListener.onTransportsChanged(associations));
+ }
+ }
+
+ private static class OnMessageReceivedListenerProxy
+ extends IOnMessageReceivedListener.Stub {
+ private final Executor mExecutor;
+ private final OnMessageReceivedListener mListener;
+
+ private OnMessageReceivedListenerProxy(Executor executor,
+ OnMessageReceivedListener listener) {
+ mExecutor = executor;
+ mListener = listener;
+ }
+
+ @Override
+ public void onMessageReceived(int associationId, byte[] data) {
+ mExecutor.execute(() -> mListener.onMessageReceived(associationId, data));
+ }
+ }
+
private static class SystemDataTransferCallbackProxy extends ISystemDataTransferCallback.Stub {
private final Executor mExecutor;
private final OutcomeReceiver<Void, CompanionException> mCallback;
diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl
index cb4baca73ba0..b5e2670e5299 100644
--- a/core/java/android/companion/ICompanionDeviceManager.aidl
+++ b/core/java/android/companion/ICompanionDeviceManager.aidl
@@ -19,6 +19,8 @@ package android.companion;
import android.app.PendingIntent;
import android.companion.IAssociationRequestCallback;
import android.companion.IOnAssociationsChangedListener;
+import android.companion.IOnMessageReceivedListener;
+import android.companion.IOnTransportsChangedListener;
import android.companion.ISystemDataTransferCallback;
import android.companion.AssociationInfo;
import android.companion.AssociationRequest;
@@ -67,6 +69,16 @@ interface ICompanionDeviceManager {
void removeOnAssociationsChangedListener(IOnAssociationsChangedListener listener, int userId);
+ void addOnTransportsChangedListener(IOnTransportsChangedListener listener);
+
+ void removeOnTransportsChangedListener(IOnTransportsChangedListener listener);
+
+ void sendMessage(int messageType, in byte[] data, in int[] associationIds);
+
+ void addOnMessageReceivedListener(int messageType, IOnMessageReceivedListener listener);
+
+ void removeOnMessageReceivedListener(int messageType, IOnMessageReceivedListener listener);
+
void notifyDeviceAppeared(int associationId);
void notifyDeviceDisappeared(int associationId);
diff --git a/core/java/android/companion/IOnMessageReceivedListener.aidl b/core/java/android/companion/IOnMessageReceivedListener.aidl
new file mode 100644
index 000000000000..17f03f80996e
--- /dev/null
+++ b/core/java/android/companion/IOnMessageReceivedListener.aidl
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2023 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 per missions and
+ * limitations under the License.
+ */
+
+package android.companion;
+
+/** @hide */
+interface IOnMessageReceivedListener {
+
+ oneway void onMessageReceived(int associationId, in byte[] data);
+} \ No newline at end of file
diff --git a/core/java/android/companion/IOnTransportsChangedListener.aidl b/core/java/android/companion/IOnTransportsChangedListener.aidl
new file mode 100644
index 000000000000..a10147627a9d
--- /dev/null
+++ b/core/java/android/companion/IOnTransportsChangedListener.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2023 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 per missions and
+ * limitations under the License.
+ */
+
+package android.companion;
+
+import android.companion.AssociationInfo;
+
+/** @hide */
+interface IOnTransportsChangedListener {
+
+ oneway void onTransportsChanged(in List<AssociationInfo> associations);
+} \ No newline at end of file
diff --git a/core/java/android/companion/virtual/VirtualDevice.java b/core/java/android/companion/virtual/VirtualDevice.java
index f3f433540ef7..4a09186570e0 100644
--- a/core/java/android/companion/virtual/VirtualDevice.java
+++ b/core/java/android/companion/virtual/VirtualDevice.java
@@ -18,6 +18,7 @@ package android.companion.virtual;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
@@ -38,9 +39,9 @@ public final class VirtualDevice implements Parcelable {
* @hide
*/
public VirtualDevice(int id, @Nullable String name) {
- if (id <= VirtualDeviceManager.DEVICE_ID_DEFAULT) {
+ if (id <= Context.DEVICE_ID_DEFAULT) {
throw new IllegalArgumentException("VirtualDevice ID mist be greater than "
- + VirtualDeviceManager.DEVICE_ID_DEFAULT);
+ + Context.DEVICE_ID_DEFAULT);
}
mId = id;
mName = name;
diff --git a/core/java/android/companion/virtual/VirtualDeviceManager.java b/core/java/android/companion/virtual/VirtualDeviceManager.java
index ae43c6eb8b85..6cc4c8a24c48 100644
--- a/core/java/android/companion/virtual/VirtualDeviceManager.java
+++ b/core/java/android/companion/virtual/VirtualDeviceManager.java
@@ -89,24 +89,6 @@ public final class VirtualDeviceManager {
private static final String TAG = "VirtualDeviceManager";
- private static final int DEFAULT_VIRTUAL_DISPLAY_FLAGS =
- DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC
- | DisplayManager.VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT
- | DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY
- | DisplayManager.VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL
- | DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH
- | DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_FOCUS;
-
- /**
- * The default device ID, which is the ID of the primary (non-virtual) device.
- */
- public static final int DEVICE_ID_DEFAULT = 0;
-
- /**
- * Invalid device ID.
- */
- public static final int DEVICE_ID_INVALID = -1;
-
/**
* Broadcast Action: A Virtual Device was removed.
*
@@ -250,7 +232,7 @@ public final class VirtualDeviceManager {
public int getDeviceIdForDisplayId(int displayId) {
if (mService == null) {
Log.w(TAG, "Failed to retrieve virtual devices; no virtual device manager service.");
- return DEVICE_ID_DEFAULT;
+ return Context.DEVICE_ID_DEFAULT;
}
try {
return mService.getDeviceIdForDisplayId(displayId);
@@ -261,7 +243,7 @@ public final class VirtualDeviceManager {
/**
* Checks whether the passed {@code deviceId} is a valid virtual device ID or not.
- * {@link VirtualDeviceManager#DEVICE_ID_DEFAULT} is not valid as it is the ID of the default
+ * {@link Context#DEVICE_ID_DEFAULT} is not valid as it is the ID of the default
* device which is not a virtual device. {@code deviceId} must correspond to a virtual device
* created by {@link VirtualDeviceManager#createVirtualDevice(int, VirtualDeviceParams)}.
*
@@ -549,7 +531,11 @@ public final class VirtualDeviceManager {
* not create the virtual display.
*
* @see DisplayManager#createVirtualDisplay
+ *
+ * @deprecated use {@link #createVirtualDisplay(VirtualDisplayConfig, Executor,
+ * VirtualDisplay.Callback)}
*/
+ @Deprecated
@Nullable
public VirtualDisplay createVirtualDisplay(
@IntRange(from = 1) int width,
@@ -562,30 +548,16 @@ public final class VirtualDeviceManager {
VirtualDisplayConfig config = new VirtualDisplayConfig.Builder(
getVirtualDisplayName(), width, height, densityDpi)
.setSurface(surface)
- .setFlags(getVirtualDisplayFlags(flags))
+ .setFlags(flags)
.build();
- return createVirtualDisplayInternal(config, executor, callback);
+ return createVirtualDisplay(config, executor, callback);
}
/**
* Creates a virtual display for this virtual device. All displays created on the same
* device belongs to the same display group.
*
- * @param width The width of the virtual display in pixels, must be greater than 0.
- * @param height The height of the virtual display in pixels, must be greater than 0.
- * @param densityDpi The density of the virtual display in dpi, must be greater than 0.
- * @param displayCategories The categories of the virtual display, indicating the type of
- * activities allowed to run on the display. Activities can declare their type using
- * {@link android.content.pm.ActivityInfo#requiredDisplayCategory}.
- * @param surface The surface to which the content of the virtual display should
- * be rendered, or null if there is none initially. The surface can also be set later using
- * {@link VirtualDisplay#setSurface(Surface)}.
- * @param flags A combination of virtual display flags accepted by
- * {@link DisplayManager#createVirtualDisplay}. In addition, the following flags are
- * automatically set for all virtual devices:
- * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PUBLIC VIRTUAL_DISPLAY_FLAG_PUBLIC} and
- * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY
- * VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY}.
+ * @param config The configuration of the display.
* @param executor The executor on which {@code callback} will be invoked. This is ignored
* if {@code callback} is {@code null}. If {@code callback} is specified, this executor must
* not be null.
@@ -597,28 +569,6 @@ public final class VirtualDeviceManager {
*/
@Nullable
public VirtualDisplay createVirtualDisplay(
- @IntRange(from = 1) int width,
- @IntRange(from = 1) int height,
- @IntRange(from = 1) int densityDpi,
- @NonNull List<String> displayCategories,
- @Nullable Surface surface,
- @VirtualDisplayFlag int flags,
- @Nullable @CallbackExecutor Executor executor,
- @Nullable VirtualDisplay.Callback callback) {
- VirtualDisplayConfig config = new VirtualDisplayConfig.Builder(
- getVirtualDisplayName(), width, height, densityDpi)
- .setDisplayCategories(displayCategories)
- .setSurface(surface)
- .setFlags(getVirtualDisplayFlags(flags))
- .build();
- return createVirtualDisplayInternal(config, executor, callback);
- }
-
- /**
- * @hide
- */
- @Nullable
- private VirtualDisplay createVirtualDisplayInternal(
@NonNull VirtualDisplayConfig config,
@Nullable @CallbackExecutor Executor executor,
@Nullable VirtualDisplay.Callback callback) {
@@ -907,16 +857,6 @@ public final class VirtualDeviceManager {
}
}
- /**
- * Returns the display flags that should be added to a particular virtual display.
- * Additional device-level flags from {@link
- * com.android.server.companion.virtual.VirtualDeviceImpl#getBaseVirtualDisplayFlags()} will
- * be added by DisplayManagerService.
- */
- private int getVirtualDisplayFlags(int flags) {
- return DEFAULT_VIRTUAL_DISPLAY_FLAGS | flags;
- }
-
private String getVirtualDisplayName() {
try {
// Currently this just use the device ID, which means all of the virtual displays
diff --git a/core/java/android/companion/virtual/VirtualDeviceParams.java b/core/java/android/companion/virtual/VirtualDeviceParams.java
index d8076b5c0fd7..3a60a695a294 100644
--- a/core/java/android/companion/virtual/VirtualDeviceParams.java
+++ b/core/java/android/companion/virtual/VirtualDeviceParams.java
@@ -35,6 +35,7 @@ import android.companion.virtual.sensor.VirtualSensorConfig;
import android.content.ComponentName;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.SharedMemory;
import android.os.UserHandle;
import android.util.ArraySet;
import android.util.SparseArray;
@@ -139,7 +140,8 @@ public final class VirtualDeviceParams implements Parcelable {
* a given policy type.
* @hide
*/
- @IntDef(prefix = "POLICY_TYPE_", value = {POLICY_TYPE_SENSORS, POLICY_TYPE_AUDIO})
+ @IntDef(prefix = "POLICY_TYPE_", value = {POLICY_TYPE_SENSORS, POLICY_TYPE_AUDIO,
+ POLICY_TYPE_RECENTS})
@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
public @interface PolicyType {}
@@ -168,22 +170,21 @@ public final class VirtualDeviceParams implements Parcelable {
* <li>{@link #DEVICE_POLICY_CUSTOM}: audio framework will assign device specific session
* ids to players and recorders constructed within device context. The session ids are
* used to re-route corresponding audio streams to VirtualAudioDevice.
- * <ul/>
+ * </ul>
*/
public static final int POLICY_TYPE_AUDIO = 1;
- /** @hide */
- @IntDef(flag = true, prefix = "RECENTS_POLICY_",
- value = {RECENTS_POLICY_ALLOW_IN_HOST_DEVICE_RECENTS})
- @Retention(RetentionPolicy.SOURCE)
- @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
- public @interface RecentsPolicy {}
-
/**
- * If set, activities launched on this virtual device are allowed to appear in the host device
- * of the recently launched activities list.
+ * Tells the activity manager how to handle recents entries for activities run on this device.
+ *
+ * <ul>
+ * <li>{@link #DEVICE_POLICY_DEFAULT}: Activities launched on VirtualDisplays owned by this
+ * device will appear in the host device recents.
+ * <li>{@link #DEVICE_POLICY_CUSTOM}: Activities launched on VirtualDisplays owned by this
+ * * device will not appear in recents.
+ * </ul>
*/
- public static final int RECENTS_POLICY_ALLOW_IN_HOST_DEVICE_RECENTS = 1 << 0;
+ public static final int POLICY_TYPE_RECENTS = 2;
private final int mLockState;
@NonNull private final ArraySet<UserHandle> mUsersWithMatchingAccounts;
@@ -200,8 +201,6 @@ public final class VirtualDeviceParams implements Parcelable {
@NonNull private final SparseIntArray mDevicePolicies;
@NonNull private final List<VirtualSensorConfig> mVirtualSensorConfigs;
@Nullable private final IVirtualSensorCallback mVirtualSensorCallback;
- @RecentsPolicy
- private final int mDefaultRecentsPolicy;
private final int mAudioPlaybackSessionId;
private final int mAudioRecordingSessionId;
@@ -218,7 +217,6 @@ public final class VirtualDeviceParams implements Parcelable {
@NonNull SparseIntArray devicePolicies,
@NonNull List<VirtualSensorConfig> virtualSensorConfigs,
@Nullable IVirtualSensorCallback virtualSensorCallback,
- @RecentsPolicy int defaultRecentsPolicy,
int audioPlaybackSessionId,
int audioRecordingSessionId) {
mLockState = lockState;
@@ -236,10 +234,8 @@ public final class VirtualDeviceParams implements Parcelable {
mDevicePolicies = Objects.requireNonNull(devicePolicies);
mVirtualSensorConfigs = Objects.requireNonNull(virtualSensorConfigs);
mVirtualSensorCallback = virtualSensorCallback;
- mDefaultRecentsPolicy = defaultRecentsPolicy;
mAudioPlaybackSessionId = audioPlaybackSessionId;
mAudioRecordingSessionId = audioRecordingSessionId;
-
}
@SuppressWarnings("unchecked")
@@ -258,7 +254,6 @@ public final class VirtualDeviceParams implements Parcelable {
parcel.readTypedList(mVirtualSensorConfigs, VirtualSensorConfig.CREATOR);
mVirtualSensorCallback =
IVirtualSensorCallback.Stub.asInterface(parcel.readStrongBinder());
- mDefaultRecentsPolicy = parcel.readInt();
mAudioPlaybackSessionId = parcel.readInt();
mAudioRecordingSessionId = parcel.readInt();
}
@@ -395,16 +390,6 @@ public final class VirtualDeviceParams implements Parcelable {
}
/**
- * Returns the policy of how to handle activities in recents.
- *
- * @see RecentsPolicy
- */
- @RecentsPolicy
- public int getDefaultRecentsPolicy() {
- return mDefaultRecentsPolicy;
- }
-
- /**
* Returns device-specific audio session id for playback.
*
* @see Builder#setAudioPlaybackSessionId(int)
@@ -442,7 +427,6 @@ public final class VirtualDeviceParams implements Parcelable {
dest.writeTypedList(mVirtualSensorConfigs);
dest.writeStrongBinder(
mVirtualSensorCallback != null ? mVirtualSensorCallback.asBinder() : null);
- dest.writeInt(mDefaultRecentsPolicy);
dest.writeInt(mAudioPlaybackSessionId);
dest.writeInt(mAudioRecordingSessionId);
}
@@ -477,7 +461,6 @@ public final class VirtualDeviceParams implements Parcelable {
&& Objects.equals(mBlockedActivities, that.mBlockedActivities)
&& mDefaultActivityPolicy == that.mDefaultActivityPolicy
&& Objects.equals(mName, that.mName)
- && mDefaultRecentsPolicy == that.mDefaultRecentsPolicy
&& mAudioPlaybackSessionId == that.mAudioPlaybackSessionId
&& mAudioRecordingSessionId == that.mAudioRecordingSessionId;
}
@@ -488,7 +471,7 @@ public final class VirtualDeviceParams implements Parcelable {
mLockState, mUsersWithMatchingAccounts, mAllowedCrossTaskNavigations,
mBlockedCrossTaskNavigations, mDefaultNavigationPolicy, mAllowedActivities,
mBlockedActivities, mDefaultActivityPolicy, mName, mDevicePolicies,
- mDefaultRecentsPolicy, mAudioPlaybackSessionId, mAudioRecordingSessionId);
+ mAudioPlaybackSessionId, mAudioRecordingSessionId);
for (int i = 0; i < mDevicePolicies.size(); i++) {
hashCode = 31 * hashCode + mDevicePolicies.keyAt(i);
hashCode = 31 * hashCode + mDevicePolicies.valueAt(i);
@@ -510,7 +493,6 @@ public final class VirtualDeviceParams implements Parcelable {
+ " mDefaultActivityPolicy=" + mDefaultActivityPolicy
+ " mName=" + mName
+ " mDevicePolicies=" + mDevicePolicies
- + " mDefaultRecentsPolicy=" + mDefaultRecentsPolicy
+ " mAudioPlaybackSessionId=" + mAudioPlaybackSessionId
+ " mAudioRecordingSessionId=" + mAudioRecordingSessionId
+ ")";
@@ -547,7 +529,6 @@ public final class VirtualDeviceParams implements Parcelable {
private boolean mDefaultActivityPolicyConfigured = false;
@Nullable private String mName;
@NonNull private SparseIntArray mDevicePolicies = new SparseIntArray();
- private int mDefaultRecentsPolicy;
private int mAudioPlaybackSessionId = AUDIO_SESSION_ID_GENERATE;
private int mAudioRecordingSessionId = AUDIO_SESSION_ID_GENERATE;
@@ -577,6 +558,25 @@ public final class VirtualDeviceParams implements Parcelable {
mExecutor.execute(() -> mCallback.onConfigurationChanged(
sensor, enabled, samplingPeriod, batchReportingLatency));
}
+
+ @Override
+ public void onDirectChannelCreated(int channelHandle,
+ @NonNull SharedMemory sharedMemory) {
+ mExecutor.execute(
+ () -> mCallback.onDirectChannelCreated(channelHandle, sharedMemory));
+ }
+
+ @Override
+ public void onDirectChannelDestroyed(int channelHandle) {
+ mExecutor.execute(() -> mCallback.onDirectChannelDestroyed(channelHandle));
+ }
+
+ @Override
+ public void onDirectChannelConfigured(int channelHandle, @NonNull VirtualSensor sensor,
+ int rateLevel, int reportToken) {
+ mExecutor.execute(() -> mCallback.onDirectChannelConfigured(
+ channelHandle, sensor, rateLevel, reportToken));
+ }
}
/**
@@ -801,17 +801,6 @@ public final class VirtualDeviceParams implements Parcelable {
}
/**
- * Sets the policy to indicate how activities are handled in recents.
- *
- * @param defaultRecentsPolicy A policy specifying how to handle activities in recents.
- */
- @NonNull
- public Builder setDefaultRecentsPolicy(@RecentsPolicy int defaultRecentsPolicy) {
- mDefaultRecentsPolicy = defaultRecentsPolicy;
- return this;
- }
-
- /**
* Sets audio playback session id specific for this virtual device.
*
* <p>Audio players constructed within context associated with this virtual device
@@ -913,7 +902,6 @@ public final class VirtualDeviceParams implements Parcelable {
mDevicePolicies,
mVirtualSensorConfigs,
mVirtualSensorCallback,
- mDefaultRecentsPolicy,
mAudioPlaybackSessionId,
mAudioRecordingSessionId);
}
diff --git a/core/java/android/companion/virtual/sensor/IVirtualSensorCallback.aidl b/core/java/android/companion/virtual/sensor/IVirtualSensorCallback.aidl
index 7da9c3224400..3cb0572f3350 100644
--- a/core/java/android/companion/virtual/sensor/IVirtualSensorCallback.aidl
+++ b/core/java/android/companion/virtual/sensor/IVirtualSensorCallback.aidl
@@ -17,6 +17,7 @@
package android.companion.virtual.sensor;
import android.companion.virtual.sensor.VirtualSensor;
+import android.os.SharedMemory;
/**
* Interface for notifying the sensor owner about whether and how sensor events should be injected.
@@ -36,4 +37,31 @@ oneway interface IVirtualSensorCallback {
*/
void onConfigurationChanged(in VirtualSensor sensor, boolean enabled, int samplingPeriodMicros,
int batchReportLatencyMicros);
+
+ /**
+ * Called when a sensor direct channel is created.
+ *
+ * @param channelHandle Identifier of the channel that was created.
+ * @param sharedMemory The shared memory region for the direct sensor channel.
+ */
+ void onDirectChannelCreated(int channelHandle, in SharedMemory sharedMemory);
+
+ /**
+ * Called when a sensor direct channel is destroyed.
+ *
+ * @param channelHandle Identifier of the channel that was destroyed.
+ */
+ void onDirectChannelDestroyed(int channelHandle);
+
+ /**
+ * Called when a sensor direct channel is configured.
+ *
+ * @param channelHandle Identifier of the channel that was configured.
+ * @param sensor The sensor, for which the channel was configured.
+ * @param rateLevel The rate level used to configure the direct sensor channel.
+ * @param reportToken A positive sensor report token, used to differentiate between events from
+ * different sensors within the same channel.
+ */
+ void onDirectChannelConfigured(int channelHandle, in VirtualSensor sensor, int rateLevel,
+ int reportToken);
}
diff --git a/core/java/android/companion/virtual/sensor/VirtualSensorCallback.java b/core/java/android/companion/virtual/sensor/VirtualSensorCallback.java
index e09718941302..f7af283a749b 100644
--- a/core/java/android/companion/virtual/sensor/VirtualSensorCallback.java
+++ b/core/java/android/companion/virtual/sensor/VirtualSensorCallback.java
@@ -17,8 +17,13 @@
package android.companion.virtual.sensor;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.hardware.Sensor;
+import android.hardware.SensorDirectChannel;
+import android.os.MemoryFile;
+import android.os.SharedMemory;
import java.time.Duration;
@@ -50,4 +55,74 @@ public interface VirtualSensorCallback {
*/
void onConfigurationChanged(@NonNull VirtualSensor sensor, boolean enabled,
@NonNull Duration samplingPeriod, @NonNull Duration batchReportLatency);
+
+ /**
+ * Called when a {@link android.hardware.SensorDirectChannel} is created.
+ *
+ * <p>The {@link android.hardware.SensorManager} instance used to create the direct channel must
+ * be associated with the virtual device.
+ *
+ * <p>A typical order of callback invocations is:
+ * <ul>
+ * <li>{@code onDirectChannelCreated} - the channel handle and the associated shared memory
+ * should be stored by the virtual device</li>
+ * <li>{@code onDirectChannelConfigured} with a positive {@code rateLevel} - the virtual
+ * device should start writing to the shared memory for the associated channel with the
+ * requested parameters.</li>
+ * <li>{@code onDirectChannelConfigured} with a {@code rateLevel = RATE_STOP} - the virtual
+ * device should stop writing to the shared memory for the associated channel.</li>
+ * <li>{@code onDirectChannelDestroyed} - the shared memory associated with the channel
+ * handle should be closed.</li>
+ * </ul>
+ *
+ * @param channelHandle Identifier of the newly created channel.
+ * @param sharedMemory writable shared memory region.
+ *
+ * @see android.hardware.SensorManager#createDirectChannel(MemoryFile)
+ * @see #onDirectChannelConfigured
+ * @see #onDirectChannelDestroyed
+ */
+ default void onDirectChannelCreated(@IntRange(from = 1) int channelHandle,
+ @NonNull SharedMemory sharedMemory) {}
+
+ /**
+ * Called when a {@link android.hardware.SensorDirectChannel} is destroyed.
+ *
+ * <p>The virtual device must perform any clean-up and close the shared memory that was
+ * received with the {@link #onDirectChannelCreated} callback and the corresponding
+ * {@code channelHandle}.
+ *
+ * @param channelHandle Identifier of the channel that was destroyed.
+ *
+ * @see SensorDirectChannel#close()
+ */
+ default void onDirectChannelDestroyed(@IntRange(from = 1) int channelHandle) {}
+
+ /**
+ * Called when a {@link android.hardware.SensorDirectChannel} is configured.
+ *
+ * <p>Sensor events for the corresponding sensor should be written at the indicated rate to the
+ * shared memory region that was received with the {@link #onDirectChannelCreated} callback and
+ * the corresponding {@code channelHandle}. The events should be written in the correct format
+ * and with the provided {@code reportToken} until the channel is reconfigured with
+ * {@link SensorDirectChannel#RATE_STOP}.
+ *
+ * <p>The sensor must support direct channel in order for this callback to be invoked. Only
+ * {@link MemoryFile} sensor direct channels are supported for virtual sensors.
+ *
+ * @param channelHandle Identifier of the channel that was configured.
+ * @param sensor The sensor, for which the channel was configured.
+ * @param rateLevel The rate level used to configure the direct sensor channel.
+ * @param reportToken A positive sensor report token, used to differentiate between events from
+ * different sensors within the same channel.
+ *
+ * @see VirtualSensorConfig.Builder#setHighestDirectReportRateLevel(int)
+ * @see VirtualSensorConfig.Builder#setDirectChannelTypesSupported(int)
+ * @see android.hardware.SensorManager#createDirectChannel(MemoryFile)
+ * @see #onDirectChannelCreated
+ * @see SensorDirectChannel#configure(Sensor, int)
+ */
+ default void onDirectChannelConfigured(@IntRange(from = 1) int channelHandle,
+ @NonNull VirtualSensor sensor, @SensorDirectChannel.RateLevel int rateLevel,
+ @IntRange(from = 1) int reportToken) {}
}
diff --git a/core/java/android/companion/virtual/sensor/VirtualSensorConfig.java b/core/java/android/companion/virtual/sensor/VirtualSensorConfig.java
index 6d45365ebbd4..ffbdff8c2e3b 100644
--- a/core/java/android/companion/virtual/sensor/VirtualSensorConfig.java
+++ b/core/java/android/companion/virtual/sensor/VirtualSensorConfig.java
@@ -21,11 +21,13 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.hardware.Sensor;
+import android.hardware.SensorDirectChannel;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.Objects;
+
/**
* Configuration for creation of a virtual sensor.
* @see VirtualSensor
@@ -33,6 +35,14 @@ import java.util.Objects;
*/
@SystemApi
public final class VirtualSensorConfig implements Parcelable {
+ private static final String TAG = "VirtualSensorConfig";
+
+ // Mask for direct mode highest rate level, bit 7, 8, 9.
+ private static final int DIRECT_REPORT_MASK = 0x380;
+ private static final int DIRECT_REPORT_SHIFT = 7;
+
+ // Mask for supported direct channel, bit 10, 11
+ private static final int DIRECT_CHANNEL_SHIFT = 10;
private final int mType;
@NonNull
@@ -40,16 +50,21 @@ public final class VirtualSensorConfig implements Parcelable {
@Nullable
private final String mVendor;
- private VirtualSensorConfig(int type, @NonNull String name, @Nullable String vendor) {
+ private final int mFlags;
+
+ private VirtualSensorConfig(int type, @NonNull String name, @Nullable String vendor,
+ int flags) {
mType = type;
mName = name;
mVendor = vendor;
+ mFlags = flags;
}
private VirtualSensorConfig(@NonNull Parcel parcel) {
mType = parcel.readInt();
mName = parcel.readString8();
mVendor = parcel.readString8();
+ mFlags = parcel.readInt();
}
@Override
@@ -62,6 +77,7 @@ public final class VirtualSensorConfig implements Parcelable {
parcel.writeInt(mType);
parcel.writeString8(mName);
parcel.writeString8(mVendor);
+ parcel.writeInt(mFlags);
}
/**
@@ -92,22 +108,64 @@ public final class VirtualSensorConfig implements Parcelable {
}
/**
+ * Returns the highest supported direct report mode rate level of the sensor.
+ *
+ * @see Sensor#getHighestDirectReportRateLevel()
+ */
+ @SensorDirectChannel.RateLevel
+ public int getHighestDirectReportRateLevel() {
+ int rateLevel = ((mFlags & DIRECT_REPORT_MASK) >> DIRECT_REPORT_SHIFT);
+ return rateLevel <= SensorDirectChannel.RATE_VERY_FAST
+ ? rateLevel : SensorDirectChannel.RATE_VERY_FAST;
+ }
+
+ /**
+ * Returns a combination of all supported direct channel types.
+ *
+ * @see Builder#setDirectChannelTypesSupported(int)
+ * @see Sensor#isDirectChannelTypeSupported(int)
+ */
+ public @SensorDirectChannel.MemoryType int getDirectChannelTypesSupported() {
+ int memoryTypes = 0;
+ if ((mFlags & (1 << DIRECT_CHANNEL_SHIFT)) > 0) {
+ memoryTypes |= SensorDirectChannel.TYPE_MEMORY_FILE;
+ }
+ if ((mFlags & (1 << (DIRECT_CHANNEL_SHIFT + 1))) > 0) {
+ memoryTypes |= SensorDirectChannel.TYPE_HARDWARE_BUFFER;
+ }
+ return memoryTypes;
+ }
+
+ /**
+ * Returns the sensor flags.
+ * @hide
+ */
+ public int getFlags() {
+ return mFlags;
+ }
+
+ /**
* Builder for {@link VirtualSensorConfig}.
*/
public static final class Builder {
+ private static final int FLAG_MEMORY_FILE_DIRECT_CHANNEL_SUPPORTED =
+ 1 << DIRECT_CHANNEL_SHIFT;
private final int mType;
@NonNull
private final String mName;
@Nullable
private String mVendor;
+ private int mFlags;
+ @SensorDirectChannel.RateLevel
+ int mHighestDirectReportRateLevel;
/**
* Creates a new builder.
*
* @param type The type of the sensor, matching {@link Sensor#getType}.
* @param name The name of the sensor. Must be unique among all sensors with the same type
- * that belong to the same virtual device.
+ * that belong to the same virtual device.
*/
public Builder(int type, @NonNull String name) {
mType = type;
@@ -119,7 +177,19 @@ public final class VirtualSensorConfig implements Parcelable {
*/
@NonNull
public VirtualSensorConfig build() {
- return new VirtualSensorConfig(mType, mName, mVendor);
+ if (mHighestDirectReportRateLevel > 0) {
+ if ((mFlags & FLAG_MEMORY_FILE_DIRECT_CHANNEL_SUPPORTED) == 0) {
+ throw new IllegalArgumentException("Setting direct channel type is required "
+ + "for sensors with direct channel support.");
+ }
+ mFlags |= mHighestDirectReportRateLevel << DIRECT_REPORT_SHIFT;
+ }
+ if ((mFlags & FLAG_MEMORY_FILE_DIRECT_CHANNEL_SUPPORTED) > 0
+ && mHighestDirectReportRateLevel == 0) {
+ throw new IllegalArgumentException("Highest direct report rate level is "
+ + "required for sensors with direct channel support.");
+ }
+ return new VirtualSensorConfig(mType, mName, mVendor, mFlags);
}
/**
@@ -130,6 +200,44 @@ public final class VirtualSensorConfig implements Parcelable {
mVendor = vendor;
return this;
}
+
+ /**
+ * Sets the highest supported rate level for direct sensor report.
+ *
+ * @see VirtualSensorConfig#getHighestDirectReportRateLevel()
+ */
+ @NonNull
+ public VirtualSensorConfig.Builder setHighestDirectReportRateLevel(
+ @SensorDirectChannel.RateLevel int rateLevel) {
+ mHighestDirectReportRateLevel = rateLevel;
+ return this;
+ }
+
+ /**
+ * Sets whether direct sensor channel of the given types is supported.
+ *
+ * @param memoryTypes A combination of {@link SensorDirectChannel.MemoryType} flags
+ * indicating the types of shared memory supported for creating direct channels. Only
+ * {@link SensorDirectChannel#TYPE_MEMORY_FILE} direct channels may be supported for virtual
+ * sensors.
+ * @throws IllegalArgumentException if {@link SensorDirectChannel#TYPE_HARDWARE_BUFFER} is
+ * set to be supported.
+ */
+ @NonNull
+ public VirtualSensorConfig.Builder setDirectChannelTypesSupported(
+ @SensorDirectChannel.MemoryType int memoryTypes) {
+ if ((memoryTypes & SensorDirectChannel.TYPE_MEMORY_FILE) > 0) {
+ mFlags |= FLAG_MEMORY_FILE_DIRECT_CHANNEL_SUPPORTED;
+ } else {
+ mFlags &= ~FLAG_MEMORY_FILE_DIRECT_CHANNEL_SUPPORTED;
+ }
+ if ((memoryTypes & ~SensorDirectChannel.TYPE_MEMORY_FILE) > 0) {
+ throw new IllegalArgumentException(
+ "Only TYPE_MEMORY_FILE direct channels can be supported for virtual "
+ + "sensors.");
+ }
+ return this;
+ }
}
@NonNull
diff --git a/core/java/android/content/AttributionSource.java b/core/java/android/content/AttributionSource.java
index e981581c269a..2b400c1fba43 100644
--- a/core/java/android/content/AttributionSource.java
+++ b/core/java/android/content/AttributionSource.java
@@ -155,6 +155,11 @@ public final class AttributionSource implements Parcelable {
AttributionSource(@NonNull Parcel in) {
this(AttributionSourceState.CREATOR.createFromParcel(in));
+ if (!Binder.isDirectlyHandlingTransaction()) {
+ throw new SecurityException("AttributionSource should be unparceled during a binder "
+ + "transaction for proper verification.");
+ }
+
// Since we just unpacked this object as part of it transiting a Binder
// call, this is the perfect time to enforce that its UID and PID can be trusted
enforceCallingUidAndPid();
diff --git a/core/java/android/content/ClipboardManager.java b/core/java/android/content/ClipboardManager.java
index 06a3b1e1cc66..8a22ce3a75f8 100644
--- a/core/java/android/content/ClipboardManager.java
+++ b/core/java/android/content/ClipboardManager.java
@@ -135,6 +135,39 @@ public class ClipboardManager extends android.text.ClipboardManager {
}
/**
+ * Determine if the Clipboard Access Notifications are enabled
+ *
+ * @return true if notifications are enabled, false otherwise.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.MANAGE_CLIPBOARD_ACCESS_NOTIFICATION)
+ public boolean areClipboardAccessNotificationsEnabled() {
+ try {
+ return mService.areClipboardAccessNotificationsEnabledForUser(mContext.getUserId());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ *
+ * Set the enable state of the Clipboard Access Notifications
+ * @param enable Whether to enable notifications
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.MANAGE_CLIPBOARD_ACCESS_NOTIFICATION)
+ public void setClipboardAccessNotificationsEnabled(boolean enable) {
+ try {
+ mService.setClipboardAccessNotificationsEnabledForUser(enable, mContext.getUserId());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Sets the current primary clip on the clipboard. This is the clip that
* is involved in normal cut and paste operations.
*
diff --git a/core/java/android/content/ContentCaptureOptions.java b/core/java/android/content/ContentCaptureOptions.java
index 77072890a1eb..856bde870bcf 100644
--- a/core/java/android/content/ContentCaptureOptions.java
+++ b/core/java/android/content/ContentCaptureOptions.java
@@ -70,6 +70,12 @@ public final class ContentCaptureOptions implements Parcelable {
public final int logHistorySize;
/**
+ * Disable flush when receiving a VIEW_TREE_APPEARING event.
+ * @hide
+ */
+ public final boolean disableFlushForViewTreeAppearing;
+
+ /**
* List of activities explicitly allowlisted for content capture (or {@code null} if allowlisted
* for all acitivites in the package).
*/
@@ -90,7 +96,8 @@ public final class ContentCaptureOptions implements Parcelable {
public ContentCaptureOptions(int loggingLevel) {
this(/* lite= */ true, loggingLevel, /* maxBufferSize= */ 0,
/* idleFlushingFrequencyMs= */ 0, /* textChangeFlushingFrequencyMs= */ 0,
- /* logHistorySize= */ 0, /* whitelistedComponents= */ null);
+ /* logHistorySize= */ 0, /* disableFlushForViewTreeAppearing= */ false,
+ /* whitelistedComponents= */ null);
}
/**
@@ -98,10 +105,23 @@ public final class ContentCaptureOptions implements Parcelable {
*/
public ContentCaptureOptions(int loggingLevel, int maxBufferSize, int idleFlushingFrequencyMs,
int textChangeFlushingFrequencyMs, int logHistorySize,
- @SuppressLint("NullableCollection")
+ @SuppressLint({"ConcreteCollection", "NullableCollection"})
+ @Nullable ArraySet<ComponentName> whitelistedComponents) {
+ this(/* lite= */ false, loggingLevel, maxBufferSize, idleFlushingFrequencyMs,
+ textChangeFlushingFrequencyMs, logHistorySize,
+ ContentCaptureManager.DEFAULT_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING,
+ whitelistedComponents);
+ }
+
+ /** @hide */
+ public ContentCaptureOptions(int loggingLevel, int maxBufferSize, int idleFlushingFrequencyMs,
+ int textChangeFlushingFrequencyMs, int logHistorySize,
+ boolean disableFlushForViewTreeAppearing,
+ @SuppressLint({"ConcreteCollection", "NullableCollection"})
@Nullable ArraySet<ComponentName> whitelistedComponents) {
this(/* lite= */ false, loggingLevel, maxBufferSize, idleFlushingFrequencyMs,
- textChangeFlushingFrequencyMs, logHistorySize, whitelistedComponents);
+ textChangeFlushingFrequencyMs, logHistorySize, disableFlushForViewTreeAppearing,
+ whitelistedComponents);
}
/** @hide */
@@ -111,11 +131,14 @@ public final class ContentCaptureOptions implements Parcelable {
ContentCaptureManager.DEFAULT_MAX_BUFFER_SIZE,
ContentCaptureManager.DEFAULT_IDLE_FLUSHING_FREQUENCY_MS,
ContentCaptureManager.DEFAULT_TEXT_CHANGE_FLUSHING_FREQUENCY_MS,
- ContentCaptureManager.DEFAULT_LOG_HISTORY_SIZE, whitelistedComponents);
+ ContentCaptureManager.DEFAULT_LOG_HISTORY_SIZE,
+ ContentCaptureManager.DEFAULT_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING,
+ whitelistedComponents);
}
private ContentCaptureOptions(boolean lite, int loggingLevel, int maxBufferSize,
int idleFlushingFrequencyMs, int textChangeFlushingFrequencyMs, int logHistorySize,
+ boolean disableFlushForViewTreeAppearing,
@Nullable ArraySet<ComponentName> whitelistedComponents) {
this.lite = lite;
this.loggingLevel = loggingLevel;
@@ -123,6 +146,7 @@ public final class ContentCaptureOptions implements Parcelable {
this.idleFlushingFrequencyMs = idleFlushingFrequencyMs;
this.textChangeFlushingFrequencyMs = textChangeFlushingFrequencyMs;
this.logHistorySize = logHistorySize;
+ this.disableFlushForViewTreeAppearing = disableFlushForViewTreeAppearing;
this.whitelistedComponents = whitelistedComponents;
}
@@ -171,7 +195,8 @@ public final class ContentCaptureOptions implements Parcelable {
.append(", maxBufferSize=").append(maxBufferSize)
.append(", idleFlushingFrequencyMs=").append(idleFlushingFrequencyMs)
.append(", textChangeFlushingFrequencyMs=").append(textChangeFlushingFrequencyMs)
- .append(", logHistorySize=").append(logHistorySize);
+ .append(", logHistorySize=").append(logHistorySize)
+ .append(", disableFlushForViewTreeAppearing=").append(disableFlushForViewTreeAppearing);
if (whitelistedComponents != null) {
string.append(", whitelisted=").append(whitelistedComponents);
}
@@ -189,6 +214,7 @@ public final class ContentCaptureOptions implements Parcelable {
pw.print(", idle="); pw.print(idleFlushingFrequencyMs);
pw.print(", textIdle="); pw.print(textChangeFlushingFrequencyMs);
pw.print(", logSize="); pw.print(logHistorySize);
+ pw.print(", disableFlushForViewTreeAppearing="); pw.print(disableFlushForViewTreeAppearing);
if (whitelistedComponents != null) {
pw.print(", whitelisted="); pw.print(whitelistedComponents);
}
@@ -209,6 +235,7 @@ public final class ContentCaptureOptions implements Parcelable {
parcel.writeInt(idleFlushingFrequencyMs);
parcel.writeInt(textChangeFlushingFrequencyMs);
parcel.writeInt(logHistorySize);
+ parcel.writeBoolean(disableFlushForViewTreeAppearing);
parcel.writeArraySet(whitelistedComponents);
}
@@ -226,12 +253,13 @@ public final class ContentCaptureOptions implements Parcelable {
final int idleFlushingFrequencyMs = parcel.readInt();
final int textChangeFlushingFrequencyMs = parcel.readInt();
final int logHistorySize = parcel.readInt();
+ final boolean disableFlushForViewTreeAppearing = parcel.readBoolean();
@SuppressWarnings("unchecked")
final ArraySet<ComponentName> whitelistedComponents =
(ArraySet<ComponentName>) parcel.readArraySet(null);
return new ContentCaptureOptions(loggingLevel, maxBufferSize,
idleFlushingFrequencyMs, textChangeFlushingFrequencyMs, logHistorySize,
- whitelistedComponents);
+ disableFlushForViewTreeAppearing, whitelistedComponents);
}
@Override
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index b72db5bdafa3..d3502c5254c8 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -363,7 +363,7 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
enumCheckUriPermission,
callingUid, uri.getAuthority(), type);
}
- } catch (RemoteException e) {
+ } catch (Exception e) {
//does nothing
}
} else {
@@ -389,6 +389,8 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
@Override
public void getTypeAnonymousAsync(Uri uri, RemoteCallback callback) {
+ uri = validateIncomingUri(uri);
+ uri = maybeGetUriWithoutUserId(uri);
final Bundle result = new Bundle();
try {
result.putString(ContentResolver.REMOTE_CALLBACK_RESULT, getTypeAnonymous(uri));
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 4dccc8d0e81a..a412560d0347 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -135,6 +135,15 @@ public abstract class Context {
@VisibleForTesting
public static final long OVERRIDABLE_COMPONENT_CALLBACKS = 193247900L;
+ /**
+ * The default device ID, which is the ID of the primary (non-virtual) device.
+ */
+ public static final int DEVICE_ID_DEFAULT = 0;
+ /**
+ * Invalid device ID.
+ */
+ public static final int DEVICE_ID_INVALID = -1;
+
/** @hide */
@IntDef(flag = true, prefix = { "MODE_" }, value = {
MODE_PRIVATE,
@@ -519,7 +528,7 @@ public abstract class Context {
/**
* Flag for {@link #bindService}: allow the process hosting the target service to gain
- * {@link ActivityManager#PROCESS_CAPABILITY_NETWORK}, which allows it be able
+ * {@link ActivityManager#PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK}, which allows it be able
* to access network regardless of any power saving restrictions.
*
* @hide
@@ -4267,7 +4276,7 @@ public abstract class Context {
* <p>Note: When implementing this method, keep in mind that new services can be added on newer
* Android releases, so if you're looking for just the explicit names mentioned above, make sure
* to return {@code null} when you don't recognize the name &mdash; if you throw a
- * {@link RuntimeException} exception instead, you're app might break on new Android releases.
+ * {@link RuntimeException} exception instead, your app might break on new Android releases.
*
* @param name The name of the desired service.
*
@@ -5694,6 +5703,9 @@ public abstract class Context {
* Use with {@link #getSystemService(String)} to retrieve a
* {@link android.companion.virtual.VirtualDeviceManager} for managing virtual devices.
*
+ * On devices without {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP}
+ * system feature the {@link #getSystemService(String)} will return {@code null}.
+ *
* @see #getSystemService(String)
* @see android.companion.virtual.VirtualDeviceManager
*/
@@ -7175,7 +7187,7 @@ public abstract class Context {
* <p>
* Applications that run on virtual devices may use this method to access the default device
* capabilities and functionality (by passing
- * {@link android.companion.virtual.VirtualDeviceManager#DEVICE_ID_DEFAULT}. Similarly,
+ * {@link Context#DEVICE_ID_DEFAULT}. Similarly,
* applications running on the default device may access the functionality of virtual devices.
* </p>
* <p>
@@ -7542,7 +7554,7 @@ public abstract class Context {
* determine whether they are running on a virtual device and identify that device.
*
* The device ID of the host device is
- * {@link android.companion.virtual.VirtualDeviceManager#DEVICE_ID_DEFAULT}
+ * {@link Context#DEVICE_ID_DEFAULT}
*
* <p>
* If the underlying device ID is changed by the system, for example, when an
diff --git a/core/java/android/content/IClipboard.aidl b/core/java/android/content/IClipboard.aidl
index b2216d4953e6..fe7798fb24a1 100644
--- a/core/java/android/content/IClipboard.aidl
+++ b/core/java/android/content/IClipboard.aidl
@@ -48,4 +48,8 @@ interface IClipboard {
String getPrimaryClipSource(String callingPackage, String attributionTag, int userId,
int deviceId);
+
+ boolean areClipboardAccessNotificationsEnabledForUser(int userId);
+
+ void setClipboardAccessNotificationsEnabledForUser(boolean enable, int userId);
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 5818ed75056c..85daf15865d1 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3234,8 +3234,9 @@ public class Intent implements Parcelable, Cloneable {
/**
* Broadcast Action: The receiver's effective locale has changed.
*
- * This happens when the device locale, or the receiving app's locale
- * (set via {@link android.app.LocaleManager#setApplicationLocales}) changed.
+ * This happens when the device locale, the receiving app's locale
+ * (set via {@link android.app.LocaleManager#setApplicationLocales}) or language tags
+ * of Regional preferences changed.
*
* Can be received by manifest-declared receivers.
*
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 7766896c7367..a6a62150d0da 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1711,8 +1711,8 @@ public class PackageInstaller {
* performed on the session. In case of device reboot or data loader transient failure
* before the session has been finalized, you may commit the session again.
* <p>
- * If the installer is the device owner or the affiliated profile owner, there will be no
- * user intervention.
+ * If the installer is the device owner, the affiliated profile owner, or has received
+ * user pre-approval of this session, there will be no user intervention.
*
* @param statusReceiver Called when the state of the session changes. Intents
* sent to this receiver contain {@link #EXTRA_STATUS}. Refer to the
@@ -1722,6 +1722,7 @@ public class PackageInstaller {
* {@link #openWrite(String, long, long)} are still open.
*
* @see android.app.admin.DevicePolicyManager
+ * @see #requestUserPreapproval
*/
public void commit(@NonNull IntentSender statusReceiver) {
try {
@@ -1987,14 +1988,22 @@ public class PackageInstaller {
* {@link android.Manifest.permission#REQUEST_INSTALL_PACKAGES REQUEST_INSTALL_PACKAGES}
* permission, they can request the approval from users before
* {@link Session#commit(IntentSender)} is called. This may require user intervention as
- * well. The result of the request will be reported through the given callback.
+ * well. When user intervention is required, installers will receive a
+ * {@link #STATUS_PENDING_USER_ACTION} callback, and {@link #STATUS_SUCCESS} otherwise.
+ * In case that requesting user pre-approval is not available, installers will receive
+ * {@link #STATUS_FAILURE_BLOCKED} instead. Note that if the users decline the request,
+ * this session will be abandoned.
+ *
+ * If user intervention is required but never resolved, or requesting user
+ * pre-approval is not available, you may still call {@link Session#commit(IntentSender)}
+ * as the typical installation.
*
* @param details the adequate context to this session for requesting the approval from
* users prior to commit.
* @param statusReceiver called when the state of the session changes.
- * Intents sent to this receiver contain
- * {@link #EXTRA_STATUS}. Refer to the individual
- * status codes on how to handle them.
+ * Intents sent to this receiver contain {@link #EXTRA_STATUS}
+ * and the {@link #EXTRA_PRE_APPROVAL} would be {@code true}.
+ * Refer to the individual status codes on how to handle them.
*
* @throws IllegalArgumentException when {@link PreapprovalDetails} is {@code null}.
* @throws IllegalArgumentException if {@link IntentSender} is {@code null}.
@@ -2003,6 +2012,7 @@ public class PackageInstaller {
* @throws IllegalStateException if called again after this method has been called on
* this session.
* @throws SecurityException when the caller does not own this session.
+ * @throws SecurityException if called after the session has been committed or abandoned.
*/
public void requestUserPreapproval(@NonNull PreapprovalDetails details,
@NonNull IntentSender statusReceiver) {
@@ -3981,8 +3991,7 @@ public class PackageInstaller {
/**
* Details for requesting the pre-commit install approval.
*/
- @DataClass(genParcelable = true, genHiddenConstructor = true, genBuilder = true,
- genToString = true)
+ @DataClass(genConstructor = false, genToString = true)
public static final class PreapprovalDetails implements Parcelable {
/**
* The icon representing the app to be installed.
@@ -4001,22 +4010,6 @@ public class PackageInstaller {
*/
private final @NonNull String mPackageName;
-
-
-
- // Code below generated by codegen v1.0.23.
- //
- // DO NOT MODIFY!
- // CHECKSTYLE:OFF Generated code
- //
- // To regenerate run:
- // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/PackageInstaller.java
- //
- // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
- // Settings > Editor > Code Style > Formatter Control
- //@formatter:off
-
-
/**
* Creates a new PreapprovalDetails.
*
@@ -4030,78 +4023,25 @@ public class PackageInstaller {
* The package name of the app to be installed.
* @hide
*/
- @DataClass.Generated.Member
public PreapprovalDetails(
@Nullable Bitmap icon,
@NonNull CharSequence label,
@NonNull ULocale locale,
@NonNull String packageName) {
- this.mIcon = icon;
- this.mLabel = label;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mLabel);
- this.mLocale = locale;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mLocale);
- this.mPackageName = packageName;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mPackageName);
-
- // onConstructed(); // You can define this method to get a callback
- }
-
- /**
- * The icon representing the app to be installed.
- */
- @DataClass.Generated.Member
- public @Nullable Bitmap getIcon() {
- return mIcon;
- }
-
- /**
- * The label representing the app to be installed.
- */
- @DataClass.Generated.Member
- public @NonNull CharSequence getLabel() {
- return mLabel;
- }
-
- /**
- * The locale of the app label being used.
- */
- @DataClass.Generated.Member
- public @NonNull ULocale getLocale() {
- return mLocale;
- }
-
- /**
- * The package name of the app to be installed.
- */
- @DataClass.Generated.Member
- public @NonNull String getPackageName() {
- return mPackageName;
- }
-
- @Override
- @DataClass.Generated.Member
- public String toString() {
- // You can override field toString logic by defining methods like:
- // String fieldNameToString() { ... }
-
- return "PreapprovalDetails { " +
- "icon = " + mIcon + ", " +
- "label = " + mLabel + ", " +
- "locale = " + mLocale + ", " +
- "packageName = " + mPackageName +
- " }";
+ mIcon = icon;
+ mLabel = label;
+ Preconditions.checkArgument(!TextUtils.isEmpty(mLabel),
+ "App label cannot be empty.");
+ mLocale = locale;
+ Preconditions.checkArgument(!Objects.isNull(mLocale),
+ "Locale cannot be null.");
+ mPackageName = packageName;
+ Preconditions.checkArgument(!TextUtils.isEmpty(mPackageName),
+ "Package name cannot be empty.");
}
@Override
- @DataClass.Generated.Member
public void writeToParcel(@NonNull Parcel dest, int flags) {
- // You can override field parcelling by defining methods like:
- // void parcelFieldName(Parcel dest, int flags) { ... }
-
byte flg = 0;
if (mIcon != null) flg |= 0x1;
dest.writeByte(flg);
@@ -4112,37 +4052,28 @@ public class PackageInstaller {
}
@Override
- @DataClass.Generated.Member
public int describeContents() { return 0; }
/** @hide */
- @SuppressWarnings({"unchecked", "RedundantCast"})
- @DataClass.Generated.Member
/* package-private */ PreapprovalDetails(@NonNull Parcel in) {
- // You can override field unparcelling by defining methods like:
- // static FieldType unparcelFieldName(Parcel in) { ... }
-
byte flg = in.readByte();
- Bitmap icon = (flg & 0x1) == 0 ? null : Bitmap.CREATOR.createFromParcel(in);
- CharSequence label = (CharSequence) in.readCharSequence();
- ULocale locale = new ULocale(in.readString8());
- String packageName = in.readString8();
-
- this.mIcon = icon;
- this.mLabel = label;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mLabel);
- this.mLocale = locale;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mLocale);
- this.mPackageName = packageName;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mPackageName);
-
- // onConstructed(); // You can define this method to get a callback
+ final Bitmap icon = (flg & 0x1) == 0 ? null : Bitmap.CREATOR.createFromParcel(in);
+ final CharSequence label = in.readCharSequence();
+ final ULocale locale = new ULocale(in.readString8());
+ final String packageName = in.readString8();
+
+ mIcon = icon;
+ mLabel = label;
+ Preconditions.checkArgument(!TextUtils.isEmpty(mLabel),
+ "App label cannot be empty.");
+ mLocale = locale;
+ Preconditions.checkArgument(!Objects.isNull(mLocale),
+ "Locale cannot be null.");
+ mPackageName = packageName;
+ Preconditions.checkArgument(!TextUtils.isEmpty(mPackageName),
+ "Package name cannot be empty.");
}
- @DataClass.Generated.Member
public static final @NonNull Parcelable.Creator<PreapprovalDetails> CREATOR
= new Parcelable.Creator<PreapprovalDetails>() {
@Override
@@ -4159,8 +4090,6 @@ public class PackageInstaller {
/**
* A builder for {@link PreapprovalDetails}
*/
- @SuppressWarnings("WeakerAccess")
- @DataClass.Generated.Member
public static final class Builder {
private @Nullable Bitmap mIcon;
@@ -4178,7 +4107,6 @@ public class PackageInstaller {
/**
* The icon representing the app to be installed.
*/
- @DataClass.Generated.Member
public @NonNull Builder setIcon(@NonNull Bitmap value) {
checkNotUsed();
mBuilderFieldsSet |= 0x1;
@@ -4189,7 +4117,6 @@ public class PackageInstaller {
/**
* The label representing the app to be installed.
*/
- @DataClass.Generated.Member
public @NonNull Builder setLabel(@NonNull CharSequence value) {
checkNotUsed();
mBuilderFieldsSet |= 0x2;
@@ -4200,7 +4127,6 @@ public class PackageInstaller {
/**
* The locale of the app label being used.
*/
- @DataClass.Generated.Member
public @NonNull Builder setLocale(@NonNull ULocale value) {
checkNotUsed();
mBuilderFieldsSet |= 0x4;
@@ -4211,7 +4137,6 @@ public class PackageInstaller {
/**
* The package name of the app to be installed.
*/
- @DataClass.Generated.Member
public @NonNull Builder setPackageName(@NonNull String value) {
checkNotUsed();
mBuilderFieldsSet |= 0x8;
@@ -4234,17 +4159,79 @@ public class PackageInstaller {
private void checkNotUsed() {
if ((mBuilderFieldsSet & 0x10) != 0) {
- throw new IllegalStateException(
- "This Builder should not be reused. Use a new Builder instance instead");
+ throw new IllegalStateException("This Builder should not be reused. "
+ + "Use a new Builder instance instead");
}
}
}
+
+
+
+ // Code below generated by codegen v1.0.23.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/PackageInstaller.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ /**
+ * The icon representing the app to be installed.
+ */
+ @DataClass.Generated.Member
+ public @Nullable Bitmap getIcon() {
+ return mIcon;
+ }
+
+ /**
+ * The label representing the app to be installed.
+ */
+ @DataClass.Generated.Member
+ public @NonNull CharSequence getLabel() {
+ return mLabel;
+ }
+
+ /**
+ * The locale of the app label being used.
+ */
+ @DataClass.Generated.Member
+ public @NonNull ULocale getLocale() {
+ return mLocale;
+ }
+
+ /**
+ * The package name of the app to be installed.
+ */
+ @DataClass.Generated.Member
+ public @NonNull String getPackageName() {
+ return mPackageName;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public String toString() {
+ // You can override field toString logic by defining methods like:
+ // String fieldNameToString() { ... }
+
+ return "PreapprovalDetails { " +
+ "icon = " + mIcon + ", " +
+ "label = " + mLabel + ", " +
+ "locale = " + mLocale + ", " +
+ "packageName = " + mPackageName +
+ " }";
+ }
+
@DataClass.Generated(
- time = 1666748098353L,
+ time = 1676970504308L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/content/pm/PackageInstaller.java",
- inputSignatures = "private final @android.annotation.Nullable android.graphics.Bitmap mIcon\nprivate final @android.annotation.NonNull java.lang.CharSequence mLabel\nprivate final @android.annotation.NonNull android.icu.util.ULocale mLocale\nprivate final @android.annotation.NonNull java.lang.String mPackageName\nclass PreapprovalDetails extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genHiddenConstructor=true, genBuilder=true, genToString=true)")
+ inputSignatures = "private final @android.annotation.Nullable android.graphics.Bitmap mIcon\nprivate final @android.annotation.NonNull java.lang.CharSequence mLabel\nprivate final @android.annotation.NonNull android.icu.util.ULocale mLocale\nprivate final @android.annotation.NonNull java.lang.String mPackageName\npublic static final @android.annotation.NonNull android.os.Parcelable.Creator<android.content.pm.PackageInstaller.PreapprovalDetails> CREATOR\npublic @java.lang.Override void writeToParcel(android.os.Parcel,int)\npublic @java.lang.Override int describeContents()\nclass PreapprovalDetails extends java.lang.Object implements [android.os.Parcelable]\nprivate @android.annotation.Nullable android.graphics.Bitmap mIcon\nprivate @android.annotation.NonNull java.lang.CharSequence mLabel\nprivate @android.annotation.NonNull android.icu.util.ULocale mLocale\nprivate @android.annotation.NonNull java.lang.String mPackageName\nprivate long mBuilderFieldsSet\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.PreapprovalDetails.Builder setIcon(android.graphics.Bitmap)\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.PreapprovalDetails.Builder setLabel(java.lang.CharSequence)\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.PreapprovalDetails.Builder setLocale(android.icu.util.ULocale)\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.PreapprovalDetails.Builder setPackageName(java.lang.String)\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.PreapprovalDetails build()\nprivate void checkNotUsed()\nclass Builder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genToString=true)")
@Deprecated
private void __metadata() {}
@@ -4347,7 +4334,7 @@ public class PackageInstaller {
};
@DataClass.Generated(
- time = 1675135664641L,
+ time = 1676970504336L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/content/pm/PackageInstaller.java",
inputSignatures = "private boolean mAllConstraintsSatisfied\npublic boolean areAllConstraintsSatisfied()\nclass InstallConstraintsResult extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genHiddenConstructor=true)")
@@ -4635,7 +4622,7 @@ public class PackageInstaller {
};
@DataClass.Generated(
- time = 1675135664653L,
+ time = 1676970504352L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/content/pm/PackageInstaller.java",
inputSignatures = "public static final @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints GENTLE_UPDATE\nprivate final boolean mDeviceIdleRequired\nprivate final boolean mAppNotForegroundRequired\nprivate final boolean mAppNotInteractingRequired\nprivate final boolean mAppNotTopVisibleRequired\nprivate final boolean mNotInCallRequired\nclass InstallConstraints extends java.lang.Object implements [android.os.Parcelable]\nprivate boolean mDeviceIdleRequired\nprivate boolean mAppNotForegroundRequired\nprivate boolean mAppNotInteractingRequired\nprivate boolean mAppNotTopVisibleRequired\nprivate boolean mNotInCallRequired\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setDeviceIdleRequired()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setAppNotForegroundRequired()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setAppNotInteractingRequired()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setAppNotTopVisibleRequired()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setNotInCallRequired()\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints build()\nclass Builder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genParcelable=true, genHiddenConstructor=true, genEqualsHashCode=true)")
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index db05b959a7b1..9388823b1a9c 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -5157,6 +5157,8 @@ public abstract class PackageManager {
* Retrieve overall information about an application package that is
* installed on the system.
*
+ * Use {@link #getPackageInfo(String, PackageInfoFlags)} when long flags are needed.
+ *
* @param packageName The full name (i.e. com.google.apps.contacts) of the
* desired package.
* @param flags Additional option flags to modify the data returned.
@@ -5169,9 +5171,7 @@ public abstract class PackageManager {
* deleted with {@code DELETE_KEEP_DATA} flag set).
* @throws NameNotFoundException if no such package is available to the
* caller.
- * @deprecated Use {@link #getPackageInfo(String, PackageInfoFlags)} instead.
*/
- @Deprecated
public abstract PackageInfo getPackageInfo(@NonNull String packageName, int flags)
throws NameNotFoundException;
@@ -5195,6 +5195,8 @@ public abstract class PackageManager {
* {@link #VERSION_CODE_HIGHEST} in the {@link VersionedPackage}
* constructor.
*
+ * Use {@link #getPackageInfo(VersionedPackage, PackageInfoFlags)} when long flags are needed.
+ *
* @param versionedPackage The versioned package for which to query.
* @param flags Additional option flags to modify the data returned.
* @return A PackageInfo object containing information about the package. If
@@ -5206,9 +5208,7 @@ public abstract class PackageManager {
* deleted with {@code DELETE_KEEP_DATA} flag set).
* @throws NameNotFoundException if no such package is available to the
* caller.
- * @deprecated Use {@link #getPackageInfo(VersionedPackage, PackageInfoFlags)} instead.
*/
- @Deprecated
public abstract PackageInfo getPackageInfo(@NonNull VersionedPackage versionedPackage,
int flags) throws NameNotFoundException;
@@ -5226,6 +5226,8 @@ public abstract class PackageManager {
* Retrieve overall information about an application package that is
* installed on the system.
*
+ * Use {@link #getPackageInfoAsUser(String, PackageInfoFlags, int)} when long flags are needed.
+ *
* @param packageName The full name (i.e. com.google.apps.contacts) of the
* desired package.
* @param flags Additional option flags to modify the data returned.
@@ -5239,10 +5241,8 @@ public abstract class PackageManager {
* deleted with {@code DELETE_KEEP_DATA} flag set).
* @throws NameNotFoundException if no such package is available to the
* caller.
- * @deprecated Use {@link #getPackageInfoAsUser(String, PackageInfoFlags, int)} instead.
* @hide
*/
- @Deprecated
@SuppressWarnings("HiddenAbstractMethod")
@RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS)
@UnsupportedAppUsage
@@ -5376,15 +5376,16 @@ public abstract class PackageManager {
* Note that the same package may have different GIDs under different
* {@link UserHandle} on the same device.
*
+ * Use {@link #getPackageGids(String, PackageInfoFlags)} when long flags are needed.
+ *
* @param packageName The full name (i.e. com.google.apps.contacts) of the
* desired package.
* @return Returns an int array of the assigned gids, or null if there are
* none.
* @throws NameNotFoundException if no such package is available to the
* caller.
- * @deprecated Use {@link #getPackageGids(String, PackageInfoFlags)} instead.
*/
- @Deprecated
+
public abstract int[] getPackageGids(@NonNull String packageName, int flags)
throws NameNotFoundException;
@@ -5404,14 +5405,14 @@ public abstract class PackageManager {
* Note that the same package will have different UIDs under different
* {@link UserHandle} on the same device.
*
+ * Use {@link #getPackageUid(String, PackageInfoFlags)} when long flags are needed.
+ *
* @param packageName The full name (i.e. com.google.apps.contacts) of the
* desired package.
* @return Returns an integer UID who owns the given package name.
* @throws NameNotFoundException if no such package is available to the
* caller.
- * @deprecated Use {@link #getPackageUid(String, PackageInfoFlags)} instead.
*/
- @Deprecated
public abstract int getPackageUid(@NonNull String packageName, int flags)
throws NameNotFoundException;
@@ -5445,10 +5446,9 @@ public abstract class PackageManager {
/**
* See {@link #getPackageUidAsUser(String, PackageInfoFlags, int)}.
- * @deprecated Use {@link #getPackageUidAsUser(String, PackageInfoFlags, int)} instead.
+ * Use {@link #getPackageUidAsUser(String, PackageInfoFlags, int)} when long flags are needed.
* @hide
*/
- @Deprecated
@SuppressWarnings("HiddenAbstractMethod")
@UnsupportedAppUsage
public abstract int getPackageUidAsUser(@NonNull String packageName,
@@ -5589,6 +5589,8 @@ public abstract class PackageManager {
* Retrieve all of the information we know about a particular
* package/application.
*
+ * Use {@link #getApplicationInfo(String, ApplicationInfoFlags)} when long flags are needed.
+ *
* @param packageName The full name (i.e. com.google.apps.contacts) of an
* application.
* @param flags Additional option flags to modify the data returned.
@@ -5601,10 +5603,8 @@ public abstract class PackageManager {
* which had been deleted with {@code DELETE_KEEP_DATA} flag set).
* @throws NameNotFoundException if a package with the given name cannot be
* found on the system.
- * @deprecated Use {@link #getApplicationInfo(String, ApplicationInfoFlags)} instead.
*/
@NonNull
- @Deprecated
public abstract ApplicationInfo getApplicationInfo(@NonNull String packageName,
int flags) throws NameNotFoundException;
@@ -5619,13 +5619,13 @@ public abstract class PackageManager {
}
/**
- * @deprecated Use {@link #getApplicationInfoAsUser(String, ApplicationInfoFlags, int)} instead.
+ * Use {@link #getApplicationInfoAsUser(String, ApplicationInfoFlags, int)} when long flags are
+ * needed.
* {@hide}
*/
@SuppressWarnings("HiddenAbstractMethod")
@NonNull
@UnsupportedAppUsage
- @Deprecated
public abstract ApplicationInfo getApplicationInfoAsUser(@NonNull String packageName,
int flags, @UserIdInt int userId) throws NameNotFoundException;
@@ -5642,6 +5642,9 @@ public abstract class PackageManager {
* Retrieve all of the information we know about a particular
* package/application, for a specific user.
*
+ * Use {@link #getApplicationInfoAsUser(String, ApplicationInfoFlags, UserHandle)} when long
+ * flags are needed.
+ *
* @param packageName The full name (i.e. com.google.apps.contacts) of an
* application.
* @param flags Additional option flags to modify the data returned.
@@ -5654,14 +5657,11 @@ public abstract class PackageManager {
* which had been deleted with {@code DELETE_KEEP_DATA} flag set).
* @throws NameNotFoundException if a package with the given name cannot be
* found on the system.
- * @deprecated Use {@link #getApplicationInfoAsUser(String, ApplicationInfoFlags, UserHandle)}
- * instead.
* @hide
*/
@NonNull
@RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS)
@SystemApi
- @Deprecated
public ApplicationInfo getApplicationInfoAsUser(@NonNull String packageName,
int flags, @NonNull UserHandle user)
throws NameNotFoundException {
@@ -5694,6 +5694,8 @@ public abstract class PackageManager {
* Retrieve all of the information we know about a particular activity
* class.
*
+ * Use {@link #getActivityInfo(ComponentName, ComponentInfoFlags)} when long flags are needed.
+ *
* @param component The full component name (i.e.
* com.google.apps.contacts/com.google.apps.contacts.
* ContactsList) of an Activity class.
@@ -5702,9 +5704,7 @@ public abstract class PackageManager {
* activity.
* @throws NameNotFoundException if a package with the given name cannot be
* found on the system.
- * @deprecated Use {@link #getActivityInfo(ComponentName, ComponentInfoFlags)} instead.
*/
- @Deprecated
@NonNull
public abstract ActivityInfo getActivityInfo(@NonNull ComponentName component,
int flags) throws NameNotFoundException;
@@ -5723,6 +5723,8 @@ public abstract class PackageManager {
* Retrieve all of the information we know about a particular receiver
* class.
*
+ * Use {@link #getReceiverInfo(ComponentName, ComponentInfoFlags)} when long flags are needed.
+ *
* @param component The full component name (i.e.
* com.google.apps.calendar/com.google.apps.calendar.
* CalendarAlarm) of a Receiver class.
@@ -5731,9 +5733,7 @@ public abstract class PackageManager {
* receiver.
* @throws NameNotFoundException if a package with the given name cannot be
* found on the system.
- * @deprecated Use {@link #getReceiverInfo(ComponentName, ComponentInfoFlags)} instead.
*/
- @Deprecated
@NonNull
public abstract ActivityInfo getReceiverInfo(@NonNull ComponentName component,
int flags) throws NameNotFoundException;
@@ -5751,6 +5751,8 @@ public abstract class PackageManager {
/**
* Retrieve all of the information we know about a particular service class.
*
+ * Use {@link #getServiceInfo(ComponentName, ComponentInfoFlags)} when long flags are needed.
+ *
* @param component The full component name (i.e.
* com.google.apps.media/com.google.apps.media.
* BackgroundPlayback) of a Service class.
@@ -5758,9 +5760,7 @@ public abstract class PackageManager {
* @return A {@link ServiceInfo} object containing information about the
* service.
* @throws NameNotFoundException if the component cannot be found on the system.
- * @deprecated Use {@link #getServiceInfo(ComponentName, ComponentInfoFlags)} instead.
*/
- @Deprecated
@NonNull
public abstract ServiceInfo getServiceInfo(@NonNull ComponentName component,
int flags) throws NameNotFoundException;
@@ -5779,6 +5779,8 @@ public abstract class PackageManager {
* Retrieve all of the information we know about a particular content
* provider class.
*
+ * Use {@link #getProviderInfo(ComponentName, ComponentInfoFlags)} when long flags are needed.
+ *
* @param component The full component name (i.e.
* com.google.providers.media/com.google.providers.media.
* MediaProvider) of a ContentProvider class.
@@ -5787,9 +5789,7 @@ public abstract class PackageManager {
* provider.
* @throws NameNotFoundException if a package with the given name cannot be
* found on the system.
- * @deprecated Use {@link #getProviderInfo(ComponentName, ComponentInfoFlags)} instead.
*/
- @Deprecated
@NonNull
public abstract ProviderInfo getProviderInfo(@NonNull ComponentName component,
int flags) throws NameNotFoundException;
@@ -5838,6 +5838,8 @@ public abstract class PackageManager {
/**
* Return a List of all packages that are installed for the current user.
*
+ * Use {@link #getInstalledPackages(PackageInfoFlags)} when long flags are needed.
+ *
* @param flags Additional option flags to modify the data returned.
* @return A List of PackageInfo objects, one for each installed package,
* containing information about the package. In the unlikely case
@@ -5847,15 +5849,12 @@ public abstract class PackageManager {
* applications (which includes installed applications as well as
* applications with data directory i.e. applications which had been
* deleted with {@code DELETE_KEEP_DATA} flag set).
- * @deprecated Use {@link #getInstalledPackages(PackageInfoFlags)} instead.
*/
- @Deprecated
@NonNull
public abstract List<PackageInfo> getInstalledPackages(int flags);
/**
* See {@link #getInstalledPackages(int)}.
- * @param flags
*/
@NonNull
public List<PackageInfo> getInstalledPackages(@NonNull PackageInfoFlags flags) {
@@ -5885,6 +5884,9 @@ public abstract class PackageManager {
* Return a List of all installed packages that are currently holding any of
* the given permissions.
*
+ * Use {@link #getPackagesHoldingPermissions(String[], PackageInfoFlags)} when long flags are
+ * needed.
+ *
* @param flags Additional option flags to modify the data returned.
* @return A List of PackageInfo objects, one for each installed package
* that holds any of the permissions that were provided, containing
@@ -5895,9 +5897,7 @@ public abstract class PackageManager {
* applications (which includes installed applications as well as
* applications with data directory i.e. applications which had been
* deleted with {@code DELETE_KEEP_DATA} flag set).
- * @deprecated Use {@link #getPackagesHoldingPermissions(String[], PackageInfoFlags)} instead.
*/
- @Deprecated
@NonNull
public abstract List<PackageInfo> getPackagesHoldingPermissions(
@NonNull String[] permissions, int flags);
@@ -5916,6 +5916,8 @@ public abstract class PackageManager {
* Return a List of all packages that are installed on the device, for a
* specific user.
*
+ * Use {@link #getInstalledPackagesAsUser(PackageInfoFlags, int)} when long flags are needed.
+ *
* @param flags Additional option flags to modify the data returned.
* @param userId The user for whom the installed packages are to be listed
* @return A List of PackageInfo objects, one for each installed package,
@@ -5926,10 +5928,8 @@ public abstract class PackageManager {
* applications (which includes installed applications as well as
* applications with data directory i.e. applications which had been
* deleted with {@code DELETE_KEEP_DATA} flag set).
- * @deprecated Use {@link #getInstalledPackagesAsUser(PackageInfoFlags, int)} instead.
* @hide
*/
- @Deprecated
@SuppressWarnings("HiddenAbstractMethod")
@NonNull
@SystemApi
@@ -6641,6 +6641,8 @@ public abstract class PackageManager {
* applications including those deleted with {@code DELETE_KEEP_DATA}
* (partially installed apps with data directory) will be returned.
*
+ * Use {@link #getInstalledApplications(ApplicationInfoFlags)} when long flags are needed.
+ *
* @param flags Additional option flags to modify the data returned.
* @return A List of ApplicationInfo objects, one for each installed
* application. In the unlikely case there are no installed
@@ -6650,10 +6652,8 @@ public abstract class PackageManager {
* applications (which includes installed applications as well as
* applications with data directory i.e. applications which had been
* deleted with {@code DELETE_KEEP_DATA} flag set).
- * @deprecated Use {@link #getInstalledApplications(ApplicationInfoFlags)} instead.
*/
@NonNull
- @Deprecated
public abstract List<ApplicationInfo> getInstalledApplications(int flags);
/**
@@ -6672,6 +6672,9 @@ public abstract class PackageManager {
* {@code DELETE_KEEP_DATA} (partially installed apps with data directory)
* will be returned.
*
+ * Use {@link #getInstalledApplicationsAsUser(ApplicationInfoFlags, int)} when long flags are
+ * needed.
+ *
* @param flags Additional option flags to modify the data returned.
* @param userId The user for whom the installed applications are to be
* listed
@@ -6683,13 +6686,11 @@ public abstract class PackageManager {
* applications (which includes installed applications as well as
* applications with data directory i.e. applications which had been
* deleted with {@code DELETE_KEEP_DATA} flag set).
- * @deprecated Use {@link #getInstalledApplicationsAsUser(ApplicationInfoFlags, int)} instead.
* @hide
*/
@SuppressWarnings("HiddenAbstractMethod")
@NonNull
@TestApi
- @Deprecated
public abstract List<ApplicationInfo> getInstalledApplicationsAsUser(
int flags, @UserIdInt int userId);
@@ -6848,13 +6849,13 @@ public abstract class PackageManager {
/**
* Get a list of shared libraries on the device.
*
+ * Use {@link #getSharedLibraries(PackageInfoFlags)} when long flags are needed.
+ *
* @param flags To filter the libraries to return.
* @return The shared library list.
*
* @see #MATCH_UNINSTALLED_PACKAGES
- * @deprecated Use {@link #getSharedLibraries(PackageInfoFlags)} instead.
*/
- @Deprecated
public abstract @NonNull List<SharedLibraryInfo> getSharedLibraries(int flags);
/**
@@ -6869,6 +6870,8 @@ public abstract class PackageManager {
/**
* Get a list of shared libraries on the device.
*
+ * Use {@link #getSharedLibrariesAsUser(PackageInfoFlags, int)} when long flags are needed.
+ *
* @param flags To filter the libraries to return.
* @param userId The user to query for.
* @return The shared library list.
@@ -6879,9 +6882,7 @@ public abstract class PackageManager {
* @see #MATCH_UNINSTALLED_PACKAGES
*
* @hide
- * @deprecated Use {@link #getSharedLibrariesAsUser(PackageInfoFlags, int)} instead.
*/
- @Deprecated
@SuppressWarnings("HiddenAbstractMethod")
public abstract @NonNull List<SharedLibraryInfo> getSharedLibrariesAsUser(int flags,
@UserIdInt int userId);
@@ -6899,14 +6900,14 @@ public abstract class PackageManager {
/**
* Get the list of shared libraries declared by a package.
*
+ * Use {@link #getDeclaredSharedLibraries(String, PackageInfoFlags)} when long flags are needed.
+ *
* @param packageName the package name to query
* @param flags the flags to filter packages
* @return the shared library list
*
* @hide
- * @deprecated Use {@link #getDeclaredSharedLibraries(String, PackageInfoFlags)} instead.
*/
- @Deprecated
@SuppressWarnings("HiddenAbstractMethod")
@NonNull
@RequiresPermission(Manifest.permission.ACCESS_SHARED_LIBRARIES)
@@ -7015,6 +7016,8 @@ public abstract class PackageManager {
* Intent.resolveActivity(PackageManager)} do.
* </p>
*
+ * Use {@link #resolveActivity(Intent, ResolveInfoFlags)} when long flags are needed.
+ *
* @param intent An intent containing all of the desired specification
* (action, data, type, category, and/or component).
* @param flags Additional option flags to modify the data returned. The
@@ -7026,9 +7029,7 @@ public abstract class PackageManager {
* matching activity was found. If multiple matching activities are
* found and there is no default set, returns a ResolveInfo object
* containing something else, such as the activity resolver.
- * @deprecated Use {@link #resolveActivity(Intent, ResolveInfoFlags)} instead.
*/
- @Deprecated
@Nullable
public abstract ResolveInfo resolveActivity(@NonNull Intent intent, int flags);
@@ -7055,6 +7056,8 @@ public abstract class PackageManager {
* Intent.resolveActivity(PackageManager)} do.
* </p>
*
+ * Use {@link #resolveActivityAsUser(Intent, ResolveInfoFlags, int)} when long flags are needed.
+ *
* @param intent An intent containing all of the desired specification
* (action, data, type, category, and/or component).
* @param flags Additional option flags to modify the data returned. The
@@ -7068,9 +7071,7 @@ public abstract class PackageManager {
* found and there is no default set, returns a ResolveInfo object
* containing something else, such as the activity resolver.
* @hide
- * @deprecated Use {@link #resolveActivityAsUser(Intent, ResolveInfoFlags, int)} instead.
*/
- @Deprecated
@SuppressWarnings("HiddenAbstractMethod")
@Nullable
@UnsupportedAppUsage
@@ -7091,6 +7092,8 @@ public abstract class PackageManager {
/**
* Retrieve all activities that can be performed for the given intent.
*
+ * Use {@link #queryIntentActivities(Intent, ResolveInfoFlags)} when long flags are needed.
+ *
* @param intent The desired intent as per resolveActivity().
* @param flags Additional option flags to modify the data returned. The
* most important is {@link #MATCH_DEFAULT_ONLY}, to limit the
@@ -7102,9 +7105,7 @@ public abstract class PackageManager {
* words, the first item is what would be returned by
* {@link #resolveActivity}. If there are no matching activities, an
* empty list is returned.
- * @deprecated Use {@link #queryIntentActivities(Intent, ResolveInfoFlags)} instead.
*/
- @Deprecated
@NonNull
public abstract List<ResolveInfo> queryIntentActivities(@NonNull Intent intent, int flags);
@@ -7122,6 +7123,9 @@ public abstract class PackageManager {
* Retrieve all activities that can be performed for the given intent, for a
* specific user.
*
+ * Use {@link #queryIntentActivitiesAsUser(Intent, ResolveInfoFlags, int)} when long flags are
+ * needed.
+ *
* @param intent The desired intent as per resolveActivity().
* @param flags Additional option flags to modify the data returned. The
* most important is {@link #MATCH_DEFAULT_ONLY}, to limit the
@@ -7134,9 +7138,7 @@ public abstract class PackageManager {
* {@link #resolveActivity}. If there are no matching activities, an
* empty list is returned.
* @hide
- * @deprecated Use {@link #queryIntentActivitiesAsUser(Intent, ResolveInfoFlags, int)} instead.
*/
- @Deprecated
@SuppressWarnings("HiddenAbstractMethod")
@NonNull
@UnsupportedAppUsage
@@ -7158,6 +7160,9 @@ public abstract class PackageManager {
* Retrieve all activities that can be performed for the given intent, for a
* specific user.
*
+ * Use {@link #queryIntentActivitiesAsUser(Intent, ResolveInfoFlags, UserHandle)} when long
+ * flags are needed.
+ *
* @param intent The desired intent as per resolveActivity().
* @param flags Additional option flags to modify the data returned. The
* most important is {@link #MATCH_DEFAULT_ONLY}, to limit the
@@ -7171,10 +7176,7 @@ public abstract class PackageManager {
* {@link #resolveActivity}. If there are no matching activities, an
* empty list is returned.
* @hide
- * @deprecated Use {@link #queryIntentActivitiesAsUser(Intent, ResolveInfoFlags, UserHandle)}
- * instead.
*/
- @Deprecated
@SuppressWarnings("HiddenAbstractMethod")
@NonNull
@RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS)
@@ -7204,6 +7206,9 @@ public abstract class PackageManager {
* final ResolveInfo list in a reasonable order, with no duplicates, based
* on those inputs.
*
+ * Use {@link #queryIntentActivityOptions(ComponentName, List, Intent, ResolveInfoFlags)} when
+ * long flags are needed.
+ *
* @param caller The class name of the activity that is making the request.
* This activity will never appear in the output list. Can be
* null.
@@ -7220,10 +7225,7 @@ public abstract class PackageManager {
* activities that can handle <var>intent</var> but did not get
* included by one of the <var>specifics</var> intents. If there are
* no matching activities, an empty list is returned.
- * @deprecated Use {@link #queryIntentActivityOptions(ComponentName, List, Intent,
- * ResolveInfoFlags)} instead.
*/
- @Deprecated
@NonNull
public abstract List<ResolveInfo> queryIntentActivityOptions(@Nullable ComponentName caller,
@Nullable Intent[] specifics, @NonNull Intent intent, int flags);
@@ -7242,14 +7244,14 @@ public abstract class PackageManager {
/**
* Retrieve all receivers that can handle a broadcast of the given intent.
*
+ * Use {@link #queryBroadcastReceivers(Intent, ResolveInfoFlags)} when long flags are needed.
+ *
* @param intent The desired intent as per resolveActivity().
* @param flags Additional option flags to modify the data returned.
* @return Returns a List of ResolveInfo objects containing one entry for
* each matching receiver, ordered from best to worst. If there are
* no matching receivers, an empty list or null is returned.
- * @deprecated Use {@link #queryBroadcastReceivers(Intent, ResolveInfoFlags)} instead.
*/
- @Deprecated
@NonNull
public abstract List<ResolveInfo> queryBroadcastReceivers(@NonNull Intent intent, int flags);
@@ -7267,6 +7269,9 @@ public abstract class PackageManager {
* Retrieve all receivers that can handle a broadcast of the given intent,
* for a specific user.
*
+ * Use {@link #queryBroadcastReceiversAsUser(Intent, ResolveInfoFlags, UserHandle)} when long
+ * flags are needed.
+ *
* @param intent The desired intent as per resolveActivity().
* @param flags Additional option flags to modify the data returned.
* @param userHandle UserHandle of the user being queried.
@@ -7274,10 +7279,7 @@ public abstract class PackageManager {
* each matching receiver, ordered from best to worst. If there are
* no matching receivers, an empty list or null is returned.
* @hide
- * @deprecated Use {@link #queryBroadcastReceiversAsUser(Intent, ResolveInfoFlags, UserHandle)}
- * instead.
*/
- @Deprecated
@SuppressWarnings("HiddenAbstractMethod")
@NonNull
@SystemApi
@@ -7301,10 +7303,9 @@ public abstract class PackageManager {
/**
* @hide
- * @deprecated Use {@link #queryBroadcastReceiversAsUser(Intent, ResolveInfoFlags, int)}
- * instead.
+ * Use {@link #queryBroadcastReceiversAsUser(Intent, ResolveInfoFlags, int)} when long flags are
+ * needed.
*/
- @Deprecated
@SuppressWarnings("HiddenAbstractMethod")
@NonNull
@UnsupportedAppUsage
@@ -7342,15 +7343,15 @@ public abstract class PackageManager {
/**
* Determine the best service to handle for a given Intent.
*
+ * Use {@link #resolveService(Intent, ResolveInfoFlags)} when long flags are needed.
+ *
* @param intent An intent containing all of the desired specification
* (action, data, type, category, and/or component).
* @param flags Additional option flags to modify the data returned.
* @return Returns a ResolveInfo object containing the final service intent
* that was determined to be the best action. Returns null if no
* matching service was found.
- * @deprecated Use {@link #resolveService(Intent, ResolveInfoFlags)} instead.
*/
- @Deprecated
@Nullable
public abstract ResolveInfo resolveService(@NonNull Intent intent, int flags);
@@ -7365,9 +7366,8 @@ public abstract class PackageManager {
/**
* @hide
- * @deprecated Use {@link #resolveServiceAsUser(Intent, ResolveInfoFlags, int)} instead.
+ * Use {@link #resolveServiceAsUser(Intent, ResolveInfoFlags, int)} when long flags are needed.
*/
- @Deprecated
@SuppressWarnings("HiddenAbstractMethod")
@Nullable
public abstract ResolveInfo resolveServiceAsUser(@NonNull Intent intent,
@@ -7387,6 +7387,8 @@ public abstract class PackageManager {
/**
* Retrieve all services that can match the given intent.
*
+ * Use {@link #queryIntentServices(Intent, ResolveInfoFlags)} when long flags are needed.
+ *
* @param intent The desired intent as per resolveService().
* @param flags Additional option flags to modify the data returned.
* @return Returns a List of ResolveInfo objects containing one entry for
@@ -7394,9 +7396,7 @@ public abstract class PackageManager {
* words, the first item is what would be returned by
* {@link #resolveService}. If there are no matching services, an
* empty list or null is returned.
- * @deprecated Use {@link #queryIntentServices(Intent, ResolveInfoFlags)} instead.
*/
- @Deprecated
@NonNull
public abstract List<ResolveInfo> queryIntentServices(@NonNull Intent intent,
int flags);
@@ -7414,6 +7414,9 @@ public abstract class PackageManager {
/**
* Retrieve all services that can match the given intent for a given user.
*
+ * Use {@link #queryIntentServicesAsUser(Intent, ResolveInfoFlags, int)} when long flags are
+ * needed.
+ *
* @param intent The desired intent as per resolveService().
* @param flags Additional option flags to modify the data returned.
* @param userId The user id.
@@ -7423,9 +7426,7 @@ public abstract class PackageManager {
* {@link #resolveService}. If there are no matching services, an
* empty list or null is returned.
* @hide
- * @deprecated Use {@link #queryIntentServicesAsUser(Intent, ResolveInfoFlags, int)} instead.
*/
- @Deprecated
@SuppressWarnings("HiddenAbstractMethod")
@NonNull
@UnsupportedAppUsage
@@ -7446,6 +7447,9 @@ public abstract class PackageManager {
/**
* Retrieve all services that can match the given intent for a given user.
*
+ * Use {@link #queryIntentServicesAsUser(Intent, ResolveInfoFlags, UserHandle)} when long flags
+ * are needed.
+ *
* @param intent The desired intent as per resolveService().
* @param flags Additional option flags to modify the data returned.
* @param user The user being queried.
@@ -7455,10 +7459,7 @@ public abstract class PackageManager {
* {@link #resolveService}. If there are no matching services, an
* empty list or null is returned.
* @hide
- * @deprecated Use {@link #queryIntentServicesAsUser(Intent, ResolveInfoFlags, UserHandle)}
- * instead.
*/
- @Deprecated
@NonNull
@RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS)
@SystemApi
@@ -7481,6 +7482,9 @@ public abstract class PackageManager {
/**
* Retrieve all providers that can match the given intent.
*
+ * Use {@link #queryIntentContentProvidersAsUser(Intent, ResolveInfoFlags, int)} when long flags
+ * are needed.
+ *
* @param intent An intent containing all of the desired specification
* (action, data, type, category, and/or component).
* @param flags Additional option flags to modify the data returned.
@@ -7489,10 +7493,7 @@ public abstract class PackageManager {
* each matching provider, ordered from best to worst. If there are
* no matching services, an empty list or null is returned.
* @hide
- * @deprecated Use {@link #queryIntentContentProvidersAsUser(Intent, ResolveInfoFlags, int)}
- * instead.
*/
- @Deprecated
@SuppressWarnings("HiddenAbstractMethod")
@NonNull
@UnsupportedAppUsage
@@ -7513,6 +7514,9 @@ public abstract class PackageManager {
/**
* Retrieve all providers that can match the given intent.
*
+ * Use {@link #queryIntentContentProvidersAsUser(Intent, ResolveInfoFlags, UserHandle)} when
+ * long flags are needed.
+ *
* @param intent An intent containing all of the desired specification
* (action, data, type, category, and/or component).
* @param flags Additional option flags to modify the data returned.
@@ -7521,10 +7525,7 @@ public abstract class PackageManager {
* each matching provider, ordered from best to worst. If there are
* no matching services, an empty list or null is returned.
* @hide
- * @deprecated Use {@link #queryIntentContentProvidersAsUser(Intent, ResolveInfoFlags,
- * UserHandle)} instead.
*/
- @Deprecated
@NonNull
@RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS)
@SystemApi
@@ -7548,15 +7549,16 @@ public abstract class PackageManager {
/**
* Retrieve all providers that can match the given intent.
*
+ * Use {@link #queryIntentContentProviders(Intent, ResolveInfoFlags)} when long flags are
+ * needed.
+ *
* @param intent An intent containing all of the desired specification
* (action, data, type, category, and/or component).
* @param flags Additional option flags to modify the data returned.
* @return Returns a List of ResolveInfo objects containing one entry for
* each matching provider, ordered from best to worst. If there are
* no matching services, an empty list or null is returned.
- * @deprecated Use {@link #queryIntentContentProviders(Intent, ResolveInfoFlags)} instead.
*/
- @Deprecated
@NonNull
public abstract List<ResolveInfo> queryIntentContentProviders(@NonNull Intent intent,
int flags);
@@ -7580,13 +7582,13 @@ public abstract class PackageManager {
* ProviderInfo info = packageManager.resolveContentProvider(uri.getAuthority(), flags);
* </pre>
*
+ * Use {@link #resolveContentProvider(String, ComponentInfoFlags)} when long flags are needed.
+ *
* @param authority The authority of the provider to find.
* @param flags Additional option flags to modify the data returned.
* @return A {@link ProviderInfo} object containing information about the
* provider. If a provider was not found, returns null.
- * @deprecated Use {@link #resolveContentProvider(String, ComponentInfoFlags)} instead.
*/
- @Deprecated
@Nullable
public abstract ProviderInfo resolveContentProvider(@NonNull String authority,
int flags);
@@ -7604,14 +7606,15 @@ public abstract class PackageManager {
/**
* Find a single content provider by its base path name.
*
+ * Use {@link #resolveContentProviderAsUser(String, ComponentInfoFlags, int)} when long flags
+ * are needed.
+ *
* @param providerName The name of the provider to find.
* @param flags Additional option flags to modify the data returned.
* @param userId The user id.
* @return A {@link ProviderInfo} object containing information about the
* provider. If a provider was not found, returns null.
* @hide
- * @deprecated Use {@link #resolveContentProviderAsUser(String, ComponentInfoFlags, int)}
- * instead.
*/
@SuppressWarnings("HiddenAbstractMethod")
@Nullable
@@ -7636,6 +7639,9 @@ public abstract class PackageManager {
* <em>Note: unlike most other methods, an empty result set is indicated
* by a null return instead of an empty list.</em>
*
+ * Use {@link #queryContentProviders(String, int, ComponentInfoFlags)} when long flags are
+ * needed.
+ *
* @param processName If non-null, limits the returned providers to only
* those that are hosted by the given process. If null, all
* content providers are returned.
@@ -7646,9 +7652,7 @@ public abstract class PackageManager {
* each provider either matching <var>processName</var> or, if
* <var>processName</var> is null, all known content providers.
* <em>If there are no matching providers, null is returned.</em>
- * @deprecated Use {@link #queryContentProviders(String, int, ComponentInfoFlags)} instead.
*/
- @Deprecated
@NonNull
public abstract List<ProviderInfo> queryContentProviders(
@Nullable String processName, int uid, int flags);
@@ -7676,11 +7680,11 @@ public abstract class PackageManager {
* to mark GAL providers, rather than intent filters, so we can't use
* {@link #queryIntentContentProviders} for that.
*
+ * Use {@link #queryContentProviders(String, int, ComponentInfoFlags, String)} when long flags
+ * are needed.
+ *
* @hide
- * @deprecated Use {@link #queryContentProviders(String, int, ComponentInfoFlags, String)}
- * instead.
*/
- @Deprecated
@NonNull
public List<ProviderInfo> queryContentProviders(@Nullable String processName,
int uid, int flags, String metaDataKey) {
@@ -8226,13 +8230,13 @@ public abstract class PackageManager {
* Retrieve overall information about an application package defined in a
* package archive file
*
+ * Use {@link #getPackageArchiveInfo(String, PackageInfoFlags)} when long flags are needed.
+ *
* @param archiveFilePath The path to the archive file
* @param flags Additional option flags to modify the data returned.
* @return A PackageInfo object containing information about the package
* archive. If the package could not be parsed, returns null.
- * @deprecated Use {@link #getPackageArchiveInfo(String, PackageInfoFlags)} instead.
*/
- @Deprecated
@Nullable
public PackageInfo getPackageArchiveInfo(@NonNull String archiveFilePath, int flags) {
return getPackageArchiveInfo(archiveFilePath, PackageInfoFlags.of(flags));
diff --git a/core/java/android/content/pm/ServiceInfo.java b/core/java/android/content/pm/ServiceInfo.java
index f3ad9d1488ff..1a3c3d97634c 100644
--- a/core/java/android/content/pm/ServiceInfo.java
+++ b/core/java/android/content/pm/ServiceInfo.java
@@ -361,7 +361,7 @@ public class ServiceInfo extends ComponentInfo
/**
* Constant corresponding to {@code systemExempted} in
* the {@link android.R.attr#foregroundServiceType} attribute.
- * The system exmpted foreground service use cases.
+ * The system exempted foreground service use cases.
*
* <p class="note">Note, apps are allowed to use this type only in the following cases:
* <ul>
@@ -376,8 +376,8 @@ public class ServiceInfo extends ComponentInfo
* <li>Headless system apps</li>
* <li><a href="{@docRoot}guide/topics/admin/device-admin">Device admin apps</a></li>
* <li>Active VPN apps</li>
- * <li>Apps holding {@link Manifest.permission#SCHEDULE_EXACT_ALARM} or
- * {@link Manifest.permission#USE_EXACT_ALARM} permission.</li>
+ * <li>Apps holding {@link android.Manifest.permission#SCHEDULE_EXACT_ALARM} or
+ * {@link android.Manifest.permission#USE_EXACT_ALARM} permission.</li>
* </ul>
* </p>
*/
@@ -393,7 +393,7 @@ public class ServiceInfo extends ComponentInfo
*
* <p>Unlike other foreground service types, this type is not associated with a specific use
* case, and it will not require any special permissions
- * (besides {@link Manifest.permission#FOREGROUND_SERVICE}).
+ * (besides {@link android.Manifest.permission#FOREGROUND_SERVICE}).
*
* However, this type has the following restrictions.
*
@@ -401,19 +401,21 @@ public class ServiceInfo extends ComponentInfo
* <li>
* The type has a 3 minute timeout.
* A foreground service of this type must be stopped within the timeout by
- * {@link android.app.Service#stopSelf),
- * or {@link android.content.Context#stopService).
- * {@link android.app.Service#stopForeground) will also work, which will demote the
+ * {@link android.app.Service#stopSelf()},
+ * {@link android.content.Context#stopService(android.content.Intent)}
+ * or their overloads).
+ * {@link android.app.Service#stopForeground(int)} will also work,
+ * which will demote the
* service to a "background" service, which will soon be stopped by the system.
*
- * <p>The system will <em>not</em> automatically stop it.
- *
* <p>If the service isn't stopped within the timeout,
- * {@link android.app.Service#onTimeout(int)} will be called.
+ * {@link android.app.Service#onTimeout(int)} will be called. Note, even when the
+ * system calls this callback, it will not stop the service automatically.
+ * You still need to stop the service using one of the aforementioned
+ * ways even when you get this callback.
*
* <p>If the service is still not stopped after the callback,
- * the app will be declared an ANR after a short grace period of several seconds.
- *
+ * the app will be declared an ANR, after a short grace period of several seconds.
* <li>
* A foreground service of this type cannot be made "sticky"
* (see {@link android.app.Service#START_STICKY}). That is, if an app is killed
@@ -427,10 +429,26 @@ public class ServiceInfo extends ComponentInfo
* <a href="/guide/components/foreground-services#background-start-restrictions>
* Restrictions on background starts
* </a>
+ * <li>
+ * You can combine multiple foreground services types with {@code |}s, and you can
+ * combine
+ * {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_SHORT_SERVICE}.
+ * with other types as well.
+ * However,
+ * {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_SHORT_SERVICE}
+ * is for situations
+ * where you have no other valid foreground services to use and the timeout is long
+ * enough for the task, and if you can use other types, there's no point using
+ * this type.
+ * For this reason, if
+ * {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_SHORT_SERVICE}
+ * is combined with other foreground service types, the system will simply ignore
+ * it, and as a result,
+ * none of the above restrictions will apply (e.g. there'll be no timeout).
* </ul>
*
- * <p>Note, even though
- * {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_SHORT_SERVICE}
+ * <p>Also note, even though
+ * {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_SHORT_SERVICE}
* was added
* on Android version {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
* it can be also used on
diff --git a/core/java/android/content/pm/TEST_MAPPING b/core/java/android/content/pm/TEST_MAPPING
index 45e0efb46616..b6012757c35d 100644
--- a/core/java/android/content/pm/TEST_MAPPING
+++ b/core/java/android/content/pm/TEST_MAPPING
@@ -28,7 +28,13 @@
"path": "cts/hostsidetests/os/test_mappings/packagemanager"
},
{
+ "path": "cts/hostsidetests/appsearch"
+ },
+ {
"path": "system/apex/tests"
+ },
+ {
+ "path": "cts/tests/tests/content/pm/SecureFrp"
}
],
"presubmit": [
@@ -43,6 +49,12 @@
"name": "ApkVerityTest"
},
{
+ "name": "CtsSilentUpdateHostTestCases"
+ },
+ {
+ "name": "CtsSuspendAppsTestCases"
+ },
+ {
"name": "CtsAppFgsTestCases",
"file_patterns": ["(/|^)ServiceInfo[^/]*"],
"options": [
@@ -108,50 +120,6 @@
]
},
{
- "name": "CtsAppSearchHostTestCases",
- "options": [
- {
- "exclude-annotation": "androidx.test.filters.FlakyTest"
- },
- {
- "exclude-annotation": "org.junit.Ignore"
- }
- ]
- },
- {
- "name": "CtsSilentUpdateHostTestCases",
- "options": [
- {
- "exclude-annotation": "androidx.test.filters.FlakyTest"
- },
- {
- "exclude-annotation": "org.junit.Ignore"
- }
- ]
- },
- {
- "name": "CtsSuspendAppsTestCases",
- "options": [
- {
- "exclude-annotation": "androidx.test.filters.FlakyTest"
- },
- {
- "exclude-annotation": "org.junit.Ignore"
- }
- ]
- },
- {
- "name": "CtsSecureFrpInstallTestCases",
- "options": [
- {
- "exclude-annotation": "androidx.test.filters.FlakyTest"
- },
- {
- "exclude-annotation": "org.junit.Ignore"
- }
- ]
- },
- {
"name": "CtsSuspendAppsPermissionTestCases",
"options": [
{
diff --git a/core/java/android/content/pm/UserPackage.java b/core/java/android/content/pm/UserPackage.java
index 7ca92c3d4777..c35e67801b71 100644
--- a/core/java/android/content/pm/UserPackage.java
+++ b/core/java/android/content/pm/UserPackage.java
@@ -18,14 +18,16 @@ package android.content.pm;
import android.annotation.NonNull;
import android.annotation.UserIdInt;
-import android.os.Process;
-import android.os.UserHandle;
import android.util.SparseArrayMap;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
+import libcore.util.EmptyArray;
+
import java.util.Objects;
+import java.util.Random;
/**
* POJO to represent a package for a specific user ID.
@@ -34,6 +36,16 @@ import java.util.Objects;
*/
public final class UserPackage {
private static final boolean ENABLE_CACHING = true;
+ /**
+ * The maximum number of entries to keep in the cache per user ID.
+ * The value should ideally be high enough to cover all packages on an end-user device,
+ * but low enough that stale or invalid packages would eventually (probably) get removed.
+ * This should benefit components that loop through all packages on a device and use this class,
+ * since being able to cache the objects for all packages on the device
+ * means we don't have to keep recreating the objects.
+ */
+ @VisibleForTesting
+ static final int MAX_NUM_CACHED_ENTRIES_PER_USER = 1000;
@UserIdInt
public final int userId;
@@ -43,11 +55,13 @@ public final class UserPackage {
@GuardedBy("sCacheLock")
private static final SparseArrayMap<String, UserPackage> sCache = new SparseArrayMap<>();
- private static final class NoPreloadHolder {
- /** Set of userIDs to cache objects for. */
- @GuardedBy("sCacheLock")
- private static int[] sUserIds = new int[]{UserHandle.getUserId(Process.myUid())};
- }
+ /**
+ * Set of userIDs to cache objects for. We start off with an empty set, so there's no caching
+ * by default. The system will override with a valid set of userIDs in its process so that
+ * caching becomes active in the system process.
+ */
+ @GuardedBy("sCacheLock")
+ private static int[] sUserIds = EmptyArray.INT;
private UserPackage(int userId, String packageName) {
this.userId = userId;
@@ -87,13 +101,14 @@ public final class UserPackage {
}
synchronized (sCacheLock) {
- if (!ArrayUtils.contains(NoPreloadHolder.sUserIds, userId)) {
+ if (!ArrayUtils.contains(sUserIds, userId)) {
// Don't cache objects for invalid userIds.
return new UserPackage(userId, packageName);
}
UserPackage up = sCache.get(userId, packageName);
if (up == null) {
+ maybePurgeRandomEntriesLocked(userId);
packageName = packageName.intern();
up = new UserPackage(userId, packageName);
sCache.add(userId, packageName, up);
@@ -121,7 +136,7 @@ public final class UserPackage {
userIds = userIds.clone();
synchronized (sCacheLock) {
- NoPreloadHolder.sUserIds = userIds;
+ sUserIds = userIds;
for (int u = sCache.numMaps() - 1; u >= 0; --u) {
final int userId = sCache.keyAt(u);
@@ -131,4 +146,35 @@ public final class UserPackage {
}
}
}
+
+ @VisibleForTesting
+ public static int numEntriesForUser(int userId) {
+ synchronized (sCacheLock) {
+ return sCache.numElementsForKey(userId);
+ }
+ }
+
+ /** Purge a random set of entries if the cache size is too large. */
+ @GuardedBy("sCacheLock")
+ private static void maybePurgeRandomEntriesLocked(int userId) {
+ final int uIdx = sCache.indexOfKey(userId);
+ if (uIdx < 0) {
+ return;
+ }
+ int numCached = sCache.numElementsForKeyAt(uIdx);
+ if (numCached < MAX_NUM_CACHED_ENTRIES_PER_USER) {
+ return;
+ }
+ // Purge a random set of 1% of cached elements for the userId. We don't want to use a
+ // deterministic system of purging because that may cause us to repeatedly remove elements
+ // that are frequently added and queried more than others. Choosing a random set
+ // means we will probably eventually remove less useful elements.
+ // An LRU cache is too expensive for this commonly used utility class.
+ final Random rand = new Random();
+ final int numToPurge = Math.max(1, MAX_NUM_CACHED_ENTRIES_PER_USER / 100);
+ for (int i = 0; i < numToPurge && numCached > 0; ++i) {
+ final int removeIdx = rand.nextInt(numCached--);
+ sCache.deleteAt(uIdx, removeIdx);
+ }
+ }
}
diff --git a/core/java/android/content/res/FontScaleConverterFactory.java b/core/java/android/content/res/FontScaleConverterFactory.java
index ffdc7b3807cf..6b09c303e3cd 100644
--- a/core/java/android/content/res/FontScaleConverterFactory.java
+++ b/core/java/android/content/res/FontScaleConverterFactory.java
@@ -18,6 +18,7 @@ package android.content.res;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.util.MathUtils;
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
@@ -98,22 +99,81 @@ public class FontScaleConverterFactory {
public static FontScaleConverter forScale(float fontScale) {
if (fontScale <= 1) {
// We don't need non-linear curves for shrinking text or for 100%.
- // Also, fontScale==0 should not have a curve either
+ // Also, fontScale==0 should not have a curve either.
+ // And ignore negative font scales; that's just silly.
return null;
}
FontScaleConverter lookupTable = get(fontScale);
- // TODO(b/247861716): interpolate between two tables when null
+ if (lookupTable != null) {
+ return lookupTable;
+ }
+
+ // Didn't find an exact match: interpolate between two existing tables
+ final int index = LOOKUP_TABLES.indexOfKey(getKey(fontScale));
+ if (index >= 0) {
+ // This should never happen, should have been covered by get() above.
+ return LOOKUP_TABLES.valueAt(index);
+ }
+ // Didn't find an exact match: interpolate between two existing tables
+ final int lowerIndex = -(index + 1) - 1;
+ final int higherIndex = lowerIndex + 1;
+ if (lowerIndex < 0 || higherIndex >= LOOKUP_TABLES.size()) {
+ // We have gone beyond our bounds and have nothing to interpolate between. Just give
+ // them a straight linear table instead.
+ // This works because when FontScaleConverter encounters a size beyond its bounds, it
+ // calculates a linear fontScale factor using the ratio of the last element pair.
+ return new FontScaleConverter(new float[] {1f}, new float[] {fontScale});
+ } else {
+ float startScale = getScaleFromKey(LOOKUP_TABLES.keyAt(lowerIndex));
+ float endScale = getScaleFromKey(LOOKUP_TABLES.keyAt(higherIndex));
+ float interpolationPoint = MathUtils.constrainedMap(
+ /* rangeMin= */ 0f,
+ /* rangeMax= */ 1f,
+ startScale,
+ endScale,
+ fontScale
+ );
+ return createInterpolatedTableBetween(
+ LOOKUP_TABLES.valueAt(lowerIndex),
+ LOOKUP_TABLES.valueAt(higherIndex),
+ interpolationPoint);
+ }
+ }
+
+ @NonNull
+ private static FontScaleConverter createInterpolatedTableBetween(
+ FontScaleConverter start,
+ FontScaleConverter end,
+ float interpolationPoint
+ ) {
+ float[] commonSpSizes = new float[] { 8f, 10f, 12f, 14f, 18f, 20f, 24f, 30f, 100f};
+ float[] dpInterpolated = new float[commonSpSizes.length];
+
+ for (int i = 0; i < commonSpSizes.length; i++) {
+ float sp = commonSpSizes[i];
+ float startDp = start.convertSpToDp(sp);
+ float endDp = end.convertSpToDp(sp);
+ dpInterpolated[i] = MathUtils.lerp(startDp, endDp, interpolationPoint);
+ }
+
+ return new FontScaleConverter(commonSpSizes, dpInterpolated);
+ }
+
+ private static int getKey(float fontScale) {
+ return (int) (fontScale * SCALE_KEY_MULTIPLIER);
+ }
- return lookupTable;
+ private static float getScaleFromKey(int key) {
+ return (float) key / SCALE_KEY_MULTIPLIER;
}
private static void put(float scaleKey, @NonNull FontScaleConverter fontScaleConverter) {
- LOOKUP_TABLES.put((int) (scaleKey * SCALE_KEY_MULTIPLIER), fontScaleConverter);
+ LOOKUP_TABLES.put(getKey(scaleKey), fontScaleConverter);
}
@Nullable
private static FontScaleConverter get(float scaleKey) {
- return LOOKUP_TABLES.get((int) (scaleKey * SCALE_KEY_MULTIPLIER));
+ return LOOKUP_TABLES.get(getKey(scaleKey));
}
}
diff --git a/core/java/android/content/res/OWNERS b/core/java/android/content/res/OWNERS
index d12d920b2a54..a7bce122eb35 100644
--- a/core/java/android/content/res/OWNERS
+++ b/core/java/android/content/res/OWNERS
@@ -4,3 +4,5 @@ toddke@android.com
toddke@google.com
patb@google.com
zyy@google.com
+
+per-file FontScaleConverter*=fuego@google.com \ No newline at end of file
diff --git a/core/java/android/credentials/CreateCredentialRequest.java b/core/java/android/credentials/CreateCredentialRequest.java
index 1e2a86f2ed11..fc3dc796d3ed 100644
--- a/core/java/android/credentials/CreateCredentialRequest.java
+++ b/core/java/android/credentials/CreateCredentialRequest.java
@@ -16,9 +16,14 @@
package android.credentials;
+import static android.Manifest.permission.CREDENTIAL_MANAGER_SET_ORIGIN;
+
import static java.util.Objects.requireNonNull;
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -69,6 +74,14 @@ public final class CreateCredentialRequest implements Parcelable {
private final boolean mIsSystemProviderRequired;
/**
+ * The origin of the calling app. Callers of this special API (e.g. browsers)
+ * can set this origin for an app different from their own, to be able to get credentials
+ * on behalf of that app.
+ */
+ @Nullable
+ private final String mOrigin;
+
+ /**
* Returns the requested credential type.
*/
@NonNull
@@ -123,6 +136,14 @@ public final class CreateCredentialRequest implements Parcelable {
return mAlwaysSendAppInfoToProvider;
}
+ /**
+ * Returns the origin of the calling app if set otherwise returns null.
+ */
+ @Nullable
+ public String getOrigin() {
+ return mOrigin;
+ }
+
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString8(mType);
@@ -130,6 +151,7 @@ public final class CreateCredentialRequest implements Parcelable {
dest.writeBundle(mCandidateQueryData);
dest.writeBoolean(mIsSystemProviderRequired);
dest.writeBoolean(mAlwaysSendAppInfoToProvider);
+ dest.writeString8(mOrigin);
}
@Override
@@ -146,6 +168,7 @@ public final class CreateCredentialRequest implements Parcelable {
+ ", isSystemProviderRequired=" + mIsSystemProviderRequired
+ ", alwaysSendAppInfoToProvider="
+ mAlwaysSendAppInfoToProvider
+ + ", origin=" + mOrigin
+ "}";
}
@@ -165,21 +188,26 @@ public final class CreateCredentialRequest implements Parcelable {
* the query phase, and will only be sent along
* with the final request, after the user has selected
* an entry on the UI.
+ * @param origin the origin of the calling app. Callers of this special setter (e.g. browsers)
+ * can set this origin for an app different from their own, to be able to get
+ * credentials on behalf of that app.
*
* @throws IllegalArgumentException If type is empty.
*/
- public CreateCredentialRequest(
+ private CreateCredentialRequest(
@NonNull String type,
@NonNull Bundle credentialData,
@NonNull Bundle candidateQueryData,
boolean isSystemProviderRequired,
- boolean alwaysSendAppInfoToProvider) {
+ boolean alwaysSendAppInfoToProvider,
+ @NonNull String origin) {
mType = Preconditions.checkStringNotEmpty(type, "type must not be empty");
mCredentialData = requireNonNull(credentialData, "credentialData must not be null");
mCandidateQueryData = requireNonNull(candidateQueryData,
"candidateQueryData must not be null");
mIsSystemProviderRequired = isSystemProviderRequired;
mAlwaysSendAppInfoToProvider = alwaysSendAppInfoToProvider;
+ mOrigin = origin;
}
private CreateCredentialRequest(@NonNull Parcel in) {
@@ -188,6 +216,7 @@ public final class CreateCredentialRequest implements Parcelable {
Bundle candidateQueryData = in.readBundle();
boolean isSystemProviderRequired = in.readBoolean();
boolean alwaysSendAppInfoToProvider = in.readBoolean();
+ mOrigin = in.readString8();
mType = type;
AnnotationValidations.validate(NonNull.class, null, mType);
@@ -211,4 +240,100 @@ public final class CreateCredentialRequest implements Parcelable {
return new CreateCredentialRequest(in);
}
};
+
+ /** A builder for {@link CreateCredentialRequest}. */
+ public static final class Builder {
+
+ private boolean mAlwaysSendAppInfoToProvider = true;
+
+ @NonNull
+ private String mType;
+
+ @NonNull
+ private final Bundle mCredentialData;
+
+ @NonNull
+ private final Bundle mCandidateQueryData;
+
+ private boolean mIsSystemProviderRequired;
+
+ private String mOrigin;
+
+ /**
+ * @param type the type of the credential to be stored
+ * @param credentialData the full credential creation request data
+ * @param candidateQueryData the partial request data that will be sent to the provider
+ * during the initial creation candidate query stage
+ */
+ public Builder(
+ @NonNull String type,
+ @NonNull Bundle credentialData,
+ @NonNull Bundle candidateQueryData) {
+ mType = Preconditions.checkStringNotEmpty(type,
+ "type must not be null or empty");
+ mCredentialData = requireNonNull(credentialData,
+ "credentialData must not be null");
+ mCandidateQueryData = requireNonNull(candidateQueryData,
+ "candidateQueryData must not be null");
+ }
+
+ /**
+ * Sets a true/false value to determine if the calling app info should be
+ * removed from the request that is sent to the providers.
+ *
+ * Developers must set this to false if they wish to remove the
+ * {@link android.service.credentials.CallingAppInfo} from the query phases requests that
+ * providers receive. Note that the calling app info will still be sent in the
+ * final phase after the user has made a selection on the UI.
+ *
+ * If not set, the default value will be true and the calling app info will be
+ * propagated to the providers in every phase.
+ */
+ @SuppressLint("MissingGetterMatchingBuilder")
+ @NonNull
+ public CreateCredentialRequest.Builder setAlwaysSendAppInfoToProvider(boolean value) {
+ mAlwaysSendAppInfoToProvider = value;
+ return this;
+ }
+
+ /**
+ * Sets whether the request must only be fulfilled by a system provider.
+ * This defaults to false
+ */
+ @SuppressLint("MissingGetterMatchingBuilder")
+ @NonNull
+ public CreateCredentialRequest.Builder setIsSystemProviderRequired(boolean value) {
+ mIsSystemProviderRequired = value;
+ return this;
+ }
+
+ /**
+ * Sets the origin of the calling app. Callers of this special setter (e.g. browsers)
+ * can set this origin for an app different from their own, to be able to get
+ * credentials on behalf of that app. The permission check only happens later when this
+ * instance is passed and processed by the Credential Manager.
+ */
+ @SuppressLint({"MissingGetterMatchingBuilder", "AndroidFrameworkRequiresPermission"})
+ @RequiresPermission(CREDENTIAL_MANAGER_SET_ORIGIN)
+ @NonNull
+ public CreateCredentialRequest.Builder setOrigin(@NonNull String origin) {
+ mOrigin = origin;
+ return this;
+ }
+
+ /**
+ * Builds a {@link GetCredentialRequest}.
+ *
+ * @throws IllegalArgumentException If credentialOptions is empty.
+ */
+ @NonNull
+ public CreateCredentialRequest build() {
+ Preconditions.checkStringNotEmpty(
+ mType,
+ "type must not be empty");
+
+ return new CreateCredentialRequest(mType, mCredentialData, mCandidateQueryData,
+ mIsSystemProviderRequired, mAlwaysSendAppInfoToProvider, mOrigin);
+ }
+ }
}
diff --git a/core/java/android/credentials/CredentialDescription.java b/core/java/android/credentials/CredentialDescription.java
index f9db5e8bf44c..bf34c1cc5712 100644
--- a/core/java/android/credentials/CredentialDescription.java
+++ b/core/java/android/credentials/CredentialDescription.java
@@ -123,7 +123,7 @@ public final class CredentialDescription implements Parcelable {
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeString(mType);
+ dest.writeString8(mType);
dest.writeString(mFlattenedRequestString);
dest.writeTypedList(mCredentialEntries, flags);
}
@@ -151,16 +151,4 @@ public final class CredentialDescription implements Parcelable {
public List<CredentialEntry> getCredentialEntries() {
return mCredentialEntries;
}
-
- @Override
- public int hashCode() {
- return Objects.hash(mType, mFlattenedRequestString);
- }
-
- @Override
- public boolean equals(Object obj) {
- return Objects.equals(mType, ((CredentialDescription) obj).getType())
- && Objects.equals(mFlattenedRequestString, ((CredentialDescription) obj)
- .getFlattenedRequestString());
- }
}
diff --git a/core/java/android/credentials/CredentialManager.java b/core/java/android/credentials/CredentialManager.java
index ff7fc36e355d..f0230e7f4593 100644
--- a/core/java/android/credentials/CredentialManager.java
+++ b/core/java/android/credentials/CredentialManager.java
@@ -123,6 +123,10 @@ public final class CredentialManager {
*
* <p>The execution can potentially launch UI flows to collect user consent to using a
* credential, display a picker when multiple credentials exist, etc.
+ * Callers (e.g. browsers) may optionally set origin in {@link GetCredentialRequest} for an
+ * app different from their own, to be able to get credentials on behalf of that app. They would
+ * need additional permission {@link CREDENTIAL_MANAGER_SET_ORIGIN}
+ * to use this functionality
*
* @param request the request specifying type(s) of credentials to get from the user
* @param activity the activity used to launch any UI needed
@@ -163,61 +167,14 @@ public final class CredentialManager {
}
/**
- * Launches the necessary flows to retrieve an app credential from the user, for the given
- * origin.
- *
- * <p>The execution can potentially launch UI flows to collect user consent to using a
- * credential, display a picker when multiple credentials exist, etc.
- *
- * @param request the request specifying type(s) of credentials to get from the user
- * @param origin the origin of the calling app. Callers of this special API (e.g. browsers)
- * can set this origin for an app different from their own, to be able to get credentials
- * on behalf of that app.
- * @param activity the activity used to launch any UI needed
- * @param cancellationSignal an optional signal that allows for cancelling this call
- * @param executor the callback will take place on this {@link Executor}
- * @param callback the callback invoked when the request succeeds or fails
- */
- @RequiresPermission(CREDENTIAL_MANAGER_SET_ORIGIN)
- public void getCredentialWithOrigin(
- @NonNull GetCredentialRequest request,
- @Nullable String origin,
- @NonNull Activity activity,
- @Nullable CancellationSignal cancellationSignal,
- @CallbackExecutor @NonNull Executor executor,
- @NonNull OutcomeReceiver<GetCredentialResponse, GetCredentialException> callback) {
- requireNonNull(request, "request must not be null");
- requireNonNull(activity, "activity must not be null");
- requireNonNull(executor, "executor must not be null");
- requireNonNull(callback, "callback must not be null");
-
- if (cancellationSignal != null && cancellationSignal.isCanceled()) {
- Log.w(TAG, "getCredential already canceled");
- return;
- }
-
- ICancellationSignal cancelRemote = null;
- try {
- cancelRemote =
- mService.executeGetCredentialWithOrigin(
- request,
- new GetCredentialTransport(activity, executor, callback),
- mContext.getOpPackageName(),
- origin);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
-
- if (cancellationSignal != null && cancelRemote != null) {
- cancellationSignal.setRemote(cancelRemote);
- }
- }
-
- /**
* Launches the necessary flows to register an app credential for the user.
*
* <p>The execution can potentially launch UI flows to collect user consent to creating or
* storing the new credential, etc.
+ * Callers (e.g. browsers) may optionally set origin in {@link CreateCredentialRequest} for an
+ * app different from their own, to be able to get credentials on behalf of that app. They would
+ * need additional permission {@link CREDENTIAL_MANAGER_SET_ORIGIN}
+ * to use this functionality
*
* @param request the request specifying type(s) of credentials to get from the user
* @param activity the activity used to launch any UI needed
@@ -259,58 +216,6 @@ public final class CredentialManager {
}
/**
- * Launches the necessary flows to register an app credential for the user.
- *
- * <p>The execution can potentially launch UI flows to collect user consent to creating or
- * storing the new credential, etc.
- *
- * @param request the request specifying type(s) of credentials to get from the user, for the
- * given origin
- * @param origin the origin of the calling app. Callers of this special API (e.g. browsers)
- * can set this origin for an app different from their own, to be able to get credentials
- * on behalf of that app.
- * @param activity the activity used to launch any UI needed
- * @param cancellationSignal an optional signal that allows for cancelling this call
- * @param executor the callback will take place on this {@link Executor}
- * @param callback the callback invoked when the request succeeds or fails
- */
- @RequiresPermission(CREDENTIAL_MANAGER_SET_ORIGIN)
- public void createCredentialWithOrigin(
- @NonNull CreateCredentialRequest request,
- @Nullable String origin,
- @NonNull Activity activity,
- @Nullable CancellationSignal cancellationSignal,
- @CallbackExecutor @NonNull Executor executor,
- @NonNull
- OutcomeReceiver<CreateCredentialResponse, CreateCredentialException> callback) {
- requireNonNull(request, "request must not be null");
- requireNonNull(activity, "activity must not be null");
- requireNonNull(executor, "executor must not be null");
- requireNonNull(callback, "callback must not be null");
-
- if (cancellationSignal != null && cancellationSignal.isCanceled()) {
- Log.w(TAG, "createCredential already canceled");
- return;
- }
-
- ICancellationSignal cancelRemote = null;
- try {
- cancelRemote =
- mService.executeCreateCredentialWithOrigin(
- request,
- new CreateCredentialTransport(activity, executor, callback),
- mContext.getOpPackageName(),
- origin);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
-
- if (cancellationSignal != null && cancelRemote != null) {
- cancellationSignal.setRemote(cancelRemote);
- }
- }
-
- /**
* Clears the current user credential state from all credential providers.
*
* <p>You should invoked this api after your user signs out of your app to notify all credential
@@ -505,7 +410,19 @@ public final class CredentialManager {
*
* @hide
*/
- public static boolean isCredentialDescriptionApiEnabled() {
+ public static boolean isCredentialDescriptionApiEnabled(Context context) {
+ if (context == null) {
+ return false;
+ }
+ CredentialManager credentialManager =
+ (CredentialManager) context.getSystemService(Context.CREDENTIAL_SERVICE);
+ if (credentialManager != null) {
+ return credentialManager.isCredentialDescriptionApiEnabled();
+ }
+ return false;
+ }
+
+ private boolean isCredentialDescriptionApiEnabled() {
return DeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_CREDENTIAL, DEVICE_CONFIG_ENABLE_CREDENTIAL_DESC_API, false);
}
@@ -527,11 +444,6 @@ public final class CredentialManager {
*/
public void registerCredentialDescription(
@NonNull RegisterCredentialDescriptionRequest request) {
-
- if (!isCredentialDescriptionApiEnabled()) {
- throw new UnsupportedOperationException("This API is not currently supported.");
- }
-
requireNonNull(request, "request must not be null");
try {
@@ -550,11 +462,6 @@ public final class CredentialManager {
*/
public void unregisterCredentialDescription(
@NonNull UnregisterCredentialDescriptionRequest request) {
-
- if (!isCredentialDescriptionApiEnabled()) {
- throw new UnsupportedOperationException("This API is not currently supported.");
- }
-
requireNonNull(request, "request must not be null");
try {
diff --git a/core/java/android/credentials/GetCredentialRequest.java b/core/java/android/credentials/GetCredentialRequest.java
index bc92c7cb148a..c58d2dcd2dbf 100644
--- a/core/java/android/credentials/GetCredentialRequest.java
+++ b/core/java/android/credentials/GetCredentialRequest.java
@@ -16,9 +16,13 @@
package android.credentials;
+import static android.Manifest.permission.CREDENTIAL_MANAGER_SET_ORIGIN;
+
import static java.util.Objects.requireNonNull;
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.os.Parcel;
@@ -49,6 +53,14 @@ public final class GetCredentialRequest implements Parcelable {
private final Bundle mData;
/**
+ * The origin of the calling app. Callers of this special API (e.g. browsers)
+ * can set this origin for an app different from their own, to be able to get credentials
+ * on behalf of that app.
+ */
+ @Nullable
+ private String mOrigin;
+
+ /**
* True/False value to determine if the calling app info should be
* removed from the request that is sent to the providers.
* Developers must set this to false if they wish to remove the
@@ -76,6 +88,14 @@ public final class GetCredentialRequest implements Parcelable {
}
/**
+ * Returns the origin of the calling app if set otherwise returns null.
+ */
+ @Nullable
+ public String getOrigin() {
+ return mOrigin;
+ }
+
+ /**
* Returns a value to determine if the calling app info should be always
* sent to the provider in every phase (if true), or should be removed
* from the query phase, and only sent as part of the request in the final phase,
@@ -90,6 +110,7 @@ public final class GetCredentialRequest implements Parcelable {
dest.writeTypedList(mCredentialOptions, flags);
dest.writeBundle(mData);
dest.writeBoolean(mAlwaysSendAppInfoToProvider);
+ dest.writeString8(mOrigin);
}
@Override
@@ -103,11 +124,12 @@ public final class GetCredentialRequest implements Parcelable {
+ ", data=" + mData
+ ", alwaysSendAppInfoToProvider="
+ mAlwaysSendAppInfoToProvider
+ + ", origin=" + mOrigin
+ "}";
}
private GetCredentialRequest(@NonNull List<CredentialOption> credentialOptions,
- @NonNull Bundle data, @NonNull boolean alwaysSendAppInfoToProvider) {
+ @NonNull Bundle data, @NonNull boolean alwaysSendAppInfoToProvider, String origin) {
Preconditions.checkCollectionNotEmpty(
credentialOptions,
/*valueName=*/ "credentialOptions");
@@ -118,6 +140,7 @@ public final class GetCredentialRequest implements Parcelable {
mData = requireNonNull(data,
"data must not be null");
mAlwaysSendAppInfoToProvider = alwaysSendAppInfoToProvider;
+ mOrigin = origin;
}
private GetCredentialRequest(@NonNull Parcel in) {
@@ -126,12 +149,12 @@ public final class GetCredentialRequest implements Parcelable {
mCredentialOptions = credentialOptions;
AnnotationValidations.validate(NonNull.class, null, mCredentialOptions);
-
Bundle data = in.readBundle();
mData = data;
AnnotationValidations.validate(NonNull.class, null, mData);
mAlwaysSendAppInfoToProvider = in.readBoolean();
+ mOrigin = in.readString8();
}
@NonNull public static final Parcelable.Creator<GetCredentialRequest> CREATOR =
@@ -159,6 +182,8 @@ public final class GetCredentialRequest implements Parcelable {
@NonNull
private boolean mAlwaysSendAppInfoToProvider = true;
+ private String mOrigin;
+
/**
* @param data the top request level data
*/
@@ -209,6 +234,20 @@ public final class GetCredentialRequest implements Parcelable {
}
/**
+ * Sets the origin of the calling app. Callers of this special setter (e.g. browsers)
+ * can set this origin for an app different from their own, to be able to get
+ * credentials on behalf of that app. The permission check only happens later when this
+ * instance is passed and processed by the Credential Manager.
+ */
+ @SuppressLint({"MissingGetterMatchingBuilder", "AndroidFrameworkRequiresPermission"})
+ @RequiresPermission(CREDENTIAL_MANAGER_SET_ORIGIN)
+ @NonNull
+ public Builder setOrigin(@NonNull String origin) {
+ mOrigin = origin;
+ return this;
+ }
+
+ /**
* Builds a {@link GetCredentialRequest}.
*
* @throws IllegalArgumentException If credentialOptions is empty.
@@ -222,7 +261,7 @@ public final class GetCredentialRequest implements Parcelable {
mCredentialOptions,
/*valueName=*/ "credentialOptions");
return new GetCredentialRequest(mCredentialOptions, mData,
- mAlwaysSendAppInfoToProvider);
+ mAlwaysSendAppInfoToProvider, mOrigin);
}
}
}
diff --git a/core/java/android/credentials/ICredentialManager.aidl b/core/java/android/credentials/ICredentialManager.aidl
index 6d81d80d249c..625fc8ab5dad 100644
--- a/core/java/android/credentials/ICredentialManager.aidl
+++ b/core/java/android/credentials/ICredentialManager.aidl
@@ -41,12 +41,8 @@ interface ICredentialManager {
@nullable ICancellationSignal executeGetCredential(in GetCredentialRequest request, in IGetCredentialCallback callback, String callingPackage);
- @nullable ICancellationSignal executeGetCredentialWithOrigin(in GetCredentialRequest request, in IGetCredentialCallback callback, String callingPackage, String origin);
-
@nullable ICancellationSignal executeCreateCredential(in CreateCredentialRequest request, in ICreateCredentialCallback callback, String callingPackage);
- @nullable ICancellationSignal executeCreateCredentialWithOrigin(in CreateCredentialRequest request, in ICreateCredentialCallback callback, String callingPackage, String origin);
-
@nullable ICancellationSignal clearCredentialState(in ClearCredentialStateRequest request, in IClearCredentialStateCallback callback, String callingPackage);
@nullable ICancellationSignal listEnabledProviders(in IListEnabledProvidersCallback callback);
diff --git a/core/java/android/credentials/ui/CancelUiRequest.java b/core/java/android/credentials/ui/CancelUiRequest.java
new file mode 100644
index 000000000000..6bd9de481a79
--- /dev/null
+++ b/core/java/android/credentials/ui/CancelUiRequest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.credentials.ui;
+
+import android.annotation.NonNull;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.AnnotationValidations;
+
+/**
+ * A request to cancel any ongoing UI matching this request.
+ *
+ * @hide
+ */
+public final class CancelUiRequest implements Parcelable {
+
+ /**
+ * The intent extra key for the {@code CancelUiRequest} object when launching the UX
+ * activities.
+ */
+ @NonNull public static final String EXTRA_CANCEL_UI_REQUEST =
+ "android.credentials.ui.extra.EXTRA_CANCEL_UI_REQUEST";
+
+ @NonNull
+ private final IBinder mToken;
+
+ /** Returns the request token matching the user request that should be cancelled. */
+ @NonNull
+ public IBinder getToken() {
+ return mToken;
+ }
+
+ public CancelUiRequest(@NonNull IBinder token) {
+ mToken = token;
+ }
+
+ private CancelUiRequest(@NonNull Parcel in) {
+ mToken = in.readStrongBinder();
+ AnnotationValidations.validate(NonNull.class, null, mToken);
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeStrongBinder(mToken);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @NonNull public static final Creator<CancelUiRequest> CREATOR = new Creator<>() {
+ @Override
+ public CancelUiRequest createFromParcel(@NonNull Parcel in) {
+ return new CancelUiRequest(in);
+ }
+
+ @Override
+ public CancelUiRequest[] newArray(int size) {
+ return new CancelUiRequest[size];
+ }
+ };
+}
diff --git a/core/java/android/credentials/ui/IntentFactory.java b/core/java/android/credentials/ui/IntentFactory.java
index 67634dc0ad8c..dcfef56f86a4 100644
--- a/core/java/android/credentials/ui/IntentFactory.java
+++ b/core/java/android/credentials/ui/IntentFactory.java
@@ -22,6 +22,7 @@ import android.annotation.TestApi;
import android.content.ComponentName;
import android.content.Intent;
import android.content.res.Resources;
+import android.os.IBinder;
import android.os.Parcel;
import android.os.ResultReceiver;
@@ -66,6 +67,25 @@ public class IntentFactory {
}
/**
+ * Creates an Intent that cancels any UI matching the given request token id.
+ *
+ * @hide
+ */
+ @NonNull
+ public static Intent createCancelUiIntent(@NonNull IBinder requestToken) {
+ Intent intent = new Intent();
+ ComponentName componentName =
+ ComponentName.unflattenFromString(
+ Resources.getSystem()
+ .getString(
+ com.android.internal.R.string
+ .config_credentialManagerDialogComponent));
+ intent.setComponent(componentName);
+ intent.putExtra(CancelUiRequest.EXTRA_CANCEL_UI_REQUEST, new CancelUiRequest(requestToken));
+ return intent;
+ }
+
+ /**
* Notify the UI that providers have been enabled/disabled.
*
* @hide
@@ -78,7 +98,7 @@ public class IntentFactory {
Resources.getSystem()
.getString(
com.android.internal.R.string
- .config_credentialManagerDialogComponent));
+ .config_credentialManagerReceiverComponent));
intent.setComponent(componentName);
intent.setAction(Constants.CREDMAN_ENABLED_PROVIDERS_UPDATED);
return intent;
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index 9388ae3fd5e4..73157e62cb56 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -17,10 +17,10 @@
package android.hardware;
import static android.companion.virtual.VirtualDeviceManager.ACTION_VIRTUAL_DEVICE_REMOVED;
-import static android.companion.virtual.VirtualDeviceManager.DEVICE_ID_DEFAULT;
import static android.companion.virtual.VirtualDeviceManager.EXTRA_VIRTUAL_DEVICE_ID;
import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT;
import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_SENSORS;
+import static android.content.Context.DEVICE_ID_DEFAULT;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import android.companion.virtual.VirtualDeviceManager;
@@ -92,7 +92,8 @@ public class SystemSensorManager extends SensorManager {
private static native boolean nativeIsDataInjectionEnabled(long nativeInstance);
private static native int nativeCreateDirectChannel(
- long nativeInstance, long size, int channelType, int fd, HardwareBuffer buffer);
+ long nativeInstance, int deviceId, long size, int channelType, int fd,
+ HardwareBuffer buffer);
private static native void nativeDestroyDirectChannel(
long nativeInstance, int channelHandle);
private static native int nativeConfigDirectChannel(
@@ -695,6 +696,10 @@ public class SystemSensorManager extends SensorManager {
/** @hide */
protected SensorDirectChannel createDirectChannelImpl(
MemoryFile memoryFile, HardwareBuffer hardwareBuffer) {
+ int deviceId = mContext.getDeviceId();
+ if (isDeviceSensorPolicyDefault(deviceId)) {
+ deviceId = DEVICE_ID_DEFAULT;
+ }
int id;
int type;
long size;
@@ -713,8 +718,8 @@ public class SystemSensorManager extends SensorManager {
}
size = memoryFile.length();
- id = nativeCreateDirectChannel(
- mNativeInstance, size, SensorDirectChannel.TYPE_MEMORY_FILE, fd, null);
+ id = nativeCreateDirectChannel(mNativeInstance, deviceId, size,
+ SensorDirectChannel.TYPE_MEMORY_FILE, fd, null);
if (id <= 0) {
throw new UncheckedIOException(
new IOException("create MemoryFile direct channel failed " + id));
@@ -738,7 +743,7 @@ public class SystemSensorManager extends SensorManager {
}
size = hardwareBuffer.getWidth();
id = nativeCreateDirectChannel(
- mNativeInstance, size, SensorDirectChannel.TYPE_HARDWARE_BUFFER,
+ mNativeInstance, deviceId, size, SensorDirectChannel.TYPE_HARDWARE_BUFFER,
-1, hardwareBuffer);
if (id <= 0) {
throw new UncheckedIOException(
diff --git a/core/java/android/hardware/biometrics/AuthenticateOptions.java b/core/java/android/hardware/biometrics/AuthenticateOptions.java
new file mode 100644
index 000000000000..77660713275f
--- /dev/null
+++ b/core/java/android/hardware/biometrics/AuthenticateOptions.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.biometrics;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Common authentication options that are exposed across all modalities.
+ *
+ * @hide
+ */
+public interface AuthenticateOptions {
+
+ /** The user id for this operation. */
+ int getUserId();
+
+ /** The sensor id for this operation. */
+ int getSensorId();
+
+ /** The state is unknown. */
+ int DISPLAY_STATE_UNKNOWN = 0;
+
+ /** The display is on and showing the lockscreen (or an occluding app). */
+ int DISPLAY_STATE_LOCKSCREEN = 1;
+
+ /** The display is off or dozing. */
+ int DISPLAY_STATE_NO_UI = 2;
+
+ /** The display is showing a screensaver (dreaming). */
+ int DISPLAY_STATE_SCREENSAVER = 3;
+
+ /** The display is dreaming with always on display. */
+ int DISPLAY_STATE_AOD = 4;
+
+ /** The doze state of the device. */
+ @IntDef(prefix = "DISPLAY_STATE_", value = {
+ DISPLAY_STATE_UNKNOWN,
+ DISPLAY_STATE_LOCKSCREEN,
+ DISPLAY_STATE_NO_UI,
+ DISPLAY_STATE_SCREENSAVER,
+ DISPLAY_STATE_AOD
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface DisplayState {}
+
+ /** The current doze state of the device. */
+ @DisplayState
+ int getDisplayState();
+
+ /**
+ * The package name for that operation that should be used for
+ * {@link android.app.AppOpsManager} verification.
+ */
+ @NonNull String getOpPackageName();
+
+ /** The attribution tag, if any. */
+ @Nullable String getAttributionTag();
+}
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 8e6576ae8619..b9b310fcc542 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -3660,8 +3660,8 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
/**
* <p>An array of mandatory stream combinations which are applicable when device lists
* {@code PREVIEW_STABILIZATION} in {@link CameraCharacteristics#CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES android.control.availableVideoStabilizationModes}.
- * This is an app-readable conversion of the preview stabilization mandatory stream combination
- * {@link android.hardware.camera2.CameraDevice#createCaptureSession tables}.</p>
+ * This is an app-readable conversion of the preview stabilization mandatory stream
+ * combination {@link android.hardware.camera2.CameraDevice#createCaptureSession tables}.</p>
* <p>The array of
* {@link android.hardware.camera2.params.MandatoryStreamCombination combinations} is
* generated according to the documented
diff --git a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
index cca900a08d8d..1bf004a2aeb0 100644
--- a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java
@@ -541,7 +541,8 @@ public final class CameraExtensionCharacteristics {
private static <T> boolean isOutputSupportedFor(Class<T> klass) {
Objects.requireNonNull(klass, "klass must not be null");
- if (klass == android.graphics.SurfaceTexture.class) {
+ if ((klass == android.graphics.SurfaceTexture.class) ||
+ (klass == android.view.SurfaceView.class)) {
return true;
}
@@ -725,6 +726,12 @@ public final class CameraExtensionCharacteristics {
* backward compatible cameras whereas other output classes are not guaranteed to be supported.
* </p>
*
+ * <p>Starting with Android {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}
+ * {@link android.view.SurfaceView} classes are also guaranteed to be supported and include
+ * the same resolutions as {@link android.graphics.SurfaceTexture}.
+ * Clients must set the desired SurfaceView resolution by calling
+ * {@link android.view.SurfaceHolder#setFixedSize}.</p>
+ *
* @param extension the extension type
* @param klass a non-{@code null} {@link Class} object reference
* @return non-modifiable list of available sizes or an empty list if the Surface output is not
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 19719a88ab2e..fbc018444dc5 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -142,24 +142,18 @@ public final class CameraManager {
PackageManager.PERMISSION_GRANTED;
}
- mHandlerThread = new HandlerThread(TAG);
- mHandlerThread.start();
- mHandler = new Handler(mHandlerThread.getLooper());
mFoldStateListener = new FoldStateListener(context);
try {
- context.getSystemService(DeviceStateManager.class)
- .registerCallback(new HandlerExecutor(mHandler), mFoldStateListener);
+ context.getSystemService(DeviceStateManager.class).registerCallback(
+ new HandlerExecutor(CameraManagerGlobal.get().getDeviceStateHandler()),
+ mFoldStateListener);
} catch (IllegalStateException e) {
Log.v(TAG, "Failed to register device state listener!");
Log.v(TAG, "Device state dependent characteristics updates will not be functional!");
- mHandlerThread.quitSafely();
- mHandler = null;
mFoldStateListener = null;
}
}
- private HandlerThread mHandlerThread;
- private Handler mHandler;
private FoldStateListener mFoldStateListener;
/**
@@ -1645,6 +1639,9 @@ public final class CameraManager {
private ICameraService mCameraService;
private boolean mHasOpenCloseListenerPermission = false;
+ private HandlerThread mDeviceStateHandlerThread;
+ private Handler mDeviceStateHandler;
+
// Singleton, don't allow construction
private CameraManagerGlobal() { }
@@ -1658,6 +1655,18 @@ public final class CameraManager {
return gCameraManager;
}
+ public Handler getDeviceStateHandler() {
+ synchronized(mLock) {
+ if (mDeviceStateHandlerThread == null) {
+ mDeviceStateHandlerThread = new HandlerThread(TAG);
+ mDeviceStateHandlerThread.start();
+ mDeviceStateHandler = new Handler(mDeviceStateHandlerThread.getLooper());
+ }
+
+ return mDeviceStateHandler;
+ }
+ }
+
@Override
public IBinder asBinder() {
return this;
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 788302b37e75..705afc59f36f 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -1000,24 +1000,25 @@ public abstract class CameraMetadata<TKey> {
* camera's crop region is set to maximum size, the FOV of the physical streams for the
* ultrawide lens will be the same as the logical stream, by making the crop region
* smaller than its active array size to compensate for the smaller focal length.</p>
- * <p>There are two ways for the application to capture RAW images from a logical camera
- * with RAW capability:</p>
+ * <p>For a logical camera, typically the underlying physical cameras have different RAW
+ * capabilities (such as resolution or CFA pattern). There are two ways for the
+ * application to capture RAW images from the logical camera:</p>
* <ul>
- * <li>Because the underlying physical cameras may have different RAW capabilities (such
- * as resolution or CFA pattern), to maintain backward compatibility, when a RAW stream
- * is configured, the camera device makes sure the default active physical camera remains
- * active and does not switch to other physical cameras. (One exception is that, if the
- * logical camera consists of identical image sensors and advertises multiple focalLength
- * due to different lenses, the camera device may generate RAW images from different
- * physical cameras based on the focalLength being set by the application.) This
- * backward-compatible approach usually results in loss of optical zoom, to telephoto
- * lens or to ultrawide lens.</li>
- * <li>Alternatively, to take advantage of the full zoomRatio range of the logical camera,
- * the application should use {@link android.hardware.camera2.MultiResolutionImageReader }
- * to capture RAW images from the currently active physical camera. Because different
- * physical camera may have different RAW characteristics, the application needs to use
- * the characteristics and result metadata of the active physical camera for the
- * relevant RAW metadata.</li>
+ * <li>If the logical camera has RAW capability, the application can create and use RAW
+ * streams in the same way as before. In case a RAW stream is configured, to maintain
+ * backward compatibility, the camera device makes sure the default active physical
+ * camera remains active and does not switch to other physical cameras. (One exception
+ * is that, if the logical camera consists of identical image sensors and advertises
+ * multiple focalLength due to different lenses, the camera device may generate RAW
+ * images from different physical cameras based on the focalLength being set by the
+ * application.) This backward-compatible approach usually results in loss of optical
+ * zoom, to telephoto lens or to ultrawide lens.</li>
+ * <li>Alternatively, if supported by the device,
+ * {@link android.hardware.camera2.MultiResolutionImageReader }
+ * can be used to capture RAW images from one of the underlying physical cameras (
+ * depending on current zoom level). Because different physical cameras may have
+ * different RAW characteristics, the application needs to use the characteristics
+ * and result metadata of the active physical camera for the relevant RAW metadata.</li>
* </ul>
* <p>The capture request and result metadata tags required for backward compatible camera
* functionalities will be solely based on the logical camera capability. On the other
diff --git a/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java
index 41c406dc1641..db83e6218daf 100644
--- a/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraAdvancedExtensionSessionImpl.java
@@ -62,8 +62,6 @@ import android.os.Handler;
import android.os.HandlerThread;
import android.os.RemoteException;
import android.util.Log;
-import android.util.Pair;
-import android.util.Range;
import android.util.Size;
import android.view.Surface;
@@ -270,6 +268,10 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
}
}
+ // The extension processing logic needs to be able to match images to capture results via
+ // image and result timestamps.
+ cameraOutput.setTimestampBase(OutputConfiguration.TIMESTAMP_BASE_SENSOR);
+ cameraOutput.setReadoutTimestampEnabled(false);
cameraOutput.setPhysicalCameraId(output.physicalCameraId);
outputList.add(cameraOutput);
mCameraConfigMap.put(cameraOutput.getSurface(), output);
diff --git a/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java
index 3f85d44b3b53..c2b36560919b 100644
--- a/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraExtensionSessionImpl.java
@@ -60,7 +60,6 @@ import android.os.RemoteException;
import android.util.Log;
import android.util.LongSparseArray;
import android.util.Pair;
-import android.util.Range;
import android.util.Size;
import android.view.Surface;
@@ -478,13 +477,21 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
ArrayList<CaptureStageImpl> sessionParamsList = new ArrayList<>();
ArrayList<OutputConfiguration> outputList = new ArrayList<>();
initializeRepeatingRequestPipeline();
- outputList.add(new OutputConfiguration(mCameraRepeatingSurface));
+ OutputConfiguration previewOutput = new OutputConfiguration(mCameraRepeatingSurface);
+ // The extension processing logic needs to be able to match images to capture results via
+ // image and result timestamps.
+ previewOutput.setTimestampBase(OutputConfiguration.TIMESTAMP_BASE_SENSOR);
+ previewOutput.setReadoutTimestampEnabled(false);
+ outputList.add(previewOutput);
CaptureStageImpl previewSessionParams = mPreviewExtender.onPresetSession();
if (previewSessionParams != null) {
sessionParamsList.add(previewSessionParams);
}
initializeBurstCapturePipeline();
- outputList.add(new OutputConfiguration(mCameraBurstSurface));
+ OutputConfiguration captureOutput = new OutputConfiguration(mCameraBurstSurface);
+ captureOutput.setTimestampBase(OutputConfiguration.TIMESTAMP_BASE_SENSOR);
+ captureOutput.setReadoutTimestampEnabled(false);
+ outputList.add(captureOutput);
CaptureStageImpl stillCaptureSessionParams = mImageExtender.onPresetSession();
if (stillCaptureSessionParams != null) {
sessionParamsList.add(stillCaptureSessionParams);
diff --git a/core/java/android/hardware/camera2/impl/CameraExtensionUtils.java b/core/java/android/hardware/camera2/impl/CameraExtensionUtils.java
index 52224084bc0a..08111c5f3874 100644
--- a/core/java/android/hardware/camera2/impl/CameraExtensionUtils.java
+++ b/core/java/android/hardware/camera2/impl/CameraExtensionUtils.java
@@ -20,6 +20,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.ImageFormat;
import android.graphics.PixelFormat;
+import android.hardware.HardwareBuffer;
import android.hardware.camera2.CameraExtensionCharacteristics;
import android.hardware.camera2.params.OutputConfiguration;
import android.hardware.camera2.params.StreamConfigurationMap;
@@ -149,6 +150,7 @@ public final class CameraExtensionUtils {
SurfaceInfo surfaceInfo = querySurface(config.getSurface());
if ((surfaceInfo.mFormat ==
CameraExtensionCharacteristics.NON_PROCESSING_INPUT_FORMAT) ||
+ ((surfaceInfo.mUsage & HardwareBuffer.USAGE_COMPOSER_OVERLAY) != 0) ||
// The default RGBA_8888 is also implicitly supported because camera will
// internally override it to
// 'CameraExtensionCharacteristics.NON_PROCESSING_INPUT_FORMAT'
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index eeff6ccafd5d..50dd7a0bc1be 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -68,6 +68,15 @@ public final class DisplayManager {
private static final boolean DEBUG = false;
private static final boolean ENABLE_VIRTUAL_DISPLAY_REFRESH_RATE = true;
+ /**
+ * The hdr output control feature flag, the value should be read via
+ * {@link android.provider.DeviceConfig#getBoolean(String, String, boolean)} with
+ * {@link android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER} as the namespace.
+ * @hide
+ */
+ @TestApi
+ public static final String HDR_OUTPUT_CONTROL_FLAG = "enable_hdr_output_control";
+
private final Context mContext;
private final DisplayManagerGlobal mGlobal;
@@ -980,24 +989,6 @@ public final class DisplayManager {
/**
* Creates a virtual display.
- *
- * @see #createVirtualDisplay(String, int, int, int, float, Surface, int,
- * Handler, VirtualDisplay.Callback)
- */
- @Nullable
- public VirtualDisplay createVirtualDisplay(@NonNull String name,
- @IntRange(from = 1) int width,
- @IntRange(from = 1) int height,
- @IntRange(from = 1) int densityDpi,
- float requestedRefreshRate,
- @Nullable Surface surface,
- @VirtualDisplayFlag int flags) {
- return createVirtualDisplay(name, width, height, densityDpi, requestedRefreshRate,
- surface, flags, null, null);
- }
-
- /**
- * Creates a virtual display.
* <p>
* The content of a virtual display is rendered to a {@link Surface} provided
* by the application.
@@ -1047,8 +1038,23 @@ public final class DisplayManager {
@VirtualDisplayFlag int flags,
@Nullable VirtualDisplay.Callback callback,
@Nullable Handler handler) {
- return createVirtualDisplay(name, width, height, densityDpi, 0.0f, surface,
- flags, handler, callback);
+ final VirtualDisplayConfig.Builder builder =
+ new VirtualDisplayConfig.Builder(name, width, height, densityDpi);
+ builder.setFlags(flags);
+ if (surface != null) {
+ builder.setSurface(surface);
+ }
+ return createVirtualDisplay(builder.build(), handler, callback);
+ }
+
+ /**
+ * Creates a virtual display.
+ *
+ * @see #createVirtualDisplay(VirtualDisplayConfig, Handler, VirtualDisplay.Callback)
+ */
+ @Nullable
+ public VirtualDisplay createVirtualDisplay(@NonNull VirtualDisplayConfig config) {
+ return createVirtualDisplay(config, /*handler=*/null, /*callback=*/null);
}
/**
@@ -1075,21 +1081,7 @@ public final class DisplayManager {
* turning off the screen.
* </p>
*
- * @param name The name of the virtual display, must be non-empty.
- * @param width The width of the virtual display in pixels, must be greater than 0.
- * @param height The height of the virtual display in pixels, must be greater than 0.
- * @param densityDpi The density of the virtual display in dpi, must be greater than 0.
- * @param requestedRefreshRate The requested refresh rate in frames per second.
- * For best results, specify a divisor of the physical refresh rate, e.g., 30 or 60 on
- * 120hz display. If an arbitrary refresh rate is specified, the rate will be rounded
- * up or down to a divisor of the physical display. If 0 is specified, the virtual
- * display is refreshed at the physical display refresh rate.
- * @param surface The surface to which the content of the virtual display should
- * be rendered, or null if there is none initially.
- * @param flags A combination of virtual display flags:
- * {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC}, {@link #VIRTUAL_DISPLAY_FLAG_PRESENTATION},
- * {@link #VIRTUAL_DISPLAY_FLAG_SECURE}, {@link #VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY},
- * or {@link #VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR}.
+ * @param config The configuration of the virtual display, must be non-null.
* @param handler The handler on which the listener should be invoked, or null
* if the listener should be invoked on the calling thread's looper.
* @param callback Callback to call when the state of the {@link VirtualDisplay} changes
@@ -1097,33 +1089,14 @@ public final class DisplayManager {
* not create the virtual display.
*
* @throws SecurityException if the caller does not have permission to create
- * a virtual display with the specified flags.
+ * a virtual display with flags specified in the configuration.
*/
@Nullable
- public VirtualDisplay createVirtualDisplay(@NonNull String name,
- @IntRange(from = 1) int width,
- @IntRange(from = 1) int height,
- @IntRange(from = 1) int densityDpi,
- float requestedRefreshRate,
- @Nullable Surface surface,
- @VirtualDisplayFlag int flags,
+ public VirtualDisplay createVirtualDisplay(
+ @NonNull VirtualDisplayConfig config,
@Nullable Handler handler,
@Nullable VirtualDisplay.Callback callback) {
- if (!ENABLE_VIRTUAL_DISPLAY_REFRESH_RATE && requestedRefreshRate != 0.0f) {
- Slog.e(TAG, "Please turn on ENABLE_VIRTUAL_DISPLAY_REFRESH_RATE to use the new api");
- return null;
- }
-
- final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(name, width,
- height, densityDpi);
- builder.setFlags(flags);
- if (surface != null) {
- builder.setSurface(surface);
- }
- if (requestedRefreshRate != 0.0f) {
- builder.setRequestedRefreshRate(requestedRefreshRate);
- }
- return createVirtualDisplay(null /* projection */, builder.build(), callback, handler,
+ return createVirtualDisplay(null /* projection */, config, callback, handler,
null /* windowContext */);
}
diff --git a/core/java/android/hardware/display/VirtualDisplayConfig.java b/core/java/android/hardware/display/VirtualDisplayConfig.java
index f6a2e33c7164..6b56a067a198 100644
--- a/core/java/android/hardware/display/VirtualDisplayConfig.java
+++ b/core/java/android/hardware/display/VirtualDisplayConfig.java
@@ -18,121 +18,44 @@ package android.hardware.display;
import static android.view.Display.DEFAULT_DISPLAY;
+import android.annotation.FloatRange;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.hardware.display.DisplayManager.VirtualDisplayFlag;
import android.media.projection.MediaProjection;
+import android.os.Handler;
import android.os.Parcel;
import android.os.Parcelable;
+import android.view.Display;
import android.view.Surface;
-import com.android.internal.util.DataClass;
-
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
+import java.util.Objects;
/**
- * Holds configuration used to create {@link VirtualDisplay} instances. See
- * {@link MediaProjection#createVirtualDisplay} and
- * {@link android.companion.virtual.VirtualDeviceManager.VirtualDevice#createVirtualDisplay}.
+ * Holds configuration used to create {@link VirtualDisplay} instances.
*
- * @hide
+ * @see DisplayManager#createVirtualDisplay(VirtualDisplayConfig, Handler, VirtualDisplay.Callback)
+ * @see MediaProjection#createVirtualDisplay
*/
-@DataClass(genParcelable = true, genAidl = true, genBuilder = true)
public final class VirtualDisplayConfig implements Parcelable {
- /**
- * The name of the virtual display, must be non-empty.
- */
- @NonNull
- private String mName;
-
- /**
- * The width of the virtual display in pixels. Must be greater than 0.
- */
- @IntRange(from = 1)
- private int mWidth;
-
- /**
- * The height of the virtual display in pixels. Must be greater than 0.
- */
- @IntRange(from = 1)
- private int mHeight;
-
- /**
- * The density of the virtual display in dpi. Must be greater than 0.
- */
- @IntRange(from = 1)
- private int mDensityDpi;
-
- /**
- * A combination of virtual display flags.
- * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PUBLIC},
- * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PRESENTATION},
- * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_SECURE},
- * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY},
- * or {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR}.
- */
- @VirtualDisplayFlag
- private int mFlags = 0;
-
- /**
- * The surface to which the content of the virtual display should be rendered, or null if
- * there is none initially.
- */
- @Nullable
- private Surface mSurface = null;
-
- /**
- * The unique identifier for the display. Shouldn't be displayed to the user.
- * @hide
- */
- @Nullable
- private String mUniqueId = null;
-
- /**
- * The id of the display that the virtual display should mirror, or
- * {@link android.view.Display#DEFAULT_DISPLAY} if there is none initially.
- */
- private int mDisplayIdToMirror = DEFAULT_DISPLAY;
-
- /**
- * Indicates if WindowManager is responsible for mirroring content to this VirtualDisplay, or
- * if DisplayManager should record contents instead.
- */
- private boolean mWindowManagerMirroring = false;
-
- /**
- * The display categories. If set, only corresponding activities from the same category can be
- * shown on the display.
- */
- @DataClass.PluralOf("displayCategory")
- @NonNull private List<String> mDisplayCategories = new ArrayList<>();
-
- /**
- * The refresh rate of a virtual display in frames per second.
- * If this value is non-zero, this is the requested refresh rate to set.
- * If this value is zero, the system chooses a default refresh rate.
- */
- private float mRequestedRefreshRate = 0.0f;
-
-
- // Code below generated by codegen v1.0.23.
- //
- // DO NOT MODIFY!
- // CHECKSTYLE:OFF Generated code
- //
- // To regenerate run:
- // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/hardware/display/VirtualDisplayConfig.java
- //
- // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
- // Settings > Editor > Code Style > Formatter Control
- //@formatter:off
-
-
- @DataClass.Generated.Member
- /* package-private */ VirtualDisplayConfig(
+ private final String mName;
+ private final int mWidth;
+ private final int mHeight;
+ private final int mDensityDpi;
+ private final int mFlags;
+ private final Surface mSurface;
+ private final String mUniqueId;
+ private final int mDisplayIdToMirror;
+ private final boolean mWindowManagerMirroring;
+ private ArrayList<String> mDisplayCategories = null;
+ private final float mRequestedRefreshRate;
+
+ private VirtualDisplayConfig(
@NonNull String name,
@IntRange(from = 1) int width,
@IntRange(from = 1) int height,
@@ -142,219 +65,200 @@ public final class VirtualDisplayConfig implements Parcelable {
@Nullable String uniqueId,
int displayIdToMirror,
boolean windowManagerMirroring,
- @NonNull List<String> displayCategories,
+ @NonNull ArrayList<String> displayCategories,
float requestedRefreshRate) {
- this.mName = name;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mName);
- this.mWidth = width;
- com.android.internal.util.AnnotationValidations.validate(
- IntRange.class, null, mWidth,
- "from", 1);
- this.mHeight = height;
- com.android.internal.util.AnnotationValidations.validate(
- IntRange.class, null, mHeight,
- "from", 1);
- this.mDensityDpi = densityDpi;
- com.android.internal.util.AnnotationValidations.validate(
- IntRange.class, null, mDensityDpi,
- "from", 1);
- this.mFlags = flags;
- com.android.internal.util.AnnotationValidations.validate(
- VirtualDisplayFlag.class, null, mFlags);
- this.mSurface = surface;
- this.mUniqueId = uniqueId;
- this.mDisplayIdToMirror = displayIdToMirror;
- this.mWindowManagerMirroring = windowManagerMirroring;
- this.mDisplayCategories = displayCategories;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mDisplayCategories);
- this.mRequestedRefreshRate = requestedRefreshRate;
-
- // onConstructed(); // You can define this method to get a callback
+ mName = name;
+ mWidth = width;
+ mHeight = height;
+ mDensityDpi = densityDpi;
+ mFlags = flags;
+ mSurface = surface;
+ mUniqueId = uniqueId;
+ mDisplayIdToMirror = displayIdToMirror;
+ mWindowManagerMirroring = windowManagerMirroring;
+ mDisplayCategories = displayCategories;
+ mRequestedRefreshRate = requestedRefreshRate;
}
/**
- * The name of the virtual display, must be non-empty.
+ * Returns the name of the virtual display.
*/
- @DataClass.Generated.Member
- public @NonNull String getName() {
+ @NonNull
+ public String getName() {
return mName;
}
/**
- * The width of the virtual display in pixels. Must be greater than 0.
+ * Returns the width of the virtual display in pixels.
*/
- @DataClass.Generated.Member
- public @IntRange(from = 1) int getWidth() {
+ public int getWidth() {
return mWidth;
}
/**
- * The height of the virtual display in pixels. Must be greater than 0.
+ * Returns the height of the virtual display in pixels.
*/
- @DataClass.Generated.Member
- public @IntRange(from = 1) int getHeight() {
+ public int getHeight() {
return mHeight;
}
/**
- * The density of the virtual display in dpi. Must be greater than 0.
+ * Returns the density of the virtual display in dpi.
*/
- @DataClass.Generated.Member
- public @IntRange(from = 1) int getDensityDpi() {
+ public int getDensityDpi() {
return mDensityDpi;
}
/**
- * A combination of virtual display flags.
- * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PUBLIC},
- * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PRESENTATION},
- * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_SECURE},
- * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY},
- * or {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR}.
+ * Returns the virtual display flags.
+ *
+ * @see Builder#setFlags
*/
- @DataClass.Generated.Member
- public @VirtualDisplayFlag int getFlags() {
+ public int getFlags() {
return mFlags;
}
/**
- * The surface to which the content of the virtual display should be rendered, or null if
- * there is none initially.
+ * Returns the surface to which the content of the virtual display should be rendered, if any.
+ *
+ * @see Builder#setSurface
*/
- @DataClass.Generated.Member
- public @Nullable Surface getSurface() {
+ @Nullable
+ public Surface getSurface() {
return mSurface;
}
/**
- * The unique identifier for the display. Shouldn't be displayed to the user.
- *
+ * Returns the unique identifier for the display. Shouldn't be displayed to the user.
* @hide
*/
- @DataClass.Generated.Member
- public @Nullable String getUniqueId() {
+ @Nullable
+ public String getUniqueId() {
return mUniqueId;
}
/**
- * The id of the display that the virtual display should mirror, or
- * {@link android.view.Display#DEFAULT_DISPLAY} if there is none initially.
+ * Returns the id of the display that the virtual display should mirror, or
+ * {@link android.view.Display#DEFAULT_DISPLAY} if there is none.
+ * @hide
*/
- @DataClass.Generated.Member
public int getDisplayIdToMirror() {
return mDisplayIdToMirror;
}
/**
- * Indicates if WindowManager is responsible for mirroring content to this VirtualDisplay, or
+ * Whether if WindowManager is responsible for mirroring content to this VirtualDisplay, or
* if DisplayManager should record contents instead.
+ * @hide
*/
- @DataClass.Generated.Member
public boolean isWindowManagerMirroring() {
return mWindowManagerMirroring;
}
/**
- * The display categories. If set, only corresponding activities from the same category can be
- * shown on the display.
+ * Returns the display categories.
+ *
+ * @see Builder#setDisplayCategories
*/
- @DataClass.Generated.Member
- public @NonNull List<String> getDisplayCategories() {
- return mDisplayCategories;
+ @NonNull
+ public List<String> getDisplayCategories() {
+ return Collections.unmodifiableList(mDisplayCategories);
}
/**
- * The refresh rate of a virtual display in frames per second.
- * If this value is none zero, this is the requested refresh rate to set.
- * If this value is zero, the system chooses a default refresh rate.
+ * Returns the refresh rate of a virtual display in frames per second, or zero if it is using a
+ * default refresh rate chosen by the system.
+ *
+ * @see Builder#setRequestedRefreshRate
*/
- @DataClass.Generated.Member
public float getRequestedRefreshRate() {
return mRequestedRefreshRate;
}
@Override
- @DataClass.Generated.Member
public void writeToParcel(@NonNull Parcel dest, int flags) {
- // You can override field parcelling by defining methods like:
- // void parcelFieldName(Parcel dest, int flags) { ... }
-
- int flg = 0;
- if (mWindowManagerMirroring) flg |= 0x100;
- if (mSurface != null) flg |= 0x20;
- if (mUniqueId != null) flg |= 0x40;
- dest.writeInt(flg);
- dest.writeString(mName);
+ dest.writeString8(mName);
dest.writeInt(mWidth);
dest.writeInt(mHeight);
dest.writeInt(mDensityDpi);
dest.writeInt(mFlags);
- if (mSurface != null) dest.writeTypedObject(mSurface, flags);
- if (mUniqueId != null) dest.writeString(mUniqueId);
+ dest.writeTypedObject(mSurface, flags);
+ dest.writeString8(mUniqueId);
dest.writeInt(mDisplayIdToMirror);
+ dest.writeBoolean(mWindowManagerMirroring);
dest.writeStringList(mDisplayCategories);
dest.writeFloat(mRequestedRefreshRate);
}
@Override
- @DataClass.Generated.Member
public int describeContents() { return 0; }
- /** @hide */
- @SuppressWarnings({"unchecked", "RedundantCast"})
- @DataClass.Generated.Member
- /* package-private */ VirtualDisplayConfig(@NonNull Parcel in) {
- // You can override field unparcelling by defining methods like:
- // static FieldType unparcelFieldName(Parcel in) { ... }
-
- int flg = in.readInt();
- boolean windowManagerMirroring = (flg & 0x100) != 0;
- String name = in.readString();
- int width = in.readInt();
- int height = in.readInt();
- int densityDpi = in.readInt();
- int flags = in.readInt();
- Surface surface = (flg & 0x20) == 0 ? null : (Surface) in.readTypedObject(Surface.CREATOR);
- String uniqueId = (flg & 0x40) == 0 ? null : in.readString();
- int displayIdToMirror = in.readInt();
- List<String> displayCategories = new ArrayList<>();
- in.readStringList(displayCategories);
- float requestedRefreshRate = in.readFloat();
-
- this.mName = name;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mName);
- this.mWidth = width;
- com.android.internal.util.AnnotationValidations.validate(
- IntRange.class, null, mWidth,
- "from", 1);
- this.mHeight = height;
- com.android.internal.util.AnnotationValidations.validate(
- IntRange.class, null, mHeight,
- "from", 1);
- this.mDensityDpi = densityDpi;
- com.android.internal.util.AnnotationValidations.validate(
- IntRange.class, null, mDensityDpi,
- "from", 1);
- this.mFlags = flags;
- com.android.internal.util.AnnotationValidations.validate(
- VirtualDisplayFlag.class, null, mFlags);
- this.mSurface = surface;
- this.mUniqueId = uniqueId;
- this.mDisplayIdToMirror = displayIdToMirror;
- this.mWindowManagerMirroring = windowManagerMirroring;
- this.mDisplayCategories = displayCategories;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mDisplayCategories);
- this.mRequestedRefreshRate = requestedRefreshRate;
-
- // onConstructed(); // You can define this method to get a callback
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof VirtualDisplayConfig)) {
+ return false;
+ }
+ VirtualDisplayConfig that = (VirtualDisplayConfig) o;
+ return Objects.equals(mName, that.mName)
+ && mWidth == that.mWidth
+ && mHeight == that.mHeight
+ && mDensityDpi == that.mDensityDpi
+ && mFlags == that.mFlags
+ && Objects.equals(mSurface, that.mSurface)
+ && Objects.equals(mUniqueId, that.mUniqueId)
+ && mDisplayIdToMirror == that.mDisplayIdToMirror
+ && mWindowManagerMirroring == that.mWindowManagerMirroring
+ && Objects.equals(mDisplayCategories, that.mDisplayCategories)
+ && mRequestedRefreshRate == that.mRequestedRefreshRate;
+ }
+
+ @Override
+ public int hashCode() {
+ int hashCode = Objects.hash(
+ mName, mWidth, mHeight, mDensityDpi, mFlags, mSurface, mUniqueId,
+ mDisplayIdToMirror, mWindowManagerMirroring, mDisplayCategories,
+ mRequestedRefreshRate);
+ return hashCode;
+ }
+
+ @Override
+ @NonNull
+ public String toString() {
+ return "VirtualDisplayConfig("
+ + " mName=" + mName
+ + " mHeight=" + mHeight
+ + " mWidth=" + mWidth
+ + " mDensityDpi=" + mDensityDpi
+ + " mFlags=" + mFlags
+ + " mSurface=" + mSurface
+ + " mUniqueId=" + mUniqueId
+ + " mDisplayIdToMirror=" + mDisplayIdToMirror
+ + " mWindowManagerMirroring=" + mWindowManagerMirroring
+ + " mDisplayCategories=" + mDisplayCategories
+ + " mRequestedRefreshRate=" + mRequestedRefreshRate
+ + ")";
+ }
+
+ private VirtualDisplayConfig(@NonNull Parcel in) {
+ mName = in.readString8();
+ mWidth = in.readInt();
+ mHeight = in.readInt();
+ mDensityDpi = in.readInt();
+ mFlags = in.readInt();
+ mSurface = in.readTypedObject(Surface.CREATOR);
+ mUniqueId = in.readString8();
+ mDisplayIdToMirror = in.readInt();
+ mWindowManagerMirroring = in.readBoolean();
+ mDisplayCategories = new ArrayList<>();
+ in.readStringList(mDisplayCategories);
+ mRequestedRefreshRate = in.readFloat();
}
- @DataClass.Generated.Member
- public static final @NonNull Parcelable.Creator<VirtualDisplayConfig> CREATOR
+ @NonNull
+ public static final Parcelable.Creator<VirtualDisplayConfig> CREATOR
= new Parcelable.Creator<VirtualDisplayConfig>() {
@Override
public VirtualDisplayConfig[] newArray(int size) {
@@ -368,229 +272,161 @@ public final class VirtualDisplayConfig implements Parcelable {
};
/**
- * A builder for {@link VirtualDisplayConfig}
+ * A builder for {@link VirtualDisplayConfig}.
*/
- @SuppressWarnings("WeakerAccess")
- @DataClass.Generated.Member
public static final class Builder {
-
- private @NonNull String mName;
- private @IntRange(from = 1) int mWidth;
- private @IntRange(from = 1) int mHeight;
- private @IntRange(from = 1) int mDensityDpi;
- private @VirtualDisplayFlag int mFlags;
- private @Nullable Surface mSurface;
- private @Nullable String mUniqueId;
- private int mDisplayIdToMirror;
- private boolean mWindowManagerMirroring;
- private @NonNull List<String> mDisplayCategories;
- private float mRequestedRefreshRate;
-
- private long mBuilderFieldsSet = 0L;
+ private final String mName;
+ private final int mWidth;
+ private final int mHeight;
+ private final int mDensityDpi;
+ private int mFlags = 0;
+ private Surface mSurface = null;
+ private String mUniqueId = null;
+ private int mDisplayIdToMirror = DEFAULT_DISPLAY;
+ private boolean mWindowManagerMirroring = false;
+ private ArrayList<String> mDisplayCategories = new ArrayList<>();
+ private float mRequestedRefreshRate = 0.0f;
/**
* Creates a new Builder.
*
- * @param name
- * The name of the virtual display, must be non-empty.
- * @param width
- * The width of the virtual display in pixels. Must be greater than 0.
- * @param height
- * The height of the virtual display in pixels. Must be greater than 0.
- * @param densityDpi
- * The density of the virtual display in dpi. Must be greater than 0.
+ * @param name The name of the virtual display, must be non-empty.
+ * @param width The width of the virtual display in pixels. Must be greater than 0.
+ * @param height The height of the virtual display in pixels. Must be greater than 0.
+ * @param densityDpi The density of the virtual display in dpi. Must be greater than 0.
*/
public Builder(
@NonNull String name,
@IntRange(from = 1) int width,
@IntRange(from = 1) int height,
@IntRange(from = 1) int densityDpi) {
+ if (name == null) {
+ throw new IllegalArgumentException("Virtual display name is required");
+ }
+ if (width <= 0) {
+ throw new IllegalArgumentException("Virtual display width must be positive");
+ }
+ if (height <= 0) {
+ throw new IllegalArgumentException("Virtual display height must be positive");
+ }
+ if (densityDpi <= 0) {
+ throw new IllegalArgumentException("Virtual display density must be positive");
+ }
mName = name;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mName);
mWidth = width;
- com.android.internal.util.AnnotationValidations.validate(
- IntRange.class, null, mWidth,
- "from", 1);
mHeight = height;
- com.android.internal.util.AnnotationValidations.validate(
- IntRange.class, null, mHeight,
- "from", 1);
mDensityDpi = densityDpi;
- com.android.internal.util.AnnotationValidations.validate(
- IntRange.class, null, mDensityDpi,
- "from", 1);
- }
-
- /**
- * The name of the virtual display, must be non-empty.
- */
- @DataClass.Generated.Member
- public @NonNull Builder setName(@NonNull String value) {
- checkNotUsed();
- mBuilderFieldsSet |= 0x1;
- mName = value;
- return this;
- }
-
- /**
- * The width of the virtual display in pixels. Must be greater than 0.
- */
- @DataClass.Generated.Member
- public @NonNull Builder setWidth(@IntRange(from = 1) int value) {
- checkNotUsed();
- mBuilderFieldsSet |= 0x2;
- mWidth = value;
- return this;
- }
-
- /**
- * The height of the virtual display in pixels. Must be greater than 0.
- */
- @DataClass.Generated.Member
- public @NonNull Builder setHeight(@IntRange(from = 1) int value) {
- checkNotUsed();
- mBuilderFieldsSet |= 0x4;
- mHeight = value;
- return this;
- }
-
- /**
- * The density of the virtual display in dpi. Must be greater than 0.
- */
- @DataClass.Generated.Member
- public @NonNull Builder setDensityDpi(@IntRange(from = 1) int value) {
- checkNotUsed();
- mBuilderFieldsSet |= 0x8;
- mDensityDpi = value;
- return this;
}
/**
- * A combination of virtual display flags.
+ * Sets the virtual display flags, a combination of
* {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PUBLIC},
* {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PRESENTATION},
* {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_SECURE},
* {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY},
* or {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR}.
*/
- @DataClass.Generated.Member
- public @NonNull Builder setFlags(@VirtualDisplayFlag int value) {
- checkNotUsed();
- mBuilderFieldsSet |= 0x10;
- mFlags = value;
+ @NonNull
+ public Builder setFlags(@VirtualDisplayFlag int flags) {
+ mFlags = flags;
return this;
}
/**
- * The surface to which the content of the virtual display should be rendered, or null if
- * there is none initially.
+ * Sets the surface to which the content of the virtual display should be rendered.
+ *
+ * <p>The surface can also be set after the display creation using
+ * {@link VirtualDisplay#setSurface(Surface)}.
*/
- @DataClass.Generated.Member
- public @NonNull Builder setSurface(@NonNull Surface value) {
- checkNotUsed();
- mBuilderFieldsSet |= 0x20;
- mSurface = value;
+ @NonNull
+ public Builder setSurface(@Nullable Surface surface) {
+ mSurface = surface;
return this;
}
/**
- * The unique identifier for the display. Shouldn't be displayed to the user.
- *
+ * Sets the unique identifier for the display.
* @hide
*/
- @DataClass.Generated.Member
- public @NonNull Builder setUniqueId(@NonNull String value) {
- checkNotUsed();
- mBuilderFieldsSet |= 0x40;
- mUniqueId = value;
+ @NonNull
+ public Builder setUniqueId(@Nullable String uniqueId) {
+ mUniqueId = uniqueId;
return this;
}
/**
- * The id of the display that the virtual display should mirror, or
- * {@link android.view.Display#DEFAULT_DISPLAY} if there is none initially.
+ * Sets the id of the display that the virtual display should mirror.
+ * @hide
*/
- @DataClass.Generated.Member
- public @NonNull Builder setDisplayIdToMirror(int value) {
- checkNotUsed();
- mBuilderFieldsSet |= 0x80;
- mDisplayIdToMirror = value;
+ @NonNull
+ public Builder setDisplayIdToMirror(int displayIdToMirror) {
+ mDisplayIdToMirror = displayIdToMirror;
return this;
}
/**
- * Indicates if WindowManager is responsible for mirroring content to this VirtualDisplay, or
- * if DisplayManager should record contents instead.
+ * Sets whether WindowManager is responsible for mirroring content to this VirtualDisplay.
+ * If unset or false, DisplayManager should record contents instead.
+ * @hide
*/
- @DataClass.Generated.Member
- public @NonNull Builder setWindowManagerMirroring(boolean value) {
- checkNotUsed();
- mBuilderFieldsSet |= 0x100;
- mWindowManagerMirroring = value;
+ @NonNull
+ public Builder setWindowManagerMirroring(boolean windowManagerMirroring) {
+ mWindowManagerMirroring = windowManagerMirroring;
return this;
}
/**
- * The display categories. If set, only corresponding activities from the same category can be
- * shown on the display.
+ * Sets the display categories.
+ *
+ * <p>The categories of the display indicate the type of activities allowed to run on that
+ * display. Activities can declare a display category using
+ * {@link android.content.pm.ActivityInfo#requiredDisplayCategory}.
*/
- @DataClass.Generated.Member
- public @NonNull Builder setDisplayCategories(@NonNull List<String> value) {
- checkNotUsed();
- mBuilderFieldsSet |= 0x200;
- mDisplayCategories = value;
+ @NonNull
+ public Builder setDisplayCategories(@NonNull List<String> displayCategories) {
+ mDisplayCategories.clear();
+ mDisplayCategories.addAll(Objects.requireNonNull(displayCategories));
return this;
}
- /** @see #setDisplayCategories */
- @DataClass.Generated.Member
- public @NonNull Builder addDisplayCategory(@NonNull String value) {
- if (mDisplayCategories == null) setDisplayCategories(new ArrayList<>());
- mDisplayCategories.add(value);
+ /**
+ * Adds a display category.
+ *
+ * @see #setDisplayCategories
+ */
+ @NonNull
+ public Builder addDisplayCategory(@NonNull String displayCategory) {
+ mDisplayCategories.add(Objects.requireNonNull(displayCategory));
return this;
}
/**
- * The refresh rate of a virtual display in frames per second.
- * If this value is none zero, this is the requested refresh rate to set.
- * If this value is zero, the system chooses a default refresh rate.
+ * Sets the refresh rate of a virtual display in frames per second.
+ *
+ * <p>For best results, specify a divisor of the physical refresh rate, e.g., 30 or 60 on
+ * a 120hz display. If an arbitrary refresh rate is specified, the rate will be rounded up
+ * down to a divisor of the physical display. If unset or zero, the virtual display will be
+ * refreshed at the physical display refresh rate.
+ *
+ * @see Display#getRefreshRate()
*/
- @DataClass.Generated.Member
- public @NonNull Builder setRequestedRefreshRate(float value) {
- checkNotUsed();
- mBuilderFieldsSet |= 0x400;
- mRequestedRefreshRate = value;
+ @NonNull
+ public Builder setRequestedRefreshRate(
+ @FloatRange(from = 0.0f) float requestedRefreshRate) {
+ if (requestedRefreshRate < 0.0f) {
+ throw new IllegalArgumentException(
+ "Virtual display requested refresh rate must be non-negative");
+ }
+ mRequestedRefreshRate = requestedRefreshRate;
return this;
}
- /** Builds the instance. This builder should not be touched after calling this! */
- public @NonNull VirtualDisplayConfig build() {
- checkNotUsed();
- mBuilderFieldsSet |= 0x800; // Mark builder used
-
- if ((mBuilderFieldsSet & 0x10) == 0) {
- mFlags = 0;
- }
- if ((mBuilderFieldsSet & 0x20) == 0) {
- mSurface = null;
- }
- if ((mBuilderFieldsSet & 0x40) == 0) {
- mUniqueId = null;
- }
- if ((mBuilderFieldsSet & 0x80) == 0) {
- mDisplayIdToMirror = DEFAULT_DISPLAY;
- }
- if ((mBuilderFieldsSet & 0x100) == 0) {
- mWindowManagerMirroring = false;
- }
- if ((mBuilderFieldsSet & 0x200) == 0) {
- mDisplayCategories = new ArrayList<>();
- }
- if ((mBuilderFieldsSet & 0x400) == 0) {
- mRequestedRefreshRate = 0.0f;
- }
- VirtualDisplayConfig o = new VirtualDisplayConfig(
+ /**
+ * Builds the {@link VirtualDisplayConfig} instance.
+ */
+ @NonNull
+ public VirtualDisplayConfig build() {
+ return new VirtualDisplayConfig(
mName,
mWidth,
mHeight,
@@ -602,27 +438,6 @@ public final class VirtualDisplayConfig implements Parcelable {
mWindowManagerMirroring,
mDisplayCategories,
mRequestedRefreshRate);
- return o;
- }
-
- private void checkNotUsed() {
- if ((mBuilderFieldsSet & 0x800) != 0) {
- throw new IllegalStateException(
- "This Builder should not be reused. Use a new Builder instance instead");
- }
}
}
-
- @DataClass.Generated(
- time = 1671047069703L,
- codegenVersion = "1.0.23",
- sourceFile = "frameworks/base/core/java/android/hardware/display/VirtualDisplayConfig.java",
- inputSignatures = "private @android.annotation.NonNull java.lang.String mName\nprivate @android.annotation.IntRange int mWidth\nprivate @android.annotation.IntRange int mHeight\nprivate @android.annotation.IntRange int mDensityDpi\nprivate @android.hardware.display.DisplayManager.VirtualDisplayFlag int mFlags\nprivate @android.annotation.Nullable android.view.Surface mSurface\nprivate @android.annotation.Nullable java.lang.String mUniqueId\nprivate int mDisplayIdToMirror\nprivate boolean mWindowManagerMirroring\nprivate @com.android.internal.util.DataClass.PluralOf(\"displayCategory\") @android.annotation.NonNull java.util.List<java.lang.String> mDisplayCategories\nprivate float mRequestedRefreshRate\nclass VirtualDisplayConfig extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genAidl=true, genBuilder=true)")
- @Deprecated
- private void __metadata() {}
-
-
- //@formatter:on
- // End of generated code
-
}
diff --git a/core/java/android/hardware/face/FaceAuthenticateOptions.aidl b/core/java/android/hardware/face/FaceAuthenticateOptions.aidl
new file mode 100644
index 000000000000..7c72b405383c
--- /dev/null
+++ b/core/java/android/hardware/face/FaceAuthenticateOptions.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.face;
+
+parcelable FaceAuthenticateOptions;
diff --git a/core/java/android/hardware/face/FaceAuthenticateOptions.java b/core/java/android/hardware/face/FaceAuthenticateOptions.java
new file mode 100644
index 000000000000..1c6de0464245
--- /dev/null
+++ b/core/java/android/hardware/face/FaceAuthenticateOptions.java
@@ -0,0 +1,633 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.face;
+
+
+import static android.os.PowerManager.WAKE_REASON_UNKNOWN;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.biometrics.AuthenticateOptions;
+import android.os.Parcelable;
+import android.os.PowerManager;
+
+import com.android.internal.util.DataClass;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Additional options when requesting Face authentication or detection.
+ *
+ * @hide
+ */
+@DataClass(
+ genParcelable = true,
+ genAidl = true,
+ genBuilder = true,
+ genSetters = true,
+ genEqualsHashCode = true
+)
+public class FaceAuthenticateOptions implements AuthenticateOptions, Parcelable {
+
+ /** The user id for this operation. */
+ private final int mUserId;
+ private static int defaultUserId() {
+ return 0;
+ }
+
+ /** The sensor id for this operation. */
+ private int mSensorId;
+ private static int defaultSensorId() {
+ return -1;
+ }
+
+ /** The current doze state of the device. */
+ @AuthenticateOptions.DisplayState
+ private final int mDisplayState;
+ private static int defaultDisplayState() {
+ return DISPLAY_STATE_UNKNOWN;
+ }
+
+ public static final int AUTHENTICATE_REASON_UNKNOWN = 0;
+ public static final int AUTHENTICATE_REASON_STARTED_WAKING_UP = 1;
+ public static final int AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN = 2;
+ public static final int AUTHENTICATE_REASON_ASSISTANT_VISIBLE = 3;
+ public static final int AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN = 4;
+ public static final int AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED = 5;
+ public static final int AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED = 6;
+ public static final int AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED = 7;
+ public static final int AUTHENTICATE_REASON_QS_EXPANDED = 8;
+ public static final int AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER = 9;
+ public static final int AUTHENTICATE_REASON_UDFPS_POINTER_DOWN = 10;
+
+ /**
+ * The reason for this operation when requested by the system (sysui),
+ * otherwise AUTHENTICATE_REASON_UNKNOWN.
+ *
+ * See frameworks/base/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
+ * for more details about each reason.
+ */
+ @AuthenticateReason
+ private final int mAuthenticateReason;
+ private static int defaultAuthenticateReason() {
+ return AUTHENTICATE_REASON_UNKNOWN;
+ }
+
+ /** A reason if this request was triggered due to a power event or WAKE_REASON_UNKNOWN. */
+ @PowerManager.WakeReason
+ private final int mWakeReason;
+ private static int defaultWakeReason() {
+ return WAKE_REASON_UNKNOWN;
+ }
+
+ /**
+ * The package name for that operation that should be used for
+ * {@link android.app.AppOpsManager} verification.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @NonNull
+ private String mOpPackageName;
+ private static String defaultOpPackageName() {
+ return "";
+ }
+
+ /**
+ * The attribution tag, if any.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @Nullable
+ private String mAttributionTag;
+ private static String defaultAttributionTag() {
+ return null;
+ }
+
+
+
+ // Code below generated by codegen v1.0.23.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/hardware/face/FaceAuthenticateOptions.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ @IntDef(prefix = "AUTHENTICATE_REASON_", value = {
+ AUTHENTICATE_REASON_UNKNOWN,
+ AUTHENTICATE_REASON_STARTED_WAKING_UP,
+ AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN,
+ AUTHENTICATE_REASON_ASSISTANT_VISIBLE,
+ AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN,
+ AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED,
+ AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED,
+ AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED,
+ AUTHENTICATE_REASON_QS_EXPANDED,
+ AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER,
+ AUTHENTICATE_REASON_UDFPS_POINTER_DOWN
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @DataClass.Generated.Member
+ public @interface AuthenticateReason {}
+
+ @DataClass.Generated.Member
+ public static String authenticateReasonToString(@AuthenticateReason int value) {
+ switch (value) {
+ case AUTHENTICATE_REASON_UNKNOWN:
+ return "AUTHENTICATE_REASON_UNKNOWN";
+ case AUTHENTICATE_REASON_STARTED_WAKING_UP:
+ return "AUTHENTICATE_REASON_STARTED_WAKING_UP";
+ case AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN:
+ return "AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN";
+ case AUTHENTICATE_REASON_ASSISTANT_VISIBLE:
+ return "AUTHENTICATE_REASON_ASSISTANT_VISIBLE";
+ case AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN:
+ return "AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN";
+ case AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED:
+ return "AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED";
+ case AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED:
+ return "AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED";
+ case AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED:
+ return "AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED";
+ case AUTHENTICATE_REASON_QS_EXPANDED:
+ return "AUTHENTICATE_REASON_QS_EXPANDED";
+ case AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER:
+ return "AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER";
+ case AUTHENTICATE_REASON_UDFPS_POINTER_DOWN:
+ return "AUTHENTICATE_REASON_UDFPS_POINTER_DOWN";
+ default: return Integer.toHexString(value);
+ }
+ }
+
+ @DataClass.Generated.Member
+ /* package-private */ FaceAuthenticateOptions(
+ int userId,
+ int sensorId,
+ @AuthenticateOptions.DisplayState int displayState,
+ @AuthenticateReason int authenticateReason,
+ @PowerManager.WakeReason int wakeReason,
+ @NonNull String opPackageName,
+ @Nullable String attributionTag) {
+ this.mUserId = userId;
+ this.mSensorId = sensorId;
+ this.mDisplayState = displayState;
+ com.android.internal.util.AnnotationValidations.validate(
+ AuthenticateOptions.DisplayState.class, null, mDisplayState);
+ this.mAuthenticateReason = authenticateReason;
+
+ if (!(mAuthenticateReason == AUTHENTICATE_REASON_UNKNOWN)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_STARTED_WAKING_UP)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_ASSISTANT_VISIBLE)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_QS_EXPANDED)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_UDFPS_POINTER_DOWN)) {
+ throw new java.lang.IllegalArgumentException(
+ "authenticateReason was " + mAuthenticateReason + " but must be one of: "
+ + "AUTHENTICATE_REASON_UNKNOWN(" + AUTHENTICATE_REASON_UNKNOWN + "), "
+ + "AUTHENTICATE_REASON_STARTED_WAKING_UP(" + AUTHENTICATE_REASON_STARTED_WAKING_UP + "), "
+ + "AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN(" + AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN + "), "
+ + "AUTHENTICATE_REASON_ASSISTANT_VISIBLE(" + AUTHENTICATE_REASON_ASSISTANT_VISIBLE + "), "
+ + "AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN(" + AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN + "), "
+ + "AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED(" + AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED + "), "
+ + "AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED(" + AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED + "), "
+ + "AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED(" + AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED + "), "
+ + "AUTHENTICATE_REASON_QS_EXPANDED(" + AUTHENTICATE_REASON_QS_EXPANDED + "), "
+ + "AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER(" + AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER + "), "
+ + "AUTHENTICATE_REASON_UDFPS_POINTER_DOWN(" + AUTHENTICATE_REASON_UDFPS_POINTER_DOWN + ")");
+ }
+
+ this.mWakeReason = wakeReason;
+ com.android.internal.util.AnnotationValidations.validate(
+ PowerManager.WakeReason.class, null, mWakeReason);
+ this.mOpPackageName = opPackageName;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mOpPackageName);
+ this.mAttributionTag = attributionTag;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ /**
+ * The user id for this operation.
+ */
+ @DataClass.Generated.Member
+ public int getUserId() {
+ return mUserId;
+ }
+
+ /**
+ * The sensor id for this operation.
+ */
+ @DataClass.Generated.Member
+ public int getSensorId() {
+ return mSensorId;
+ }
+
+ /**
+ * The current doze state of the device.
+ */
+ @DataClass.Generated.Member
+ public @AuthenticateOptions.DisplayState int getDisplayState() {
+ return mDisplayState;
+ }
+
+ /**
+ * The reason for this operation when requested by the system (sysui),
+ * otherwise AUTHENTICATE_REASON_UNKNOWN.
+ *
+ * See frameworks/base/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
+ * for more details about each reason.
+ */
+ @DataClass.Generated.Member
+ public @AuthenticateReason int getAuthenticateReason() {
+ return mAuthenticateReason;
+ }
+
+ /**
+ * A reason if this request was triggered due to a power event or WAKE_REASON_UNKNOWN.
+ */
+ @DataClass.Generated.Member
+ public @PowerManager.WakeReason int getWakeReason() {
+ return mWakeReason;
+ }
+
+ /**
+ * The package name for that operation that should be used for
+ * {@link android.app.AppOpsManager} verification.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @NonNull String getOpPackageName() {
+ return mOpPackageName;
+ }
+
+ /**
+ * The attribution tag, if any.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @Nullable String getAttributionTag() {
+ return mAttributionTag;
+ }
+
+ /**
+ * The sensor id for this operation.
+ */
+ @DataClass.Generated.Member
+ public @NonNull FaceAuthenticateOptions setSensorId( int value) {
+ mSensorId = value;
+ return this;
+ }
+
+ /**
+ * The package name for that operation that should be used for
+ * {@link android.app.AppOpsManager} verification.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @NonNull FaceAuthenticateOptions setOpPackageName(@NonNull String value) {
+ mOpPackageName = value;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mOpPackageName);
+ return this;
+ }
+
+ /**
+ * The attribution tag, if any.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @NonNull FaceAuthenticateOptions setAttributionTag(@NonNull String value) {
+ mAttributionTag = value;
+ return this;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public boolean equals(@Nullable Object o) {
+ // You can override field equality logic by defining either of the methods like:
+ // boolean fieldNameEquals(FaceAuthenticateOptions other) { ... }
+ // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ @SuppressWarnings("unchecked")
+ FaceAuthenticateOptions that = (FaceAuthenticateOptions) o;
+ //noinspection PointlessBooleanExpression
+ return true
+ && mUserId == that.mUserId
+ && mSensorId == that.mSensorId
+ && mDisplayState == that.mDisplayState
+ && mAuthenticateReason == that.mAuthenticateReason
+ && mWakeReason == that.mWakeReason
+ && java.util.Objects.equals(mOpPackageName, that.mOpPackageName)
+ && java.util.Objects.equals(mAttributionTag, that.mAttributionTag);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int hashCode() {
+ // You can override field hashCode logic by defining methods like:
+ // int fieldNameHashCode() { ... }
+
+ int _hash = 1;
+ _hash = 31 * _hash + mUserId;
+ _hash = 31 * _hash + mSensorId;
+ _hash = 31 * _hash + mDisplayState;
+ _hash = 31 * _hash + mAuthenticateReason;
+ _hash = 31 * _hash + mWakeReason;
+ _hash = 31 * _hash + java.util.Objects.hashCode(mOpPackageName);
+ _hash = 31 * _hash + java.util.Objects.hashCode(mAttributionTag);
+ return _hash;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ byte flg = 0;
+ if (mAttributionTag != null) flg |= 0x40;
+ dest.writeByte(flg);
+ dest.writeInt(mUserId);
+ dest.writeInt(mSensorId);
+ dest.writeInt(mDisplayState);
+ dest.writeInt(mAuthenticateReason);
+ dest.writeInt(mWakeReason);
+ dest.writeString(mOpPackageName);
+ if (mAttributionTag != null) dest.writeString(mAttributionTag);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ protected FaceAuthenticateOptions(@NonNull android.os.Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ byte flg = in.readByte();
+ int userId = in.readInt();
+ int sensorId = in.readInt();
+ int displayState = in.readInt();
+ int authenticateReason = in.readInt();
+ int wakeReason = in.readInt();
+ String opPackageName = in.readString();
+ String attributionTag = (flg & 0x40) == 0 ? null : in.readString();
+
+ this.mUserId = userId;
+ this.mSensorId = sensorId;
+ this.mDisplayState = displayState;
+ com.android.internal.util.AnnotationValidations.validate(
+ AuthenticateOptions.DisplayState.class, null, mDisplayState);
+ this.mAuthenticateReason = authenticateReason;
+
+ if (!(mAuthenticateReason == AUTHENTICATE_REASON_UNKNOWN)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_STARTED_WAKING_UP)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_ASSISTANT_VISIBLE)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_QS_EXPANDED)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_UDFPS_POINTER_DOWN)) {
+ throw new java.lang.IllegalArgumentException(
+ "authenticateReason was " + mAuthenticateReason + " but must be one of: "
+ + "AUTHENTICATE_REASON_UNKNOWN(" + AUTHENTICATE_REASON_UNKNOWN + "), "
+ + "AUTHENTICATE_REASON_STARTED_WAKING_UP(" + AUTHENTICATE_REASON_STARTED_WAKING_UP + "), "
+ + "AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN(" + AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN + "), "
+ + "AUTHENTICATE_REASON_ASSISTANT_VISIBLE(" + AUTHENTICATE_REASON_ASSISTANT_VISIBLE + "), "
+ + "AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN(" + AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN + "), "
+ + "AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED(" + AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED + "), "
+ + "AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED(" + AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED + "), "
+ + "AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED(" + AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED + "), "
+ + "AUTHENTICATE_REASON_QS_EXPANDED(" + AUTHENTICATE_REASON_QS_EXPANDED + "), "
+ + "AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER(" + AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER + "), "
+ + "AUTHENTICATE_REASON_UDFPS_POINTER_DOWN(" + AUTHENTICATE_REASON_UDFPS_POINTER_DOWN + ")");
+ }
+
+ this.mWakeReason = wakeReason;
+ com.android.internal.util.AnnotationValidations.validate(
+ PowerManager.WakeReason.class, null, mWakeReason);
+ this.mOpPackageName = opPackageName;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mOpPackageName);
+ this.mAttributionTag = attributionTag;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<FaceAuthenticateOptions> CREATOR
+ = new Parcelable.Creator<FaceAuthenticateOptions>() {
+ @Override
+ public FaceAuthenticateOptions[] newArray(int size) {
+ return new FaceAuthenticateOptions[size];
+ }
+
+ @Override
+ public FaceAuthenticateOptions createFromParcel(@NonNull android.os.Parcel in) {
+ return new FaceAuthenticateOptions(in);
+ }
+ };
+
+ /**
+ * A builder for {@link FaceAuthenticateOptions}
+ */
+ @SuppressWarnings("WeakerAccess")
+ @DataClass.Generated.Member
+ public static class Builder {
+
+ private int mUserId;
+ private int mSensorId;
+ private @AuthenticateOptions.DisplayState int mDisplayState;
+ private @AuthenticateReason int mAuthenticateReason;
+ private @PowerManager.WakeReason int mWakeReason;
+ private @NonNull String mOpPackageName;
+ private @Nullable String mAttributionTag;
+
+ private long mBuilderFieldsSet = 0L;
+
+ public Builder() {
+ }
+
+ /**
+ * The user id for this operation.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setUserId(int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x1;
+ mUserId = value;
+ return this;
+ }
+
+ /**
+ * The sensor id for this operation.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setSensorId(int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x2;
+ mSensorId = value;
+ return this;
+ }
+
+ /**
+ * The current doze state of the device.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setDisplayState(@AuthenticateOptions.DisplayState int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x4;
+ mDisplayState = value;
+ return this;
+ }
+
+ /**
+ * The reason for this operation when requested by the system (sysui),
+ * otherwise AUTHENTICATE_REASON_UNKNOWN.
+ *
+ * See frameworks/base/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
+ * for more details about each reason.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setAuthenticateReason(@AuthenticateReason int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x8;
+ mAuthenticateReason = value;
+ return this;
+ }
+
+ /**
+ * A reason if this request was triggered due to a power event or WAKE_REASON_UNKNOWN.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setWakeReason(@PowerManager.WakeReason int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x10;
+ mWakeReason = value;
+ return this;
+ }
+
+ /**
+ * The package name for that operation that should be used for
+ * {@link android.app.AppOpsManager} verification.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setOpPackageName(@NonNull String value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x20;
+ mOpPackageName = value;
+ return this;
+ }
+
+ /**
+ * The attribution tag, if any.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setAttributionTag(@NonNull String value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x40;
+ mAttributionTag = value;
+ return this;
+ }
+
+ /** Builds the instance. This builder should not be touched after calling this! */
+ public @NonNull FaceAuthenticateOptions build() {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x80; // Mark builder used
+
+ if ((mBuilderFieldsSet & 0x1) == 0) {
+ mUserId = defaultUserId();
+ }
+ if ((mBuilderFieldsSet & 0x2) == 0) {
+ mSensorId = defaultSensorId();
+ }
+ if ((mBuilderFieldsSet & 0x4) == 0) {
+ mDisplayState = defaultDisplayState();
+ }
+ if ((mBuilderFieldsSet & 0x8) == 0) {
+ mAuthenticateReason = defaultAuthenticateReason();
+ }
+ if ((mBuilderFieldsSet & 0x10) == 0) {
+ mWakeReason = defaultWakeReason();
+ }
+ if ((mBuilderFieldsSet & 0x20) == 0) {
+ mOpPackageName = defaultOpPackageName();
+ }
+ if ((mBuilderFieldsSet & 0x40) == 0) {
+ mAttributionTag = defaultAttributionTag();
+ }
+ FaceAuthenticateOptions o = new FaceAuthenticateOptions(
+ mUserId,
+ mSensorId,
+ mDisplayState,
+ mAuthenticateReason,
+ mWakeReason,
+ mOpPackageName,
+ mAttributionTag);
+ return o;
+ }
+
+ private void checkNotUsed() {
+ if ((mBuilderFieldsSet & 0x80) != 0) {
+ throw new IllegalStateException(
+ "This Builder should not be reused. Use a new Builder instance instead");
+ }
+ }
+ }
+
+ @DataClass.Generated(
+ time = 1677119626034L,
+ codegenVersion = "1.0.23",
+ sourceFile = "frameworks/base/core/java/android/hardware/face/FaceAuthenticateOptions.java",
+ inputSignatures = "private final int mUserId\nprivate int mSensorId\nprivate final @android.hardware.biometrics.AuthenticateOptions.DisplayState int mDisplayState\npublic static final int AUTHENTICATE_REASON_UNKNOWN\npublic static final int AUTHENTICATE_REASON_STARTED_WAKING_UP\npublic static final int AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN\npublic static final int AUTHENTICATE_REASON_ASSISTANT_VISIBLE\npublic static final int AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN\npublic static final int AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED\npublic static final int AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED\npublic static final int AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED\npublic static final int AUTHENTICATE_REASON_QS_EXPANDED\npublic static final int AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER\npublic static final int AUTHENTICATE_REASON_UDFPS_POINTER_DOWN\nprivate final @android.hardware.face.FaceAuthenticateOptions.AuthenticateReason int mAuthenticateReason\nprivate final @android.os.PowerManager.WakeReason int mWakeReason\nprivate @android.annotation.NonNull java.lang.String mOpPackageName\nprivate @android.annotation.Nullable java.lang.String mAttributionTag\nprivate static int defaultUserId()\nprivate static int defaultSensorId()\nprivate static int defaultDisplayState()\nprivate static int defaultAuthenticateReason()\nprivate static int defaultWakeReason()\nprivate static java.lang.String defaultOpPackageName()\nprivate static java.lang.String defaultAttributionTag()\nclass FaceAuthenticateOptions extends java.lang.Object implements [android.hardware.biometrics.AuthenticateOptions, android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genAidl=true, genBuilder=true, genSetters=true, genEqualsHashCode=true)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index 96098f853552..55b20e17d4d7 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -194,18 +194,30 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
}
/**
- * Request authentication of a crypto object. This call operates the face recognition hardware
- * and starts capturing images. It terminates when
+ * @deprecated use {@link #authenticate(CryptoObject, CancellationSignal, AuthenticationCallback, Handler, FaceAuthenticateOptions)}.
+ */
+ @Deprecated
+ @RequiresPermission(USE_BIOMETRIC_INTERNAL)
+ public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
+ @NonNull AuthenticationCallback callback, @Nullable Handler handler, int userId) {
+ authenticate(crypto, cancel, callback, handler, new FaceAuthenticateOptions.Builder()
+ .setUserId(userId)
+ .build());
+ }
+
+ /**
+ * Request authentication. This call operates the face recognition hardware and starts capturing images.
+ * It terminates when
* {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} or
* {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult)} is called, at
* which point the object is no longer valid. The operation can be canceled by using the
* provided cancel object.
*
- * @param crypto object associated with the call or null if none required.
+ * @param crypto object associated with the call or null if none required
* @param cancel an object that can be used to cancel authentication
* @param callback an object to receive authentication events
* @param handler an optional handler to handle callback events
- * @param userId userId to authenticate for
+ * @param options additional options to customize this request
* @throws IllegalArgumentException if the crypto operation is not supported or is not backed
* by
* <a href="{@docRoot}training/articles/keystore.html">Android
@@ -215,8 +227,8 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
*/
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
- @NonNull AuthenticationCallback callback, @Nullable Handler handler, int userId,
- boolean isKeyguardBypassEnabled) {
+ @NonNull AuthenticationCallback callback, @Nullable Handler handler,
+ @NonNull FaceAuthenticateOptions options) {
if (callback == null) {
throw new IllegalArgumentException("Must supply an authentication callback");
}
@@ -226,6 +238,9 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
return;
}
+ options.setOpPackageName(mContext.getOpPackageName());
+ options.setAttributionTag(mContext.getAttributionTag());
+
if (mService != null) {
try {
useHandler(handler);
@@ -233,8 +248,8 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
mCryptoObject = crypto;
final long operationId = crypto != null ? crypto.getOpId() : 0;
Trace.beginSection("FaceManager#authenticate");
- final long authId = mService.authenticate(mToken, operationId, userId,
- mServiceReceiver, mContext.getOpPackageName(), isKeyguardBypassEnabled);
+ final long authId = mService.authenticate(
+ mToken, operationId, mServiceReceiver, options);
if (cancel != null) {
cancel.setOnCancelListener(new OnAuthenticationCancelListener(authId));
}
@@ -258,7 +273,7 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
*/
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
public void detectFace(@NonNull CancellationSignal cancel,
- @NonNull FaceDetectionCallback callback, int userId) {
+ @NonNull FaceDetectionCallback callback, @NonNull FaceAuthenticateOptions options) {
if (mService == null) {
return;
}
@@ -268,11 +283,13 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
return;
}
+ options.setOpPackageName(mContext.getOpPackageName());
+ options.setAttributionTag(mContext.getAttributionTag());
+
mFaceDetectionCallback = callback;
try {
- final long authId = mService.detectFace(
- mToken, userId, mServiceReceiver, mContext.getOpPackageName());
+ final long authId = mService.detectFace(mToken, mServiceReceiver, options);
cancel.setOnCancelListener(new OnFaceDetectionCancelListener(authId));
} catch (RemoteException e) {
Slog.w(TAG, "Remote exception when requesting finger detect", e);
diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl
index 5fcc31e3ea25..9d5073e43957 100644
--- a/core/java/android/hardware/face/IFaceService.aidl
+++ b/core/java/android/hardware/face/IFaceService.aidl
@@ -24,6 +24,7 @@ import android.hardware.biometrics.ITestSessionCallback;
import android.hardware.face.IFaceAuthenticatorsRegisteredCallback;
import android.hardware.face.IFaceServiceReceiver;
import android.hardware.face.Face;
+import android.hardware.face.FaceAuthenticateOptions;
import android.hardware.face.FaceSensorPropertiesInternal;
import android.view.Surface;
@@ -52,14 +53,14 @@ interface IFaceService {
// Authenticate with a face. A requestId is returned that can be used to cancel this operation.
@EnforcePermission("USE_BIOMETRIC_INTERNAL")
- long authenticate(IBinder token, long operationId, int userId, IFaceServiceReceiver receiver,
- String opPackageName, boolean isKeyguardBypassEnabled);
+ long authenticate(IBinder token, long operationId, IFaceServiceReceiver receiver,
+ in FaceAuthenticateOptions options);
// Uses the face hardware to detect for the presence of a face, without giving details
// about accept/reject/lockout. A requestId is returned that can be used to cancel this
// operation.
@EnforcePermission("USE_BIOMETRIC_INTERNAL")
- long detectFace(IBinder token, int userId, IFaceServiceReceiver receiver, String opPackageName);
+ long detectFace(IBinder token, IFaceServiceReceiver receiver, in FaceAuthenticateOptions options);
// This method prepares the service to start authenticating, but doesn't start authentication.
// This is protected by the MANAGE_BIOMETRIC signatuer permission. This method should only be
@@ -67,9 +68,9 @@ interface IFaceService {
// by BiometricService. To start authentication after the clients are ready, use
// startPreparedClient().
@EnforcePermission("USE_BIOMETRIC_INTERNAL")
- void prepareForAuthentication(int sensorId, boolean requireConfirmation, IBinder token,
- long operationId, int userId, IBiometricSensorReceiver sensorReceiver,
- String opPackageName, long requestId, int cookie,
+ void prepareForAuthentication(boolean requireConfirmation, IBinder token,
+ long operationId, IBiometricSensorReceiver sensorReceiver,
+ in FaceAuthenticateOptions options, long requestId, int cookie,
boolean allowBackgroundAuthentication);
// Starts authentication with the previously prepared client.
diff --git a/core/java/android/hardware/fingerprint/FingerprintAuthenticateOptions.aidl b/core/java/android/hardware/fingerprint/FingerprintAuthenticateOptions.aidl
new file mode 100644
index 000000000000..ad30fab89a3b
--- /dev/null
+++ b/core/java/android/hardware/fingerprint/FingerprintAuthenticateOptions.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.fingerprint;
+
+parcelable FingerprintAuthenticateOptions;
diff --git a/core/java/android/hardware/fingerprint/FingerprintAuthenticateOptions.java b/core/java/android/hardware/fingerprint/FingerprintAuthenticateOptions.java
new file mode 100644
index 000000000000..763246e25a26
--- /dev/null
+++ b/core/java/android/hardware/fingerprint/FingerprintAuthenticateOptions.java
@@ -0,0 +1,456 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.fingerprint;
+
+import static android.hardware.fingerprint.FingerprintManager.SENSOR_ID_ANY;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.biometrics.AuthenticateOptions;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * Additional options when requesting Fingerprint authentication or detection.
+ *
+ * @hide
+ */
+@DataClass(
+ genParcelable = true,
+ genAidl = true,
+ genBuilder = true,
+ genSetters = true,
+ genEqualsHashCode = true
+)
+public final class FingerprintAuthenticateOptions implements AuthenticateOptions, Parcelable {
+
+ /** The user id for this operation. */
+ private final int mUserId;
+ private static int defaultUserId() {
+ return 0;
+ }
+
+ /** The sensor id for this operation. */
+ private int mSensorId;
+ private static int defaultSensorId() {
+ return SENSOR_ID_ANY;
+ }
+
+ /** If enrollment state should be ignored. */
+ private final boolean mIgnoreEnrollmentState;
+ private static boolean defaultIgnoreEnrollmentState() {
+ return false;
+ }
+
+ /** The current doze state of the device. */
+ @AuthenticateOptions.DisplayState
+ private final int mDisplayState;
+ private static int defaultDisplayState() {
+ return DISPLAY_STATE_UNKNOWN;
+ }
+
+ /**
+ * The package name for that operation that should be used for
+ * {@link android.app.AppOpsManager} verification.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @NonNull private String mOpPackageName;
+ private static String defaultOpPackageName() {
+ return "";
+ }
+
+ /**
+ * The attribution tag, if any.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @Nullable private String mAttributionTag;
+ private static String defaultAttributionTag() {
+ return null;
+ }
+
+
+
+ // Code below generated by codegen v1.0.23.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/hardware/fingerprint/FingerprintAuthenticateOptions.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ @DataClass.Generated.Member
+ /* package-private */ FingerprintAuthenticateOptions(
+ int userId,
+ int sensorId,
+ boolean ignoreEnrollmentState,
+ @AuthenticateOptions.DisplayState int displayState,
+ @NonNull String opPackageName,
+ @Nullable String attributionTag) {
+ this.mUserId = userId;
+ this.mSensorId = sensorId;
+ this.mIgnoreEnrollmentState = ignoreEnrollmentState;
+ this.mDisplayState = displayState;
+ com.android.internal.util.AnnotationValidations.validate(
+ AuthenticateOptions.DisplayState.class, null, mDisplayState);
+ this.mOpPackageName = opPackageName;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mOpPackageName);
+ this.mAttributionTag = attributionTag;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ /**
+ * The user id for this operation.
+ */
+ @DataClass.Generated.Member
+ public int getUserId() {
+ return mUserId;
+ }
+
+ /**
+ * The sensor id for this operation.
+ */
+ @DataClass.Generated.Member
+ public int getSensorId() {
+ return mSensorId;
+ }
+
+ /**
+ * If enrollment state should be ignored.
+ */
+ @DataClass.Generated.Member
+ public boolean isIgnoreEnrollmentState() {
+ return mIgnoreEnrollmentState;
+ }
+
+ /**
+ * The current doze state of the device.
+ */
+ @DataClass.Generated.Member
+ public @AuthenticateOptions.DisplayState int getDisplayState() {
+ return mDisplayState;
+ }
+
+ /**
+ * The package name for that operation that should be used for
+ * {@link android.app.AppOpsManager} verification.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @NonNull String getOpPackageName() {
+ return mOpPackageName;
+ }
+
+ /**
+ * The attribution tag, if any.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @Nullable String getAttributionTag() {
+ return mAttributionTag;
+ }
+
+ /**
+ * The sensor id for this operation.
+ */
+ @DataClass.Generated.Member
+ public @NonNull FingerprintAuthenticateOptions setSensorId( int value) {
+ mSensorId = value;
+ return this;
+ }
+
+ /**
+ * The package name for that operation that should be used for
+ * {@link android.app.AppOpsManager} verification.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @NonNull FingerprintAuthenticateOptions setOpPackageName(@NonNull String value) {
+ mOpPackageName = value;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mOpPackageName);
+ return this;
+ }
+
+ /**
+ * The attribution tag, if any.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @NonNull FingerprintAuthenticateOptions setAttributionTag(@NonNull String value) {
+ mAttributionTag = value;
+ return this;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public boolean equals(@Nullable Object o) {
+ // You can override field equality logic by defining either of the methods like:
+ // boolean fieldNameEquals(FingerprintAuthenticateOptions other) { ... }
+ // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ @SuppressWarnings("unchecked")
+ FingerprintAuthenticateOptions that = (FingerprintAuthenticateOptions) o;
+ //noinspection PointlessBooleanExpression
+ return true
+ && mUserId == that.mUserId
+ && mSensorId == that.mSensorId
+ && mIgnoreEnrollmentState == that.mIgnoreEnrollmentState
+ && mDisplayState == that.mDisplayState
+ && java.util.Objects.equals(mOpPackageName, that.mOpPackageName)
+ && java.util.Objects.equals(mAttributionTag, that.mAttributionTag);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int hashCode() {
+ // You can override field hashCode logic by defining methods like:
+ // int fieldNameHashCode() { ... }
+
+ int _hash = 1;
+ _hash = 31 * _hash + mUserId;
+ _hash = 31 * _hash + mSensorId;
+ _hash = 31 * _hash + Boolean.hashCode(mIgnoreEnrollmentState);
+ _hash = 31 * _hash + mDisplayState;
+ _hash = 31 * _hash + java.util.Objects.hashCode(mOpPackageName);
+ _hash = 31 * _hash + java.util.Objects.hashCode(mAttributionTag);
+ return _hash;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ byte flg = 0;
+ if (mIgnoreEnrollmentState) flg |= 0x4;
+ if (mAttributionTag != null) flg |= 0x20;
+ dest.writeByte(flg);
+ dest.writeInt(mUserId);
+ dest.writeInt(mSensorId);
+ dest.writeInt(mDisplayState);
+ dest.writeString(mOpPackageName);
+ if (mAttributionTag != null) dest.writeString(mAttributionTag);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ /* package-private */ FingerprintAuthenticateOptions(@NonNull android.os.Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ byte flg = in.readByte();
+ boolean ignoreEnrollmentState = (flg & 0x4) != 0;
+ int userId = in.readInt();
+ int sensorId = in.readInt();
+ int displayState = in.readInt();
+ String opPackageName = in.readString();
+ String attributionTag = (flg & 0x20) == 0 ? null : in.readString();
+
+ this.mUserId = userId;
+ this.mSensorId = sensorId;
+ this.mIgnoreEnrollmentState = ignoreEnrollmentState;
+ this.mDisplayState = displayState;
+ com.android.internal.util.AnnotationValidations.validate(
+ AuthenticateOptions.DisplayState.class, null, mDisplayState);
+ this.mOpPackageName = opPackageName;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mOpPackageName);
+ this.mAttributionTag = attributionTag;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<FingerprintAuthenticateOptions> CREATOR
+ = new Parcelable.Creator<FingerprintAuthenticateOptions>() {
+ @Override
+ public FingerprintAuthenticateOptions[] newArray(int size) {
+ return new FingerprintAuthenticateOptions[size];
+ }
+
+ @Override
+ public FingerprintAuthenticateOptions createFromParcel(@NonNull android.os.Parcel in) {
+ return new FingerprintAuthenticateOptions(in);
+ }
+ };
+
+ /**
+ * A builder for {@link FingerprintAuthenticateOptions}
+ */
+ @SuppressWarnings("WeakerAccess")
+ @DataClass.Generated.Member
+ public static final class Builder {
+
+ private int mUserId;
+ private int mSensorId;
+ private boolean mIgnoreEnrollmentState;
+ private @AuthenticateOptions.DisplayState int mDisplayState;
+ private @NonNull String mOpPackageName;
+ private @Nullable String mAttributionTag;
+
+ private long mBuilderFieldsSet = 0L;
+
+ public Builder() {
+ }
+
+ /**
+ * The user id for this operation.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setUserId(int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x1;
+ mUserId = value;
+ return this;
+ }
+
+ /**
+ * The sensor id for this operation.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setSensorId(int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x2;
+ mSensorId = value;
+ return this;
+ }
+
+ /**
+ * If enrollment state should be ignored.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setIgnoreEnrollmentState(boolean value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x4;
+ mIgnoreEnrollmentState = value;
+ return this;
+ }
+
+ /**
+ * The current doze state of the device.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setDisplayState(@AuthenticateOptions.DisplayState int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x8;
+ mDisplayState = value;
+ return this;
+ }
+
+ /**
+ * The package name for that operation that should be used for
+ * {@link android.app.AppOpsManager} verification.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setOpPackageName(@NonNull String value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x10;
+ mOpPackageName = value;
+ return this;
+ }
+
+ /**
+ * The attribution tag, if any.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setAttributionTag(@NonNull String value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x20;
+ mAttributionTag = value;
+ return this;
+ }
+
+ /** Builds the instance. This builder should not be touched after calling this! */
+ public @NonNull FingerprintAuthenticateOptions build() {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x40; // Mark builder used
+
+ if ((mBuilderFieldsSet & 0x1) == 0) {
+ mUserId = defaultUserId();
+ }
+ if ((mBuilderFieldsSet & 0x2) == 0) {
+ mSensorId = defaultSensorId();
+ }
+ if ((mBuilderFieldsSet & 0x4) == 0) {
+ mIgnoreEnrollmentState = defaultIgnoreEnrollmentState();
+ }
+ if ((mBuilderFieldsSet & 0x8) == 0) {
+ mDisplayState = defaultDisplayState();
+ }
+ if ((mBuilderFieldsSet & 0x10) == 0) {
+ mOpPackageName = defaultOpPackageName();
+ }
+ if ((mBuilderFieldsSet & 0x20) == 0) {
+ mAttributionTag = defaultAttributionTag();
+ }
+ FingerprintAuthenticateOptions o = new FingerprintAuthenticateOptions(
+ mUserId,
+ mSensorId,
+ mIgnoreEnrollmentState,
+ mDisplayState,
+ mOpPackageName,
+ mAttributionTag);
+ return o;
+ }
+
+ private void checkNotUsed() {
+ if ((mBuilderFieldsSet & 0x40) != 0) {
+ throw new IllegalStateException(
+ "This Builder should not be reused. Use a new Builder instance instead");
+ }
+ }
+ }
+
+ @DataClass.Generated(
+ time = 1677119626721L,
+ codegenVersion = "1.0.23",
+ sourceFile = "frameworks/base/core/java/android/hardware/fingerprint/FingerprintAuthenticateOptions.java",
+ inputSignatures = "private final int mUserId\nprivate int mSensorId\nprivate final boolean mIgnoreEnrollmentState\nprivate final @android.hardware.biometrics.AuthenticateOptions.DisplayState int mDisplayState\nprivate @android.annotation.NonNull java.lang.String mOpPackageName\nprivate @android.annotation.Nullable java.lang.String mAttributionTag\nprivate static int defaultUserId()\nprivate static int defaultSensorId()\nprivate static boolean defaultIgnoreEnrollmentState()\nprivate static int defaultDisplayState()\nprivate static java.lang.String defaultOpPackageName()\nprivate static java.lang.String defaultAttributionTag()\nclass FingerprintAuthenticateOptions extends java.lang.Object implements [android.hardware.biometrics.AuthenticateOptions, android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genAidl=true, genBuilder=true, genSetters=true, genEqualsHashCode=true)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index d9f8f8e0e715..eb8136e39d29 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -577,8 +577,10 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
/**
* Per-user version of authenticate.
+ * @deprecated use {@link #authenticate(CryptoObject, CancellationSignal, AuthenticationCallback, Handler, FingerprintAuthenticateOptions)}.
* @hide
*/
+ @Deprecated
@RequiresPermission(anyOf = {USE_BIOMETRIC, USE_FINGERPRINT})
public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
@NonNull AuthenticationCallback callback, Handler handler, int userId) {
@@ -587,13 +589,29 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
/**
* Per-user and per-sensor version of authenticate.
+ * @deprecated use {@link #authenticate(CryptoObject, CancellationSignal, AuthenticationCallback, Handler, FingerprintAuthenticateOptions)}.
* @hide
*/
+ @Deprecated
@RequiresPermission(anyOf = {USE_BIOMETRIC, USE_FINGERPRINT})
public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
@NonNull AuthenticationCallback callback, Handler handler, int sensorId, int userId,
int flags) {
+ authenticate(crypto, cancel, callback, handler, new FingerprintAuthenticateOptions.Builder()
+ .setSensorId(sensorId)
+ .setUserId(userId)
+ .setIgnoreEnrollmentState(flags != 0)
+ .build());
+ }
+ /**
+ * Version of authenticate with additional options.
+ * @hide
+ */
+ @RequiresPermission(anyOf = {USE_BIOMETRIC, USE_FINGERPRINT})
+ public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
+ @NonNull AuthenticationCallback callback, @NonNull Handler handler,
+ @NonNull FingerprintAuthenticateOptions options) {
FrameworkStatsLog.write(FrameworkStatsLog.AUTH_DEPRECATED_API_USED,
AUTH_DEPRECATED_APIUSED__DEPRECATED_API__API_FINGERPRINT_MANAGER_AUTHENTICATE,
mContext.getApplicationInfo().uid,
@@ -608,7 +626,8 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
return;
}
- final boolean ignoreEnrollmentState = flags == 0 ? false : true;
+ options.setOpPackageName(mContext.getOpPackageName());
+ options.setAttributionTag(mContext.getAttributionTag());
if (mService != null) {
try {
@@ -616,16 +635,7 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
mAuthenticationCallback = callback;
mCryptoObject = crypto;
final long operationId = crypto != null ? crypto.getOpId() : 0;
- final long authId =
- mService.authenticate(
- mToken,
- operationId,
- sensorId,
- userId,
- mServiceReceiver,
- mContext.getOpPackageName(),
- mContext.getAttributionTag(),
- ignoreEnrollmentState);
+ final long authId = mService.authenticate(mToken, operationId, mServiceReceiver, options);
if (cancel != null) {
cancel.setOnCancelListener(new OnAuthenticationCancelListener(authId));
}
@@ -647,7 +657,7 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
*/
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
public void detectFingerprint(@NonNull CancellationSignal cancel,
- @NonNull FingerprintDetectionCallback callback, int userId) {
+ @NonNull FingerprintDetectionCallback callback, @NonNull FingerprintAuthenticateOptions options) {
if (mService == null) {
return;
}
@@ -657,11 +667,13 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
return;
}
+ options.setOpPackageName(mContext.getOpPackageName());
+ options.setAttributionTag(mContext.getAttributionTag());
+
mFingerprintDetectionCallback = callback;
try {
- final long authId = mService.detectFingerprint(mToken, userId, mServiceReceiver,
- mContext.getOpPackageName());
+ final long authId = mService.detectFingerprint(mToken, mServiceReceiver, options);
cancel.setOnCancelListener(new OnFingerprintDetectionCancelListener(authId));
} catch (RemoteException e) {
Slog.w(TAG, "Remote exception when requesting finger detect", e);
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index 6f35713d434f..ec5749ed4f05 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -29,6 +29,7 @@ import android.hardware.fingerprint.IUdfpsOverlayController;
import android.hardware.fingerprint.ISidefpsController;
import android.hardware.fingerprint.IUdfpsOverlay;
import android.hardware.fingerprint.Fingerprint;
+import android.hardware.fingerprint.FingerprintAuthenticateOptions;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import java.util.List;
@@ -56,16 +57,15 @@ interface IFingerprintService {
// Authenticate with a fingerprint. This is protected by USE_FINGERPRINT/USE_BIOMETRIC
// permission. This is effectively deprecated, since it only comes through FingerprintManager
// now. A requestId is returned that can be used to cancel this operation.
- long authenticate(IBinder token, long operationId, int sensorId, int userId,
- IFingerprintServiceReceiver receiver, String opPackageName, String attributionTag,
- boolean shouldIgnoreEnrollmentState);
+ long authenticate(IBinder token, long operationId, IFingerprintServiceReceiver receiver,
+ in FingerprintAuthenticateOptions options);
// Uses the fingerprint hardware to detect for the presence of a finger, without giving details
// about accept/reject/lockout. A requestId is returned that can be used to cancel this
// operation.
@EnforcePermission("USE_BIOMETRIC_INTERNAL")
- long detectFingerprint(IBinder token, int userId, IFingerprintServiceReceiver receiver,
- String opPackageName);
+ long detectFingerprint(IBinder token, IFingerprintServiceReceiver receiver,
+ in FingerprintAuthenticateOptions options);
// This method prepares the service to start authenticating, but doesn't start authentication.
// This is protected by the MANAGE_BIOMETRIC signatuer permission. This method should only be
@@ -73,8 +73,8 @@ interface IFingerprintService {
// by BiometricService. To start authentication after the clients are ready, use
// startPreparedClient().
@EnforcePermission("MANAGE_BIOMETRIC")
- void prepareForAuthentication(int sensorId, IBinder token, long operationId, int userId,
- IBiometricSensorReceiver sensorReceiver, String opPackageName, long requestId,
+ void prepareForAuthentication(IBinder token, long operationId,
+ IBiometricSensorReceiver sensorReceiver, in FingerprintAuthenticateOptions options, long requestId,
int cookie, boolean allowBackgroundAuthentication);
// Starts authentication with the previously prepared client.
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index a33cd9760091..490589f34411 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -48,8 +48,6 @@ import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.ServiceManager.ServiceNotFoundException;
import android.os.SystemClock;
import android.os.VibrationEffect;
import android.os.Vibrator;
@@ -305,8 +303,11 @@ public final class InputManager {
private static String sVelocityTrackerStrategy;
- private InputManager(IInputManager im) {
- mIm = im;
+ private InputManagerGlobal mGlobal;
+
+ private InputManager() {
+ mGlobal = InputManagerGlobal.getInstance();
+ mIm = mGlobal.getInputManagerService();
try {
sVelocityTrackerStrategy = mIm.getVelocityTrackerStrategy();
} catch (RemoteException ex) {
@@ -324,7 +325,8 @@ public final class InputManager {
@VisibleForTesting
public static InputManager resetInstance(IInputManager inputManagerService) {
synchronized (InputManager.class) {
- sInstance = new InputManager(inputManagerService);
+ InputManagerGlobal.resetInstance(inputManagerService);
+ sInstance = new InputManager();
return sInstance;
}
}
@@ -337,6 +339,7 @@ public final class InputManager {
@VisibleForTesting
public static void clearInstance() {
synchronized (InputManager.class) {
+ InputManagerGlobal.clearInstance();
sInstance = null;
}
}
@@ -364,13 +367,7 @@ public final class InputManager {
public static InputManager getInstance(Context context) {
synchronized (InputManager.class) {
if (sInstance == null) {
- try {
- sInstance = new InputManager(IInputManager.Stub
- .asInterface(ServiceManager.getServiceOrThrow(Context.INPUT_SERVICE)));
-
- } catch (ServiceNotFoundException e) {
- throw new IllegalStateException(e);
- }
+ sInstance = new InputManager();
}
if (sInstance.mWeakContext == null || sInstance.mWeakContext.get() == null) {
sInstance.mWeakContext = new WeakReference(context);
diff --git a/core/java/android/hardware/input/InputManagerGlobal.java b/core/java/android/hardware/input/InputManagerGlobal.java
new file mode 100644
index 000000000000..82dddfc8756c
--- /dev/null
+++ b/core/java/android/hardware/input/InputManagerGlobal.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input;
+
+import android.content.Context;
+import android.os.IBinder;
+import android.os.ServiceManager;
+
+/**
+ * Manages communication with the input manager service on behalf of
+ * an application process. You're probably looking for {@link InputManager}.
+ *
+ * @hide
+ */
+public final class InputManagerGlobal {
+ private static final String TAG = "InputManagerGlobal";
+
+ private static InputManagerGlobal sInstance;
+
+ private final IInputManager mIm;
+
+ public InputManagerGlobal(IInputManager im) {
+ mIm = im;
+ }
+
+ /**
+ * Gets an instance of the input manager global singleton.
+ *
+ * @return The display manager instance, may be null early in system startup
+ * before the display manager has been fully initialized.
+ */
+ public static InputManagerGlobal getInstance() {
+ synchronized (InputManagerGlobal.class) {
+ if (sInstance == null) {
+ IBinder b = ServiceManager.getService(Context.INPUT_SERVICE);
+ if (b != null) {
+ sInstance = new InputManagerGlobal(IInputManager.Stub.asInterface(b));
+ }
+ }
+ return sInstance;
+ }
+ }
+
+ public IInputManager getInputManagerService() {
+ return mIm;
+ }
+
+ /**
+ * Gets an instance of the input manager.
+ *
+ * @return The input manager instance.
+ */
+ public static InputManagerGlobal resetInstance(IInputManager inputManagerService) {
+ synchronized (InputManager.class) {
+ sInstance = new InputManagerGlobal(inputManagerService);
+ return sInstance;
+ }
+ }
+
+ /**
+ * Clear the instance of the input manager.
+ */
+ public static void clearInstance() {
+ synchronized (InputManagerGlobal.class) {
+ sInstance = null;
+ }
+ }
+}
diff --git a/core/java/android/hardware/input/VirtualTouchEvent.java b/core/java/android/hardware/input/VirtualTouchEvent.java
index 9b1e6e84a022..a2bb382e9950 100644
--- a/core/java/android/hardware/input/VirtualTouchEvent.java
+++ b/core/java/android/hardware/input/VirtualTouchEvent.java
@@ -18,6 +18,7 @@ package android.hardware.input;
import android.annotation.FloatRange;
import android.annotation.IntDef;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.os.Parcel;
@@ -82,6 +83,10 @@ public final class VirtualTouchEvent implements Parcelable {
@Retention(RetentionPolicy.SOURCE)
public @interface Action {}
+ // The maximum number of pointers that can be touching the screen at once. (See MAX_POINTERS
+ // in frameworks/native/include/input/Input.h)
+ private static final int MAX_POINTERS = 16;
+
private final int mPointerId;
private final @ToolType int mToolType;
private final @Action int mAction;
@@ -214,9 +219,17 @@ public final class VirtualTouchEvent implements Parcelable {
/**
* Sets the pointer id of the event.
*
+ * <p>A Valid pointer id need to be in the range of 0 to 15.
+ *
* @return this builder, to allow for chaining of calls
*/
- public @NonNull Builder setPointerId(int pointerId) {
+ public @NonNull Builder setPointerId(
+ @IntRange(from = 0, to = MAX_POINTERS - 1) int pointerId) {
+ if (pointerId < 0 || pointerId > 15) {
+ throw new IllegalArgumentException(
+ "The pointer id must be in the range 0 - " + (MAX_POINTERS - 1)
+ + "inclusive, but was: " + pointerId);
+ }
mPointerId = pointerId;
return this;
}
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 9341105675a2..104a8b2095d8 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -475,8 +475,8 @@ public class NetworkPolicyManager {
*
* @param uid The UID whose status needs to be checked.
* @return {@link ConnectivityManager#RESTRICT_BACKGROUND_STATUS_DISABLED},
- * {@link ConnectivityManager##RESTRICT_BACKGROUND_STATUS_ENABLED},
- * or {@link ConnectivityManager##RESTRICT_BACKGROUND_STATUS_WHITELISTED} to denote
+ * {@link ConnectivityManager#RESTRICT_BACKGROUND_STATUS_ENABLED},
+ * or {@link ConnectivityManager#RESTRICT_BACKGROUND_STATUS_WHITELISTED} to denote
* the current status of the UID.
* @hide
*/
@@ -769,6 +769,28 @@ public class NetworkPolicyManager {
}
/**
+ * Returns the default network capabilities
+ * ({@link ActivityManager#PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK
+ * ActivityManager.PROCESS_CAPABILITY_*}) of the specified process state.
+ * This <b>DOES NOT</b> return all default process capabilities for a proc state.
+ * @hide
+ */
+ public static int getDefaultProcessNetworkCapabilities(int procState) {
+ switch (procState) {
+ case ActivityManager.PROCESS_STATE_PERSISTENT:
+ case ActivityManager.PROCESS_STATE_PERSISTENT_UI:
+ case ActivityManager.PROCESS_STATE_TOP:
+ return ActivityManager.PROCESS_CAPABILITY_ALL;
+ case ActivityManager.PROCESS_STATE_BOUND_TOP:
+ case ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE:
+ case ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE:
+ return ActivityManager.PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
+ default:
+ return ActivityManager.PROCESS_CAPABILITY_NONE;
+ }
+ }
+
+ /**
* Returns true if {@param procState} is considered foreground and as such will be allowed
* to access network when the device is idle or in battery saver mode. Otherwise, false.
* @hide
@@ -784,7 +806,7 @@ public class NetworkPolicyManager {
public static boolean isProcStateAllowedWhileIdleOrPowerSaveMode(
int procState, @ProcessCapability int capability) {
return procState <= FOREGROUND_THRESHOLD_STATE
- || (capability & ActivityManager.PROCESS_CAPABILITY_NETWORK) != 0;
+ || (capability & ActivityManager.PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK) != 0;
}
/** @hide */
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 4a244c0f87bb..e2af9b03d7f5 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -26,8 +26,6 @@ import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.UserIdInt;
import android.app.Activity;
-import android.app.ActivityThread;
-import android.app.OnActivityPausedListener;
import android.app.PendingIntent;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
@@ -1469,17 +1467,11 @@ public final class NfcAdapter {
if (activity == null || intent == null) {
throw new NullPointerException();
}
- if (!activity.isResumed()) {
- throw new IllegalStateException("Foreground dispatch can only be enabled " +
- "when your activity is resumed");
- }
try {
TechListParcel parcel = null;
if (techLists != null && techLists.length > 0) {
parcel = new TechListParcel(techLists);
}
- ActivityThread.currentActivityThread().registerOnActivityPausedListener(activity,
- mForegroundDispatchListener);
sService.setForegroundDispatch(intent, filters, parcel);
} catch (RemoteException e) {
attemptDeadServiceRecovery(e);
@@ -1507,25 +1499,8 @@ public final class NfcAdapter {
throw new UnsupportedOperationException();
}
}
- ActivityThread.currentActivityThread().unregisterOnActivityPausedListener(activity,
- mForegroundDispatchListener);
- disableForegroundDispatchInternal(activity, false);
- }
-
- OnActivityPausedListener mForegroundDispatchListener = new OnActivityPausedListener() {
- @Override
- public void onPaused(Activity activity) {
- disableForegroundDispatchInternal(activity, true);
- }
- };
-
- void disableForegroundDispatchInternal(Activity activity, boolean force) {
try {
sService.setForegroundDispatch(null, null, null);
- if (!force && !activity.isResumed()) {
- throw new IllegalStateException("You must disable foreground dispatching " +
- "while your activity is still resumed");
- }
} catch (RemoteException e) {
attemptDeadServiceRecovery(e);
}
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index 09540132fe0d..793a70e93f56 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -660,7 +660,7 @@ public final class ApduServiceInfo implements Parcelable {
* @param proto the ProtoOutputStream to write to
*/
public void dumpDebug(ProtoOutputStream proto) {
- getComponent().dumpDebug(proto, ApduServiceInfoProto.COMPONENT_NAME);
+ Utils.dumpDebugComponentName(getComponent(), proto, ApduServiceInfoProto.COMPONENT_NAME);
proto.write(ApduServiceInfoProto.DESCRIPTION, getDescription());
proto.write(ApduServiceInfoProto.ON_HOST, mOnHost);
if (!mOnHost) {
diff --git a/core/java/android/nfc/cardemulation/NfcFServiceInfo.java b/core/java/android/nfc/cardemulation/NfcFServiceInfo.java
index f8f7dfe034b5..7a36b269240c 100644
--- a/core/java/android/nfc/cardemulation/NfcFServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/NfcFServiceInfo.java
@@ -340,7 +340,7 @@ public final class NfcFServiceInfo implements Parcelable {
* @param proto the ProtoOutputStream to write to
*/
public void dumpDebug(ProtoOutputStream proto) {
- getComponent().dumpDebug(proto, NfcFServiceInfoProto.COMPONENT_NAME);
+ Utils.dumpDebugComponentName(getComponent(), proto, NfcFServiceInfoProto.COMPONENT_NAME);
proto.write(NfcFServiceInfoProto.DESCRIPTION, getDescription());
proto.write(NfcFServiceInfoProto.SYSTEM_CODE, getSystemCode());
proto.write(NfcFServiceInfoProto.NFCID2, getNfcid2());
diff --git a/core/java/android/nfc/cardemulation/Utils.java b/core/java/android/nfc/cardemulation/Utils.java
new file mode 100644
index 000000000000..202e1cfb48f6
--- /dev/null
+++ b/core/java/android/nfc/cardemulation/Utils.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.nfc.cardemulation;
+
+import android.annotation.NonNull;
+import android.content.ComponentName;
+import android.content.ComponentNameProto;
+import android.util.proto.ProtoOutputStream;
+
+/** @hide */
+public final class Utils {
+ private Utils() {
+ }
+
+ /** Copied from {@link ComponentName#dumpDebug(ProtoOutputStream, long)} */
+ public static void dumpDebugComponentName(
+ @NonNull ComponentName componentName, @NonNull ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+ proto.write(ComponentNameProto.PACKAGE_NAME, componentName.getPackageName());
+ proto.write(ComponentNameProto.CLASS_NAME, componentName.getClassName());
+ proto.end(token);
+ }
+}
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index 76f857bd91b7..6bc0f6ea947c 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -147,6 +147,18 @@ public class BatteryManager {
public static final String EXTRA_SEQUENCE = "seq";
/**
+ * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
+ * Int value representing the battery charging cycle count.
+ */
+ public static final String EXTRA_CYCLE_COUNT = "android.os.extra.CYCLE_COUNT";
+
+ /**
+ * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
+ * Int value representing the battery charging status.
+ */
+ public static final String EXTRA_CHARGING_STATUS = "android.os.extra.CHARGING_STATUS";
+
+ /**
* Extra for {@link android.content.Intent#ACTION_BATTERY_LEVEL_CHANGED}:
* Contains list of Bundles representing battery events
* @hide
@@ -190,6 +202,35 @@ public class BatteryManager {
/** Power source is dock. */
public static final int BATTERY_PLUGGED_DOCK = OsProtoEnums.BATTERY_PLUGGED_DOCK; // = 8
+ // values for "charge policy" property
+ /**
+ * Default policy (e.g. normal).
+ * @hide
+ */
+ @SystemApi
+ public static final int CHARGING_POLICY_DEFAULT = OsProtoEnums.CHARGING_POLICY_DEFAULT; // = 1
+ /**
+ * Optimized for battery health using static thresholds (e.g stop at 80%).
+ * @hide
+ */
+ @SystemApi
+ public static final int CHARGING_POLICY_ADAPTIVE_AON =
+ OsProtoEnums.CHARGING_POLICY_ADAPTIVE_AON; // = 2
+ /**
+ * Optimized for battery health using adaptive thresholds.
+ * @hide
+ */
+ @SystemApi
+ public static final int CHARGING_POLICY_ADAPTIVE_AC =
+ OsProtoEnums.CHARGING_POLICY_ADAPTIVE_AC; // = 3
+ /**
+ * Optimized for battery health, devices always connected to power.
+ * @hide
+ */
+ @SystemApi
+ public static final int CHARGING_POLICY_ADAPTIVE_LONGLIFE =
+ OsProtoEnums.CHARGING_POLICY_ADAPTIVE_LONGLIFE; // = 4
+
/** @hide */
public static final int BATTERY_PLUGGED_ANY =
BATTERY_PLUGGED_AC | BATTERY_PLUGGED_USB | BATTERY_PLUGGED_WIRELESS
@@ -254,6 +295,76 @@ public class BatteryManager {
*/
public static final int BATTERY_PROPERTY_STATUS = 6;
+ /**
+ * Battery manufacturing date is reported in epoch. The 0 timepoint
+ * begins at midnight Coordinated Universal Time (UTC) on January 1, 1970.
+ * It is a long integer in seconds.
+ *
+ * <p class="note">
+ * The sender must hold the {@link android.Manifest.permission#BATTERY_STATS} permission.
+ *
+ * Example: <code>
+ * // The value returned from the API can be used to create a Date, used
+ * // to set the time on a calendar and coverted to a string.
+ * import java.util.Date;
+ *
+ * mBatteryManager = mContext.getSystemService(BatteryManager.class);
+ * final long manufacturingDate =
+ * mBatteryManager.getLongProperty(BatteryManager.BATTERY_PROPERTY_MANUFACTURING_DATE);
+ * Date date = new Date(manufacturingDate);
+ * Calendar calendar = Calendar.getInstance();
+ * calendar.setTime(date);
+ * // Convert to yyyy-MM-dd HH:mm:ss format string
+ * SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ * String dateString = sdf.format(date);
+ * </code>
+ * @hide
+ */
+ @RequiresPermission(permission.BATTERY_STATS)
+ @SystemApi
+ public static final int BATTERY_PROPERTY_MANUFACTURING_DATE = 7;
+
+ /**
+ * The date of first usage is reported in epoch. The 0 timepoint
+ * begins at midnight Coordinated Universal Time (UTC) on January 1, 1970.
+ * It is a long integer in seconds.
+ *
+ * <p class="note">
+ * The sender must hold the {@link android.Manifest.permission#BATTERY_STATS} permission.
+ *
+ * {@link BATTERY_PROPERTY_MANUFACTURING_DATE for sample code}
+ * @hide
+ */
+ @RequiresPermission(permission.BATTERY_STATS)
+ @SystemApi
+ public static final int BATTERY_PROPERTY_FIRST_USAGE_DATE = 8;
+
+ /**
+ * Battery charging policy from a CHARGING_POLICY_* value..
+ *
+ * <p class="note">
+ * The sender must hold the {@link android.Manifest.permission#BATTERY_STATS} permission.
+ *
+ * @hide
+ */
+ @RequiresPermission(permission.BATTERY_STATS)
+ @SystemApi
+ public static final int BATTERY_PROPERTY_CHARGING_POLICY = 9;
+
+ /**
+ *
+ * Percentage representing the measured battery state of health (remaining
+ * estimated full charge capacity relative to the rated capacity in %).
+ *
+ * <p class="note">
+ * The sender must hold the {@link android.Manifest.permission#BATTERY_STATS} permission.
+ *
+ * @hide
+ */
+ @RequiresPermission(permission.BATTERY_STATS)
+ @SystemApi
+ public static final int BATTERY_PROPERTY_STATE_OF_HEALTH = 10;
+
private final Context mContext;
private final IBatteryStats mBatteryStats;
private final IBatteryPropertiesRegistrar mBatteryPropertiesRegistrar;
@@ -307,7 +418,6 @@ public class BatteryManager {
try {
BatteryProperty prop = new BatteryProperty();
-
if (mBatteryPropertiesRegistrar.getProperty(id, prop) == 0)
ret = prop.getLong();
else
diff --git a/core/java/android/os/CancellationSignalBeamer.java b/core/java/android/os/CancellationSignalBeamer.java
new file mode 100644
index 000000000000..afb5ff7bf626
--- /dev/null
+++ b/core/java/android/os/CancellationSignalBeamer.java
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.system.SystemCleaner;
+
+import java.lang.ref.Cleaner;
+import java.lang.ref.Reference;
+import java.util.HashMap;
+
+/**
+ * A transport for {@link CancellationSignal}, but unlike
+ * {@link CancellationSignal#createTransport()} doesn't require pre-creating the transport in the
+ * target process. Instead, cancellation is forwarded over the same IPC surface as the cancellable
+ * request.
+ *
+ * <p><strong>Important:</strong> For this to work, the following invariants must be held up:
+ * <ul>
+ * <li>A call to beam() <strong>MUST</strong> result in a call to close() on the result
+ * (otherwise, the token will be leaked and cancellation isn't propagated), and that call
+ * must happen after the call using the
+ * token is sent (otherwise, any concurrent cancellation may be lost). It is strongly
+ * recommended to use try-with-resources on the token.
+ * <li>The cancel(), forget() and cancellable operations transporting the token must either
+ * all be oneway on the same binder, or all be non-oneway to guarantee proper ordering.
+ * <li>A {@link CancellationSignal} <strong>SHOULD</strong> be used only once, as there
+ * can only be a single {@link android.os.CancellationSignal.OnCancelListener OnCancelListener}.
+ *
+ * </ul>
+ * <p>Caveats:
+ * <ul>
+ * <li>Cancellation is only ever dispatched after the token is closed, and thus after the
+ * call performing the cancellable operation (if the invariants are followed). The operation
+ * must therefore not block the incoming binder thread, or cancellation won't be possible.
+ * <li>Consequently, in the unlikely event that the sender dies right after beaming an already
+ * cancelled {@link CancellationSignal}, the cancellation may be lost (unlike with
+ * {@link CancellationSignal#createTransport()}).
+ * <li>The forwarding OnCancelListener is set in the implied finally phase of try-with-resources
+ * / when closing the token. If the receiver is in the same process, and the signal is
+ * already cancelled, this may invoke the target's OnCancelListener during that phase.
+ * </ul>
+ *
+ *
+ * <p>Usage:
+ * <pre>
+ * // Sender:
+ *
+ * class FooManager {
+ * var mCancellationSignalSender = new CancellationSignalBeamer.Sender() {
+ * &#064;Override
+ * public void onCancel(IBinder token) { remoteIFooService.onCancelToken(token); }
+ *
+ * &#064;Override
+ * public void onForget(IBinder token) { remoteIFooService.onForgetToken(token); }
+ * };
+ *
+ * public void doCancellableOperation(..., CancellationSignal cs) {
+ * try (var csToken = mCancellationSignalSender.beam(cs)) {
+ * remoteIFooService.doCancellableOperation(..., csToken);
+ * }
+ * }
+ * }
+ *
+ * // Receiver:
+ *
+ * class FooManagerService extends IFooService.Stub {
+ * var mCancellationSignalReceiver = new CancellationSignalBeamer.Receiver();
+ *
+ * &#064;Override
+ * public void doCancellableOperation(..., IBinder csToken) {
+ * CancellationSignal cs = mCancellationSignalReceiver.unbeam(csToken))
+ * // ...
+ * }
+ *
+ * &#064;Override
+ * public void onCancelToken(..., IBinder csToken) {
+ * mCancellationSignalReceiver.cancelToken(csToken))
+ * }
+ *
+ * &#064;Override
+ * public void onForgetToken(..., IBinder csToken) {
+ * mCancellationSignalReceiver.forgetToken(csToken))
+ * }
+ * }
+ *
+ * </pre>
+ *
+ * @hide
+ */
+public class CancellationSignalBeamer {
+
+ static final Cleaner sCleaner = SystemCleaner.cleaner();
+
+ /** The sending side of an {@link CancellationSignalBeamer} */
+ public abstract static class Sender {
+
+ /**
+ * Beams a {@link CancellationSignal} through an existing Binder interface.
+ *
+ * @param cs the {@code CancellationSignal} to beam, or {@code null}.
+ * @return an {@link IBinder} token. MUST be {@link CloseableToken#close}d <em>after</em>
+ * the binder call transporting it to the remote process, best with
+ * try-with-resources. {@code null} if {@code cs} was {@code null}.
+ */
+ // TODO(b/254888024): @MustBeClosed
+ @Nullable
+ public CloseableToken beam(@Nullable CancellationSignal cs) {
+ if (cs == null) {
+ return null;
+ }
+ return new Token(this, cs);
+ }
+
+ /**
+ * A {@link #beam}ed {@link CancellationSignal} was closed.
+ *
+ * MUST be forwarded to {@link Receiver#cancel} with proper ordering. See
+ * {@link CancellationSignalBeamer} for details.
+ */
+ public abstract void onCancel(IBinder token);
+
+ /**
+ * A {@link #beam}ed {@link CancellationSignal} was GC'd.
+ *
+ * MUST be forwarded to {@link Receiver#forget} with proper ordering. See
+ * {@link CancellationSignalBeamer} for details.
+ */
+ public abstract void onForget(IBinder token);
+
+ private static class Token extends Binder implements CloseableToken, Runnable {
+
+ private final Sender mSender;
+ private Preparer mPreparer;
+
+ private Token(Sender sender, CancellationSignal signal) {
+ mSender = sender;
+ mPreparer = new Preparer(sender, signal, this);
+ }
+
+ @Override
+ public void close() {
+ Preparer preparer = mPreparer;
+ mPreparer = null;
+ if (preparer != null) {
+ preparer.setup();
+ }
+ }
+
+ @Override
+ public void run() {
+ mSender.onForget(this);
+ }
+
+ private static class Preparer implements CancellationSignal.OnCancelListener {
+ private final Sender mSender;
+ private final CancellationSignal mSignal;
+ private final Token mToken;
+
+ private Preparer(Sender sender, CancellationSignal signal, Token token) {
+ mSender = sender;
+ mSignal = signal;
+ mToken = token;
+ }
+
+ void setup() {
+ sCleaner.register(this, mToken);
+ mSignal.setOnCancelListener(this);
+ }
+
+ @Override
+ public void onCancel() {
+ try {
+ mSender.onCancel(mToken);
+ } finally {
+ // Make sure we dispatch onCancel before the cleaner can run.
+ Reference.reachabilityFence(this);
+ }
+ }
+ }
+ }
+
+ /**
+ * A {@link #beam}ed {@link CancellationSignal} ready for sending over Binder.
+ *
+ * MUST be closed <em>after</em> it is sent over binder, ideally through try-with-resources.
+ */
+ public interface CloseableToken extends IBinder, AutoCloseable {
+ @Override
+ void close(); // No throws
+ }
+ }
+
+ /** The receiving side of a {@link CancellationSignalBeamer}. */
+ public static class Receiver implements IBinder.DeathRecipient {
+ private final HashMap<IBinder, CancellationSignal> mTokenMap = new HashMap<>();
+ private final boolean mCancelOnSenderDeath;
+
+ /**
+ * Constructs a new {@code Receiver}.
+ *
+ * @param cancelOnSenderDeath if true, {@link CancellationSignal}s obtained from
+ * {@link #unbeam} are automatically {@link #cancel}led if the sender token
+ * {@link Binder#linkToDeath dies}; otherwise they are simnply dropped. Note: if the
+ * sending process drops all references to the {@link CancellationSignal} before
+ * process death, the cancellation is not guaranteed.
+ */
+ public Receiver(boolean cancelOnSenderDeath) {
+ mCancelOnSenderDeath = cancelOnSenderDeath;
+ }
+
+ /**
+ * Unbeams a token that was obtained via {@link Sender#beam} and turns it back into a
+ * {@link CancellationSignal}.
+ *
+ * A subsequent call to {@link #cancel} with the same token will cancel the returned
+ * {@code CancellationSignal}.
+ *
+ * @param token a token that was obtained from {@link Sender}, possibly in a remote process.
+ * @return a {@link CancellationSignal} linked to the given token.
+ */
+ @Nullable
+ public CancellationSignal unbeam(@Nullable IBinder token) {
+ if (token == null) {
+ return null;
+ }
+ synchronized (this) {
+ CancellationSignal cs = mTokenMap.get(token);
+ if (cs != null) {
+ return cs;
+ }
+
+ cs = new CancellationSignal();
+ mTokenMap.put(token, cs);
+ try {
+ token.linkToDeath(this, 0);
+ } catch (RemoteException e) {
+ dead(token);
+ }
+ return cs;
+ }
+ }
+
+ /**
+ * Forgets state associated with the given token (if any).
+ *
+ * Subsequent calls to {@link #cancel} or binder death notifications on the token will not
+ * have any effect.
+ *
+ * This MUST be invoked when forwarding {@link Sender#onForget}, otherwise the token and
+ * {@link CancellationSignal} will leak if the token was ever {@link #unbeam}ed.
+ *
+ * Optionally, the receiving service logic may also invoke this if it can guarantee that
+ * the unbeamed CancellationSignal isn't needed anymore (i.e. the cancellable operation
+ * using the CancellationSignal has been fully completed).
+ *
+ * @param token the token to forget. No-op if {@code null}.
+ */
+ public void forget(@Nullable IBinder token) {
+ synchronized (this) {
+ if (mTokenMap.remove(token) != null) {
+ token.unlinkToDeath(this, 0);
+ }
+ }
+ }
+
+ /**
+ * Cancels the {@link CancellationSignal} associated with the given token (if any).
+ *
+ * This MUST be invoked when forwarding {@link Sender#onCancel}, otherwise the token and
+ * {@link CancellationSignal} will leak if the token was ever {@link #unbeam}ed.
+ *
+ * Optionally, the receiving service logic may also invoke this if it can guarantee that
+ * the unbeamed CancellationSignal isn't needed anymore (i.e. the cancellable operation
+ * using the CancellationSignal has been fully completed).
+ *
+ * @param token the token to forget. No-op if {@code null}.
+ */
+ public void cancel(@Nullable IBinder token) {
+ CancellationSignal cs;
+ synchronized (this) {
+ cs = mTokenMap.get(token);
+ if (cs != null) {
+ forget(token);
+ } else {
+ return;
+ }
+ }
+ cs.cancel();
+ }
+
+ private void dead(@NonNull IBinder token) {
+ if (mCancelOnSenderDeath) {
+ cancel(token);
+ } else {
+ forget(token);
+ }
+ }
+
+ @Override
+ public void binderDied(@NonNull IBinder who) {
+ dead(who);
+ }
+
+ @Override
+ public void binderDied() {
+ throw new RuntimeException("unreachable");
+ }
+ }
+}
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 3cf3ea234d30..fcebb455d09d 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -117,6 +117,7 @@ interface IUserManager {
boolean someUserHasAccount(in String accountName, in String accountType);
String getProfileType(int userId);
boolean isDemoUser(int userId);
+ boolean isAdminUser(int userId);
boolean isPreCreated(int userId);
UserInfo createProfileForUserEvenWhenDisallowedWithThrow(in String name, in String userType, int flags,
int userId, in String[] disallowedPackages);
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index bbf7f810b3c0..290f929d699a 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1641,6 +1641,7 @@ public class UserManager {
DISALLOW_ADD_WIFI_CONFIG,
DISALLOW_CELLULAR_2G,
DISALLOW_ULTRA_WIDEBAND_RADIO,
+ DISALLOW_GRANT_ADMIN,
})
@Retention(RetentionPolicy.SOURCE)
public @interface UserRestrictionKey {}
@@ -2432,21 +2433,24 @@ public class UserManager {
}
/**
- * Used to check if the context user is an admin user. An admin user is allowed to
+ * Used to check if the context user is an admin user. An admin user may be allowed to
* modify or configure certain settings that aren't available to non-admin users,
* create and delete additional users, etc. There can be more than one admin users.
*
* @return whether the context user is an admin user.
- * @hide
*/
- @SystemApi
- @RequiresPermission(anyOf = {
- Manifest.permission.MANAGE_USERS,
- Manifest.permission.CREATE_USERS,
- Manifest.permission.QUERY_USERS})
- @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU)
+ @UserHandleAware(
+ enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU,
+ requiresAnyOfPermissionsIfNotCallerProfileGroup = {
+ Manifest.permission.MANAGE_USERS,
+ Manifest.permission.CREATE_USERS,
+ Manifest.permission.QUERY_USERS})
public boolean isAdminUser() {
- return isUserAdmin(getContextUserIfAppropriate());
+ try {
+ return mService.isAdminUser(getContextUserIfAppropriate());
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
}
/**
@@ -3056,6 +3060,7 @@ public class UserManager {
*
* @hide
*/
+ @TestApi
public int getDisplayIdAssignedToUser() {
try {
return mService.getDisplayIdAssignedToUser();
@@ -3970,6 +3975,9 @@ public class UserManager {
* time, the preferred user name and account information are used by the setup process for that
* user.
*
+ * This API should only be called if the current user is an {@link #isAdminUser() admin} user,
+ * as otherwise the returned intent will not be able to create a user.
+ *
* @param userName Optional name to assign to the user.
* @param accountName Optional account name that will be used by the setup wizard to initialize
* the user.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 54e4909c12af..ef007746a67f 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -99,7 +99,6 @@ import android.widget.Editor;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
-import com.android.internal.widget.ILockSettings;
import java.io.IOException;
import java.lang.annotation.ElementType;
@@ -116,6 +115,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Executor;
+import java.util.function.Consumer;
/**
* The Settings provider contains global system-level device preferences.
@@ -2978,19 +2978,22 @@ public final class Settings {
}
private static final class GenerationTracker {
- private final MemoryIntArray mArray;
- private final Runnable mErrorHandler;
+ @NonNull private final String mName;
+ @NonNull private final MemoryIntArray mArray;
+ @NonNull private final Consumer<String> mErrorHandler;
private final int mIndex;
private int mCurrentGeneration;
- public GenerationTracker(@NonNull MemoryIntArray array, int index,
- int generation, Runnable errorHandler) {
+ GenerationTracker(@NonNull String name, @NonNull MemoryIntArray array, int index,
+ int generation, Consumer<String> errorHandler) {
+ mName = name;
mArray = array;
mIndex = index;
mErrorHandler = errorHandler;
mCurrentGeneration = generation;
}
+ // This method also updates the obsolete generation code stored locally
public boolean isGenerationChanged() {
final int currentGeneration = readCurrentGeneration();
if (currentGeneration >= 0) {
@@ -3011,9 +3014,7 @@ public final class Settings {
return mArray.get(mIndex);
} catch (IOException e) {
Log.e(TAG, "Error getting current generation", e);
- if (mErrorHandler != null) {
- mErrorHandler.run();
- }
+ mErrorHandler.accept(mName);
}
return -1;
}
@@ -3023,9 +3024,6 @@ public final class Settings {
mArray.close();
} catch (IOException e) {
Log.e(TAG, "Error closing backing array", e);
- if (mErrorHandler != null) {
- mErrorHandler.run();
- }
}
}
}
@@ -3088,8 +3086,21 @@ public final class Settings {
private final ArraySet<String> mAllFields;
private final ArrayMap<String, Integer> mReadableFieldsWithMaxTargetSdk;
+ // Mapping from the name of a setting (or the prefix of a namespace) to a generation tracker
@GuardedBy("this")
- private GenerationTracker mGenerationTracker;
+ private ArrayMap<String, GenerationTracker> mGenerationTrackers = new ArrayMap<>();
+
+ private Consumer<String> mGenerationTrackerErrorHandler = (String name) -> {
+ synchronized (NameValueCache.this) {
+ Log.e(TAG, "Error accessing generation tracker - removing");
+ final GenerationTracker tracker = mGenerationTrackers.get(name);
+ if (tracker != null) {
+ tracker.destroy();
+ mGenerationTrackers.remove(name);
+ }
+ mValues.remove(name);
+ }
+ };
<T extends NameValueTable> NameValueCache(Uri uri, String getCommand,
String setCommand, String deleteCommand, ContentProviderHolder providerHolder,
@@ -3178,6 +3189,43 @@ public final class Settings {
@UnsupportedAppUsage
public String getStringForUser(ContentResolver cr, String name, final int userHandle) {
+ final boolean isSelf = (userHandle == UserHandle.myUserId());
+ int currentGeneration = -1;
+ boolean needsGenerationTracker = false;
+
+ if (isSelf) {
+ synchronized (NameValueCache.this) {
+ final GenerationTracker generationTracker = mGenerationTrackers.get(name);
+ if (generationTracker != null) {
+ if (generationTracker.isGenerationChanged()) {
+ if (DEBUG) {
+ Log.i(TAG, "Generation changed for setting:" + name
+ + " type:" + mUri.getPath()
+ + " in package:" + cr.getPackageName()
+ + " and user:" + userHandle);
+ }
+ mValues.remove(name);
+ } else if (mValues.containsKey(name)) {
+ if (DEBUG) {
+ Log.i(TAG, "Cache hit for setting:" + name);
+ }
+ return mValues.get(name);
+ }
+ currentGeneration = generationTracker.getCurrentGeneration();
+ } else {
+ needsGenerationTracker = true;
+ }
+ }
+ } else {
+ if (DEBUG || LOCAL_LOGV) {
+ Log.v(TAG, "get setting for user " + userHandle
+ + " by user " + UserHandle.myUserId() + " so skipping cache");
+ }
+ }
+ if (DEBUG) {
+ Log.i(TAG, "Cache miss for setting:" + name + " for user:" + userHandle);
+ }
+
// Check if the target settings key is readable. Reject if the caller is not system and
// is trying to access a settings key defined in the Settings.Secure, Settings.System or
// Settings.Global and is not annotated as @Readable.
@@ -3211,31 +3259,6 @@ public final class Settings {
}
}
- final boolean isSelf = (userHandle == UserHandle.myUserId());
- int currentGeneration = -1;
- if (isSelf) {
- synchronized (NameValueCache.this) {
- if (mGenerationTracker != null) {
- if (mGenerationTracker.isGenerationChanged()) {
- if (DEBUG) {
- Log.i(TAG, "Generation changed for type:"
- + mUri.getPath() + " in package:"
- + cr.getPackageName() +" and user:" + userHandle);
- }
- mValues.clear();
- } else if (mValues.containsKey(name)) {
- return mValues.get(name);
- }
- if (mGenerationTracker != null) {
- currentGeneration = mGenerationTracker.getCurrentGeneration();
- }
- }
- }
- } else {
- if (LOCAL_LOGV) Log.v(TAG, "get setting for user " + userHandle
- + " by user " + UserHandle.myUserId() + " so skipping cache");
- }
-
IContentProvider cp = mProviderHolder.getProvider(cr);
// Try the fast path first, not using query(). If this
@@ -3244,24 +3267,17 @@ public final class Settings {
// interface.
if (mCallGetCommand != null) {
try {
- Bundle args = null;
+ Bundle args = new Bundle();
if (!isSelf) {
- args = new Bundle();
args.putInt(CALL_METHOD_USER_KEY, userHandle);
}
- boolean needsGenerationTracker = false;
- synchronized (NameValueCache.this) {
- if (isSelf && mGenerationTracker == null) {
- needsGenerationTracker = true;
- if (args == null) {
- args = new Bundle();
- }
- args.putString(CALL_METHOD_TRACK_GENERATION_KEY, null);
- if (DEBUG) {
- Log.i(TAG, "Requested generation tracker for type: "+ mUri.getPath()
- + " in package:" + cr.getPackageName() +" and user:"
- + userHandle);
- }
+ if (needsGenerationTracker) {
+ args.putString(CALL_METHOD_TRACK_GENERATION_KEY, null);
+ if (DEBUG) {
+ Log.i(TAG, "Requested generation tracker for setting:" + name
+ + " type:" + mUri.getPath()
+ + " in package:" + cr.getPackageName()
+ + " and user:" + userHandle);
}
}
Bundle b;
@@ -3298,33 +3314,24 @@ public final class Settings {
final int generation = b.getInt(
CALL_METHOD_GENERATION_KEY, 0);
if (DEBUG) {
- Log.i(TAG, "Received generation tracker for type:"
- + mUri.getPath() + " in package:"
- + cr.getPackageName() + " and user:"
- + userHandle + " with index:" + index);
+ Log.i(TAG, "Received generation tracker for setting:"
+ + name
+ + " type:" + mUri.getPath()
+ + " in package:" + cr.getPackageName()
+ + " and user:" + userHandle
+ + " with index:" + index);
}
- if (mGenerationTracker != null) {
- mGenerationTracker.destroy();
- }
- mGenerationTracker = new GenerationTracker(array, index,
- generation, () -> {
- synchronized (NameValueCache.this) {
- Log.e(TAG, "Error accessing generation"
- + " tracker - removing");
- if (mGenerationTracker != null) {
- GenerationTracker generationTracker =
- mGenerationTracker;
- mGenerationTracker = null;
- generationTracker.destroy();
- mValues.clear();
- }
- }
- });
+ mGenerationTrackers.put(name, new GenerationTracker(name,
+ array, index, generation,
+ mGenerationTrackerErrorHandler));
currentGeneration = generation;
}
}
- if (mGenerationTracker != null && currentGeneration ==
- mGenerationTracker.getCurrentGeneration()) {
+ if (mGenerationTrackers.get(name) != null && currentGeneration
+ == mGenerationTrackers.get(name).getCurrentGeneration()) {
+ if (DEBUG) {
+ Log.i(TAG, "Updating cache for setting:" + name);
+ }
mValues.put(name, value);
}
}
@@ -3367,15 +3374,14 @@ public final class Settings {
String value = c.moveToNext() ? c.getString(0) : null;
synchronized (NameValueCache.this) {
- if (mGenerationTracker != null
- && currentGeneration == mGenerationTracker.getCurrentGeneration()) {
+ if (mGenerationTrackers.get(name) != null && currentGeneration
+ == mGenerationTrackers.get(name).getCurrentGeneration()) {
+ if (DEBUG) {
+ Log.i(TAG, "Updating cache for setting:" + name + " using query");
+ }
mValues.put(name, value);
}
}
- if (LOCAL_LOGV) {
- Log.v(TAG, "cache miss [" + mUri.getLastPathSegment() + "]: " +
- name + " = " + (value == null ? "(null)" : value));
- }
return value;
} catch (RemoteException e) {
Log.w(TAG, "Can't get key " + name + " from " + mUri, e);
@@ -3409,18 +3415,29 @@ public final class Settings {
Config.enforceReadPermission(namespace);
ArrayMap<String, String> keyValues = new ArrayMap<>();
int currentGeneration = -1;
+ boolean needsGenerationTracker = false;
synchronized (NameValueCache.this) {
- if (mGenerationTracker != null) {
- if (mGenerationTracker.isGenerationChanged()) {
+ final GenerationTracker generationTracker = mGenerationTrackers.get(prefix);
+ if (generationTracker != null) {
+ if (generationTracker.isGenerationChanged()) {
if (DEBUG) {
- Log.i(TAG, "Generation changed for type:" + mUri.getPath()
+ Log.i(TAG, "Generation changed for prefix:" + prefix
+ + " type:" + mUri.getPath()
+ " in package:" + cr.getPackageName());
}
- mValues.clear();
+ for (int i = 0; i < mValues.size(); ++i) {
+ String key = mValues.keyAt(i);
+ if (key.startsWith(prefix)) {
+ mValues.remove(key);
+ }
+ }
} else {
boolean prefixCached = mValues.containsKey(prefix);
if (prefixCached) {
+ if (DEBUG) {
+ Log.i(TAG, "Cache hit for prefix:" + prefix);
+ }
if (!names.isEmpty()) {
for (String name : names) {
if (mValues.containsKey(name)) {
@@ -3440,9 +3457,9 @@ public final class Settings {
return keyValues;
}
}
- if (mGenerationTracker != null) {
- currentGeneration = mGenerationTracker.getCurrentGeneration();
- }
+ currentGeneration = generationTracker.getCurrentGeneration();
+ } else {
+ needsGenerationTracker = true;
}
}
@@ -3450,20 +3467,20 @@ public final class Settings {
// No list command specified, return empty map
return keyValues;
}
+ if (DEBUG) {
+ Log.i(TAG, "Cache miss for prefix:" + prefix);
+ }
IContentProvider cp = mProviderHolder.getProvider(cr);
try {
Bundle args = new Bundle();
args.putString(Settings.CALL_METHOD_PREFIX_KEY, prefix);
- boolean needsGenerationTracker = false;
- synchronized (NameValueCache.this) {
- if (mGenerationTracker == null) {
- needsGenerationTracker = true;
- args.putString(CALL_METHOD_TRACK_GENERATION_KEY, null);
- if (DEBUG) {
- Log.i(TAG, "Requested generation tracker for type: "
- + mUri.getPath() + " in package:" + cr.getPackageName());
- }
+ if (needsGenerationTracker) {
+ args.putString(CALL_METHOD_TRACK_GENERATION_KEY, null);
+ if (DEBUG) {
+ Log.i(TAG, "Requested generation tracker for prefix:" + prefix
+ + " type: " + mUri.getPath()
+ + " in package:" + cr.getPackageName());
}
}
@@ -3516,32 +3533,22 @@ public final class Settings {
final int generation = b.getInt(
CALL_METHOD_GENERATION_KEY, 0);
if (DEBUG) {
- Log.i(TAG, "Received generation tracker for type:"
- + mUri.getPath() + " in package:"
- + cr.getPackageName() + " with index:" + index);
- }
- if (mGenerationTracker != null) {
- mGenerationTracker.destroy();
+ Log.i(TAG, "Received generation tracker for prefix:" + prefix
+ + " type:" + mUri.getPath()
+ + " in package:" + cr.getPackageName()
+ + " with index:" + index);
}
- mGenerationTracker = new GenerationTracker(array, index,
- generation, () -> {
- synchronized (NameValueCache.this) {
- Log.e(TAG, "Error accessing generation tracker"
- + " - removing");
- if (mGenerationTracker != null) {
- GenerationTracker generationTracker =
- mGenerationTracker;
- mGenerationTracker = null;
- generationTracker.destroy();
- mValues.clear();
- }
- }
- });
+ mGenerationTrackers.put(prefix,
+ new GenerationTracker(prefix, array, index, generation,
+ mGenerationTrackerErrorHandler));
currentGeneration = generation;
}
}
- if (mGenerationTracker != null && currentGeneration
- == mGenerationTracker.getCurrentGeneration()) {
+ if (mGenerationTrackers.get(prefix) != null && currentGeneration
+ == mGenerationTrackers.get(prefix).getCurrentGeneration()) {
+ if (DEBUG) {
+ Log.i(TAG, "Updating cache for prefix:" + prefix);
+ }
// cache the complete list of flags for the namespace
mValues.putAll(flagsToValues);
// Adding the prefix as a signal that the prefix is cached.
@@ -3557,11 +3564,11 @@ public final class Settings {
public void clearGenerationTrackerForTest() {
synchronized (NameValueCache.this) {
- if (mGenerationTracker != null) {
- mGenerationTracker.destroy();
+ for (int i = 0; i < mGenerationTrackers.size(); i++) {
+ mGenerationTrackers.valueAt(i).destroy();
}
+ mGenerationTrackers.clear();
mValues.clear();
- mGenerationTracker = null;
}
}
}
@@ -6184,9 +6191,6 @@ public final class Settings {
sProviderHolder,
Secure.class);
- private static ILockSettings sLockSettings = null;
-
- private static boolean sIsSystemProcess;
@UnsupportedAppUsage
private static final HashSet<String> MOVED_TO_LOCK_SETTINGS;
@UnsupportedAppUsage
@@ -6350,35 +6354,25 @@ public final class Settings {
return Global.getStringForUser(resolver, name, userHandle);
}
- if (MOVED_TO_LOCK_SETTINGS.contains(name)) {
- synchronized (Secure.class) {
- if (sLockSettings == null) {
- sLockSettings = ILockSettings.Stub.asInterface(
- (IBinder) ServiceManager.getService("lock_settings"));
- sIsSystemProcess = Process.myUid() == Process.SYSTEM_UID;
- }
- }
- if (sLockSettings != null && !sIsSystemProcess) {
- // No context; use the ActivityThread's context as an approximation for
- // determining the target API level.
- Application application = ActivityThread.currentApplication();
-
- boolean isPreMnc = application != null
- && application.getApplicationInfo() != null
- && application.getApplicationInfo().targetSdkVersion
- <= VERSION_CODES.LOLLIPOP_MR1;
- if (isPreMnc) {
- try {
- return sLockSettings.getString(name, "0", userHandle);
- } catch (RemoteException re) {
- // Fall through
- }
- } else {
- throw new SecurityException("Settings.Secure." + name
- + " is deprecated and no longer accessible."
- + " See API documentation for potential replacements.");
- }
+ if (MOVED_TO_LOCK_SETTINGS.contains(name) && Process.myUid() != Process.SYSTEM_UID) {
+ // No context; use the ActivityThread's context as an approximation for
+ // determining the target API level.
+ Application application = ActivityThread.currentApplication();
+
+ boolean isPreMnc = application != null
+ && application.getApplicationInfo() != null
+ && application.getApplicationInfo().targetSdkVersion
+ <= VERSION_CODES.LOLLIPOP_MR1;
+ if (isPreMnc) {
+ // Old apps used to get the three deprecated LOCK_PATTERN_* settings from
+ // ILockSettings.getString(). For security reasons, we now just return a
+ // stubbed-out value. Note: the only one of these three settings actually known
+ // to have been used was LOCK_PATTERN_ENABLED, and ILockSettings.getString()
+ // already always returned "0" for that starting in Android 11.
+ return "0";
}
+ throw new SecurityException("Settings.Secure." + name + " is deprecated and no" +
+ " longer accessible. See API documentation for potential replacements.");
}
return sNameValueCache.getStringForUser(resolver, name, userHandle);
@@ -8295,6 +8289,15 @@ public final class Settings {
"accessibility_display_inversion_enabled";
/**
+ * Flag that specifies whether font size has been changed. The flag will
+ * be set when users change the scaled value of font size for the first time.
+ * @hide
+ */
+ @Readable
+ public static final String ACCESSIBILITY_FONT_SCALING_HAS_BEEN_CHANGED =
+ "accessibility_font_scaling_has_been_changed";
+
+ /**
* Setting that specifies whether display color space adjustment is
* enabled.
*
@@ -10784,6 +10787,15 @@ public final class Settings {
"low_power_warning_acknowledged";
/**
+ * Whether the "first time extra battery saver warning" dialog needs to be shown
+ * (0: default) or not (1).
+ *
+ * @hide
+ */
+ public static final String EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED =
+ "extra_low_power_warning_acknowledged";
+
+ /**
* 0 (default) Auto battery saver suggestion has not been suppressed. 1) it has been
* suppressed.
* @hide
@@ -15199,6 +15211,12 @@ public final class Settings {
public static final String LOW_POWER_MODE = "low_power";
/**
+ * If 1 extra low power mode is enabled.
+ * @hide
+ */
+ public static final String EXTRA_LOW_POWER_MODE = "extra_low_power";
+
+ /**
* If 1, battery saver ({@link #LOW_POWER_MODE}) will be re-activated after the device
* is unplugged from a charger or rebooted.
* @hide
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 6896e0244791..d14abfd5d7ae 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -4937,4 +4937,66 @@ public final class Telephony {
return ALL_COLUMNS;
}
}
+
+ /**
+ * Stores incoming satellite datagrams.
+ * @hide
+ */
+ public static final class SatelliteDatagrams {
+ /**
+ * Not instantiable.
+ * @hide
+ */
+ private SatelliteDatagrams() {}
+
+ /**
+ * Provider name for Satellite Datagrams table.
+ */
+ public static final String PROVIDER_NAME = "satellite";
+
+ /**
+ * Table name for Satellite Datagrams table.
+ */
+ public static final String TABLE_NAME = "incoming_datagrams";
+
+ /**
+ * URL for satellite incoming datagrams table.
+ */
+ private static final String URL = "content://" + PROVIDER_NAME + "/" + TABLE_NAME;
+
+ /**
+ * The {@code content://} style URI for this provider.
+ * @hide
+ */
+ public static final Uri CONTENT_URI = Uri.parse(URL);
+
+ /**
+ * SatelliteProvider unique key column name is the datagram id.
+ * <P>Type: INTEGER (int)</P>
+ * @hide
+ */
+ public static final String COLUMN_UNIQUE_KEY_DATAGRAM_ID = "datagram_id";
+
+ /**
+ * SatelliteProvider column name for storing datagram.
+ * <p>TYPE: BLOB
+ * @hide
+ */
+ public static final String COLUMN_DATAGRAM = "datagram";
+
+ /** All columns in {@link SatelliteDatagrams} table. */
+ private static final List<String> ALL_COLUMNS = List.of(
+ COLUMN_UNIQUE_KEY_DATAGRAM_ID,
+ COLUMN_DATAGRAM
+ );
+
+ /**
+ * @return All columns in {@link SatelliteDatagrams} table.
+ * @hide
+ */
+ @NonNull
+ public static List<String> getAllColumns() {
+ return ALL_COLUMNS;
+ }
+ }
}
diff --git a/core/java/android/service/autofill/FillEventHistory.java b/core/java/android/service/autofill/FillEventHistory.java
index b0e847cd53f9..5d58120ef5bb 100644
--- a/core/java/android/service/autofill/FillEventHistory.java
+++ b/core/java/android/service/autofill/FillEventHistory.java
@@ -233,6 +233,22 @@ public final class FillEventHistory implements Parcelable {
*/
public static final int TYPE_DATASETS_SHOWN = 5;
+ /**
+ * The app/user requested for a field to be Autofilled.
+ *
+ * This event is fired when the view has been entered (by user or app) in order
+ * to differentiate from FillRequests that have been pretriggered for FillDialogs.
+ *
+ * For example, the user might navigate away from a screen without tapping any
+ * fields. In this case, a FillRequest/FillResponse has been generated, but was
+ * not used for Autofilling. The user did not intend to see an Autofill result,
+ * but a FillRequest was still generated. This is different from when the user
+ * did tap on a field after the pretriggered FillRequest, this event will appear
+ * in the FillEventHistory, signaling that the user did intend to Autofill
+ * something.
+ */
+ public static final int TYPE_VIEW_REQUESTED_AUTOFILL = 6;
+
/** @hide */
@IntDef(prefix = { "TYPE_" }, value = {
TYPE_DATASET_SELECTED,
@@ -240,7 +256,8 @@ public final class FillEventHistory implements Parcelable {
TYPE_AUTHENTICATION_SELECTED,
TYPE_SAVE_SHOWN,
TYPE_CONTEXT_COMMITTED,
- TYPE_DATASETS_SHOWN
+ TYPE_DATASETS_SHOWN,
+ TYPE_VIEW_REQUESTED_AUTOFILL
})
@Retention(RetentionPolicy.SOURCE)
@interface EventIds{}
@@ -659,8 +676,8 @@ public final class FillEventHistory implements Parcelable {
@Nullable AutofillId[] detectedFieldIds,
@Nullable FieldClassification[] detectedFieldClassifications,
int saveDialogNotShowReason, int uiType) {
- mEventType = Preconditions.checkArgumentInRange(eventType, 0, TYPE_DATASETS_SHOWN,
- "eventType");
+ mEventType = Preconditions.checkArgumentInRange(eventType, 0,
+ TYPE_VIEW_REQUESTED_AUTOFILL, "eventType");
mDatasetId = datasetId;
mClientState = clientState;
mSelectedDatasetIds = selectedDatasetIds;
@@ -723,6 +740,8 @@ public final class FillEventHistory implements Parcelable {
return "TYPE_CONTEXT_COMMITTED";
case TYPE_DATASETS_SHOWN:
return "TYPE_DATASETS_SHOWN";
+ case TYPE_VIEW_REQUESTED_AUTOFILL:
+ return "TYPE_VIEW_REQUESTED_AUTOFILL";
default:
return "TYPE_UNKNOWN";
}
diff --git a/core/java/android/service/credentials/BeginCreateCredentialResponse.java b/core/java/android/service/credentials/BeginCreateCredentialResponse.java
index f0f954dda182..eebd31c6fa96 100644
--- a/core/java/android/service/credentials/BeginCreateCredentialResponse.java
+++ b/core/java/android/service/credentials/BeginCreateCredentialResponse.java
@@ -32,7 +32,7 @@ import java.util.Objects;
*/
public final class BeginCreateCredentialResponse implements Parcelable {
private final @NonNull List<CreateEntry> mCreateEntries;
- private final @Nullable CreateEntry mRemoteCreateEntry;
+ private final @Nullable RemoteEntry mRemoteCreateEntry;
/**
* Creates an empty response instance, to be used when there are no {@link CreateEntry}
@@ -46,7 +46,7 @@ public final class BeginCreateCredentialResponse implements Parcelable {
List<CreateEntry> createEntries = new ArrayList<>();
in.readTypedList(createEntries, CreateEntry.CREATOR);
mCreateEntries = createEntries;
- mRemoteCreateEntry = in.readTypedObject(CreateEntry.CREATOR);
+ mRemoteCreateEntry = in.readTypedObject(RemoteEntry.CREATOR);
}
@Override
@@ -75,7 +75,7 @@ public final class BeginCreateCredentialResponse implements Parcelable {
/* package-private */ BeginCreateCredentialResponse(
@NonNull List<CreateEntry> createEntries,
- @Nullable CreateEntry remoteCreateEntry) {
+ @Nullable RemoteEntry remoteCreateEntry) {
this.mCreateEntries = createEntries;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mCreateEntries);
@@ -88,7 +88,7 @@ public final class BeginCreateCredentialResponse implements Parcelable {
}
/** Returns the remote create entry to be displayed on the UI. */
- public @Nullable CreateEntry getRemoteCreateEntry() {
+ public @Nullable RemoteEntry getRemoteCreateEntry() {
return mRemoteCreateEntry;
}
@@ -98,7 +98,7 @@ public final class BeginCreateCredentialResponse implements Parcelable {
@SuppressWarnings("WeakerAccess") /* synthetic access */
public static final class Builder {
private @NonNull List<CreateEntry> mCreateEntries = new ArrayList<>();
- private @Nullable CreateEntry mRemoteCreateEntry;
+ private @Nullable RemoteEntry mRemoteCreateEntry;
/**
* Sets the list of create entries to be shown on the UI.
@@ -138,7 +138,7 @@ public final class BeginCreateCredentialResponse implements Parcelable {
* {@link CredentialProviderService#EXTRA_CREATE_CREDENTIAL_RESPONSE} key should be populated
* with a {@link android.credentials.CreateCredentialResponse} object.
*/
- public @NonNull Builder setRemoteCreateEntry(@Nullable CreateEntry remoteCreateEntry) {
+ public @NonNull Builder setRemoteCreateEntry(@Nullable RemoteEntry remoteCreateEntry) {
mRemoteCreateEntry = remoteCreateEntry;
return this;
}
diff --git a/core/java/android/service/credentials/BeginGetCredentialOption.java b/core/java/android/service/credentials/BeginGetCredentialOption.java
index 81b9f22ebc7f..1ad0424f44e3 100644
--- a/core/java/android/service/credentials/BeginGetCredentialOption.java
+++ b/core/java/android/service/credentials/BeginGetCredentialOption.java
@@ -116,12 +116,12 @@ public class BeginGetCredentialOption implements Parcelable {
* @param id the unique id associated with this option
* @param type the requested credential type
* @param candidateQueryData the request candidateQueryData
- * @throws IllegalArgumentException If type is empty.
+ * @throws IllegalArgumentException If id or type is empty.
*/
public BeginGetCredentialOption(
@NonNull String id, @NonNull String type,
@NonNull Bundle candidateQueryData) {
- mId = id;
+ mId = Preconditions.checkStringNotEmpty(id, "id must not be empty");
mType = Preconditions.checkStringNotEmpty(type, "type must not be empty");
Bundle bundle = new Bundle();
bundle.putAll(candidateQueryData);
diff --git a/core/java/android/service/credentials/BeginGetCredentialResponse.java b/core/java/android/service/credentials/BeginGetCredentialResponse.java
index 3652742d4ff4..97f5079393a0 100644
--- a/core/java/android/service/credentials/BeginGetCredentialResponse.java
+++ b/core/java/android/service/credentials/BeginGetCredentialResponse.java
@@ -42,7 +42,7 @@ public final class BeginGetCredentialResponse implements Parcelable {
private final @NonNull List<Action> mActions;
/** Remote credential entry to get the response from a different device. */
- private final @Nullable CredentialEntry mRemoteCredentialEntry;
+ private final @Nullable RemoteEntry mRemoteCredentialEntry;
/**
* Creates an empty response instance, to be used when there are no {@link CredentialEntry},
@@ -57,7 +57,7 @@ public final class BeginGetCredentialResponse implements Parcelable {
private BeginGetCredentialResponse(@NonNull List<CredentialEntry> credentialEntries,
@NonNull List<Action> authenticationEntries, @NonNull List<Action> actions,
- @Nullable CredentialEntry remoteCredentialEntry) {
+ @Nullable RemoteEntry remoteCredentialEntry) {
mCredentialEntries = new ArrayList<>(credentialEntries);
mAuthenticationEntries = new ArrayList<>(authenticationEntries);
mActions = new ArrayList<>(actions);
@@ -74,7 +74,7 @@ public final class BeginGetCredentialResponse implements Parcelable {
List<Action> actions = new ArrayList<>();
in.readTypedList(actions, Action.CREATOR);
mActions = actions;
- mRemoteCredentialEntry = in.readTypedObject(CredentialEntry.CREATOR);
+ mRemoteCredentialEntry = in.readTypedObject(RemoteEntry.CREATOR);
}
public static final @NonNull Creator<BeginGetCredentialResponse> CREATOR =
@@ -127,7 +127,7 @@ public final class BeginGetCredentialResponse implements Parcelable {
/**
* Returns the remote credential entry to be displayed on the UI.
*/
- public @Nullable CredentialEntry getRemoteCredentialEntry() {
+ public @Nullable RemoteEntry getRemoteCredentialEntry() {
return mRemoteCredentialEntry;
}
@@ -139,7 +139,7 @@ public final class BeginGetCredentialResponse implements Parcelable {
private List<Action> mAuthenticationEntries = new ArrayList<>();
private List<Action> mActions = new ArrayList<>();
- private CredentialEntry mRemoteCredentialEntry;
+ private RemoteEntry mRemoteCredentialEntry;
/**
* Sets a remote credential entry to be shown on the UI. Provider must set this if they
@@ -155,7 +155,7 @@ public final class BeginGetCredentialResponse implements Parcelable {
* {@link CredentialProviderService#EXTRA_GET_CREDENTIAL_RESPONSE} key should be populated
* with a {@link android.credentials.Credential} object.
*/
- public @NonNull Builder setRemoteCredentialEntry(@Nullable CredentialEntry
+ public @NonNull Builder setRemoteCredentialEntry(@Nullable RemoteEntry
remoteCredentialEntry) {
mRemoteCredentialEntry = remoteCredentialEntry;
return this;
diff --git a/core/java/android/service/credentials/CallingAppInfo.java b/core/java/android/service/credentials/CallingAppInfo.java
index fba91d457236..e755581638f5 100644
--- a/core/java/android/service/credentials/CallingAppInfo.java
+++ b/core/java/android/service/credentials/CallingAppInfo.java
@@ -17,6 +17,7 @@
package android.service.credentials;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.pm.SigningInfo;
import android.os.Parcel;
import android.os.Parcelable;
@@ -32,6 +33,8 @@ import java.util.Objects;
public final class CallingAppInfo implements Parcelable {
@NonNull private final String mPackageName;
@NonNull private final SigningInfo mSigningInfo;
+ @Nullable
+ private final String mOrigin;
/**
* Constructs a new instance.
@@ -41,14 +44,31 @@ public final class CallingAppInfo implements Parcelable {
*/
public CallingAppInfo(@NonNull String packageName,
@NonNull SigningInfo signingInfo) {
+ this(packageName, signingInfo, /*origin=*/ null);
+ }
+
+ /**
+ * Constructs a new instance.
+ *
+ * @param packageName - the package name of the calling app
+ * @param signingInfo - the signing info on the calling app
+ * @param origin - the origin that the calling app wants to use when making request on behalf of
+ * other
+ * @throws IllegalArgumentException If {@code packageName} is null or empty.
+ * @throws NullPointerException If {@code signingInfo} is null.
+ */
+ public CallingAppInfo(@NonNull String packageName,
+ @NonNull SigningInfo signingInfo, @Nullable String origin) {
mPackageName = Preconditions.checkStringNotEmpty(packageName, "package name"
+ "must not be null or empty");
mSigningInfo = Objects.requireNonNull(signingInfo);
+ mOrigin = origin;
}
private CallingAppInfo(@NonNull Parcel in) {
mPackageName = in.readString8();
mSigningInfo = in.readTypedObject(SigningInfo.CREATOR);
+ mOrigin = in.readString8();
}
public static final @NonNull Creator<CallingAppInfo> CREATOR = new Creator<CallingAppInfo>() {
@@ -76,6 +96,22 @@ public final class CallingAppInfo implements Parcelable {
return mSigningInfo;
}
+ /**
+ * Returns the origin of the calling app if set otherwise returns null.
+ * This value is set only if the origin is different than that of the calling app,
+ * and should be expected from privileged callers(browsers) only when making request on behalf
+ * of other applications.
+ *
+ * Android system makes sure that only applications that poses the permission
+ * {@link android.Manifest.permission.CREDENTIAL_MANAGER_SET_ORIGIN} can set the origin on
+ * the incoming {@link android.credentials.GetCredentialRequest} or
+ * {@link android.credentials.CreateCredentialRequest}.
+ */
+ @Nullable
+ public String getOrigin() {
+ return mOrigin;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -85,6 +121,7 @@ public final class CallingAppInfo implements Parcelable {
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString8(mPackageName);
dest.writeTypedObject(mSigningInfo, flags);
+ dest.writeString8(mOrigin);
}
@Override
@@ -97,6 +134,7 @@ public final class CallingAppInfo implements Parcelable {
} else {
builder.append(", mSigningInfo: null");
}
+ builder.append(",mOrigin: " + mOrigin);
builder.append(" }");
return builder.toString();
}
diff --git a/core/java/android/service/credentials/GetCredentialRequest.java b/core/java/android/service/credentials/GetCredentialRequest.java
index 4f13922caf15..5bad9abb2eed 100644
--- a/core/java/android/service/credentials/GetCredentialRequest.java
+++ b/core/java/android/service/credentials/GetCredentialRequest.java
@@ -23,14 +23,16 @@ import android.os.Parcelable;
import com.android.internal.util.AnnotationValidations;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Objects;
/**
* Request for getting user's credential from a given credential provider.
*
- * <p>Provider will receive this request once the user selects a given {@link CredentialEntry}
- * on the selector, that was sourced from provider's result to
- * {@link CredentialProviderService#onBeginGetCredential}.
+ * <p>A credential provider will receive this request once the user selects a
+ * given {@link CredentialEntry}, or {@link RemoteEntry} on the selector, that was sourced
+ * from provider's initial response to {@link CredentialProviderService#onBeginGetCredential}.
*/
public final class GetCredentialRequest implements Parcelable {
/** Calling package of the app requesting for credentials. */
@@ -38,24 +40,27 @@ public final class GetCredentialRequest implements Parcelable {
private final CallingAppInfo mCallingAppInfo;
/**
- * Holds parameters to be used for retrieving a specific type of credential.
+ * Holds a list of options (parameters) to be used for retrieving a specific type of credential.
*/
@NonNull
- private final CredentialOption mCredentialOption;
+ private final List<CredentialOption> mCredentialOptions;
public GetCredentialRequest(@NonNull CallingAppInfo callingAppInfo,
- @NonNull CredentialOption credentialOption) {
+ @NonNull List<CredentialOption> credentialOptions) {
this.mCallingAppInfo = Objects.requireNonNull(callingAppInfo,
"callingAppInfo must not be null");
- this.mCredentialOption = Objects.requireNonNull(credentialOption,
- "credentialOption must not be null");
+ this.mCredentialOptions = Objects.requireNonNull(credentialOptions,
+ "credentialOptions must not be null");
}
private GetCredentialRequest(@NonNull Parcel in) {
mCallingAppInfo = in.readTypedObject(CallingAppInfo.CREATOR);
AnnotationValidations.validate(NonNull.class, null, mCallingAppInfo);
- mCredentialOption = in.readTypedObject(CredentialOption.CREATOR);
- AnnotationValidations.validate(NonNull.class, null, mCredentialOption);
+
+ List<CredentialOption> credentialOptions = new ArrayList<>();
+ in.readTypedList(credentialOptions, CredentialOption.CREATOR);
+ mCredentialOptions = credentialOptions;
+ AnnotationValidations.validate(NonNull.class, null, mCredentialOptions);
}
@NonNull public static final Creator<GetCredentialRequest> CREATOR =
@@ -79,7 +84,7 @@ public final class GetCredentialRequest implements Parcelable {
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeTypedObject(mCallingAppInfo, flags);
- dest.writeTypedObject(mCredentialOption, flags);
+ dest.writeTypedList(mCredentialOptions, flags);
}
/**
@@ -91,10 +96,26 @@ public final class GetCredentialRequest implements Parcelable {
}
/**
- * Returns the parameters needed to return a given type of credential.
+ * Returns a list of options containing parameters needed to return a given type of credential.
+ * This is part of the request that the credential provider receives after the user has
+ * selected an entry on a selector UI.
+ *
+ * When the user selects a {@link CredentialEntry} and the credential provider receives a
+ * {@link GetCredentialRequest}, this list is expected to contain a single
+ * {@link CredentialOption} only. A {@link CredentialEntry} is always created for a given
+ * {@link BeginGetCredentialOption}, and hence when the user selects it, the provider
+ * receives a corresponding {@link CredentialOption} that contains all the required parameters
+ * to actually retrieve the credential.
+ *
+ * When the user selects a {@link RemoteEntry} and the credential provider receives a
+ * {@link GetCredentialRequest}, this list may contain greater than a single
+ * {@link CredentialOption}, representing the number of options specified by the developer
+ * in the original {@link android.credentials.GetCredentialRequest}. This is because a
+ * {@link RemoteEntry} indicates that the entire request will be processed on a different
+ * device and is not tied to a particular option.
*/
@NonNull
- public CredentialOption getCredentialOption() {
- return mCredentialOption;
+ public List<CredentialOption> getCredentialOptions() {
+ return mCredentialOptions;
}
}
diff --git a/core/java/android/service/credentials/RemoteEntry.java b/core/java/android/service/credentials/RemoteEntry.java
new file mode 100644
index 000000000000..716c00d726f3
--- /dev/null
+++ b/core/java/android/service/credentials/RemoteEntry.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.credentials;
+
+import android.annotation.NonNull;
+import android.annotation.SuppressLint;
+import android.app.PendingIntent;
+import android.app.slice.Slice;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * An entry to be shown on the UI. This entry represents remote execution of a get/create flow
+ * whereby credentials are retrieved from, or stored to a remote device.
+ *
+ * <p>If user selects this entry, the corresponding {@link PendingIntent} set on the
+ * {@code slice} as a {@link androidx.slice.core.SliceAction} will get invoked.
+ * Once the resulting activity fulfills the required user engagement,
+ * the {@link android.app.Activity} result should be set to {@link android.app.Activity#RESULT_OK},
+ * and the result of the operation must be set as the activity result.
+ *
+ * For a get flow, invoked through {@link CredentialProviderService#onBeginGetCredential},
+ * providers must set a {@link android.credentials.GetCredentialResponse} on the activity result,
+ * against the key {@link CredentialProviderService#EXTRA_GET_CREDENTIAL_RESPONSE}.
+ *
+ * For a creates flow, invoked through {@link CredentialProviderService#onBeginCreateCredential},
+ * providers must set a {@link android.credentials.CreateCredentialResponse} on the activity
+ * result against the ket {@link CredentialProviderService#EXTRA_CREATE_CREDENTIAL_RESPONSE}.
+ *
+ * <p>Any class that extends this class must only add extra field values to the {@code slice}
+ * object passed into the constructor. Any other field will not be parceled through. If the
+ * derived class has custom parceling implementation, this class will not be able to unpack
+ * the parcel without having access to that implementation.
+ */
+@SuppressLint("ParcelNotFinal")
+public class RemoteEntry implements Parcelable {
+ private final @NonNull Slice mSlice;
+
+ private RemoteEntry(@NonNull Parcel in) {
+ mSlice = in.readTypedObject(Slice.CREATOR);
+ }
+
+ @NonNull
+ public static final Creator<RemoteEntry> CREATOR = new Creator<RemoteEntry>() {
+ @Override
+ public RemoteEntry createFromParcel(@NonNull Parcel in) {
+ return new RemoteEntry(in);
+ }
+
+ @Override
+ public RemoteEntry[] newArray(int size) {
+ return new RemoteEntry[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeTypedObject(mSlice, flags);
+ }
+
+ /**
+ * Constructs a RemoteEntry to be displayed on the UI.
+ *
+ * @param slice the display content to be displayed on the UI, along with this entry
+ */
+ public RemoteEntry(
+ @NonNull Slice slice) {
+ this.mSlice = slice;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mSlice);
+ }
+
+ /** Returns the content to be displayed with this remote entry on the UI. */
+ @NonNull
+ public Slice getSlice() {
+ return mSlice;
+ }
+}
diff --git a/core/java/android/service/dreams/DreamActivity.java b/core/java/android/service/dreams/DreamActivity.java
index ff14404f787e..a3892238f1e6 100644
--- a/core/java/android/service/dreams/DreamActivity.java
+++ b/core/java/android/service/dreams/DreamActivity.java
@@ -70,7 +70,7 @@ public class DreamActivity extends Activity {
@Override
public void onDestroy() {
- if (mCallback != null && !isFinishing()) {
+ if (mCallback != null) {
mCallback.onActivityDestroyed();
}
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index d79ea8929047..c7099fdd202a 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -1588,7 +1588,8 @@ public class DreamService extends Service implements Window.Callback {
// If DreamActivity is destroyed, wake up from Dream.
void onActivityDestroyed() {
mActivity = null;
- onDestroy();
+ mWindow = null;
+ detach();
}
}
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index eb9901af315f..5c2b38963005 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -953,7 +953,7 @@ public class ZenModeConfig implements Parcelable {
private static Uri safeUri(TypedXmlPullParser parser, String att) {
final String val = parser.getAttributeValue(null, att);
- if (TextUtils.isEmpty(val)) return null;
+ if (val == null) return null;
return Uri.parse(val);
}
diff --git a/core/java/android/service/voice/AbstractDetector.java b/core/java/android/service/voice/AbstractDetector.java
index 466bc0520ee5..644a2bfa70bd 100644
--- a/core/java/android/service/voice/AbstractDetector.java
+++ b/core/java/android/service/voice/AbstractDetector.java
@@ -77,6 +77,13 @@ abstract class AbstractDetector implements HotwordDetector {
mIsDetectorActive = new AtomicBoolean(true);
}
+ boolean isSameToken(IBinder token) {
+ if (token == null) {
+ return false;
+ }
+ return mToken == token;
+ }
+
/**
* Method to be called for the detector to ready/register itself with underlying system
* services.
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index 50ac1f36099e..b1dc68605991 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -1707,6 +1707,13 @@ public class AlwaysOnHotwordDetector extends AbstractDetector {
}
}
+ void onDetectorRemoteException() {
+ Message.obtain(mHandler, MSG_DETECTION_ERROR,
+ new HotwordDetectionServiceFailure(
+ HotwordDetectionServiceFailure.ERROR_CODE_REMOTE_EXCEPTION,
+ "Detector remote exception occurs")).sendToTarget();
+ }
+
class MyHandler extends Handler {
MyHandler(@NonNull Looper looper) {
super(looper);
diff --git a/core/java/android/service/voice/HotwordDetectionService.java b/core/java/android/service/voice/HotwordDetectionService.java
index 0384454bb69c..d9ee859dc66b 100644
--- a/core/java/android/service/voice/HotwordDetectionService.java
+++ b/core/java/android/service/voice/HotwordDetectionService.java
@@ -72,7 +72,7 @@ import java.util.function.IntConsumer;
*/
@SystemApi
public abstract class HotwordDetectionService extends Service
- implements SandboxedDetectionServiceBase {
+ implements SandboxedDetectionInitializer {
private static final String TAG = "HotwordDetectionService";
private static final boolean DBG = false;
@@ -89,21 +89,23 @@ public abstract class HotwordDetectionService extends Service
/**
* Indicates that the updated status is successful.
*
- * @deprecated Replaced with {@link SandboxedDetectionServiceBase#INITIALIZATION_STATUS_SUCCESS}
+ * @deprecated Replaced with
+ * {@link SandboxedDetectionInitializer#INITIALIZATION_STATUS_SUCCESS}
*/
@Deprecated
public static final int INITIALIZATION_STATUS_SUCCESS =
- SandboxedDetectionServiceBase.INITIALIZATION_STATUS_SUCCESS;
+ SandboxedDetectionInitializer.INITIALIZATION_STATUS_SUCCESS;
/**
* Indicates that the callback wasn’t invoked within the timeout.
* This is used by system.
*
- * @deprecated Replaced with {@link SandboxedDetectionServiceBase#INITIALIZATION_STATUS_UNKNOWN}
+ * @deprecated Replaced with
+ * {@link SandboxedDetectionInitializer#INITIALIZATION_STATUS_UNKNOWN}
*/
@Deprecated
public static final int INITIALIZATION_STATUS_UNKNOWN =
- SandboxedDetectionServiceBase.INITIALIZATION_STATUS_UNKNOWN;
+ SandboxedDetectionInitializer.INITIALIZATION_STATUS_UNKNOWN;
/**
* Source for the given audio stream.
@@ -259,7 +261,7 @@ public abstract class HotwordDetectionService extends Service
*
* @hide
* @deprecated Replaced with
- * {@link SandboxedDetectionServiceBase#getMaxCustomInitializationStatus()}
+ * {@link SandboxedDetectionInitializer#getMaxCustomInitializationStatus()}
*/
@SystemApi
@Deprecated
@@ -368,7 +370,7 @@ public abstract class HotwordDetectionService extends Service
private void onUpdateStateInternal(@Nullable PersistableBundle options,
@Nullable SharedMemory sharedMemory, IRemoteCallback callback) {
IntConsumer intConsumer =
- SandboxedDetectionServiceBase.createInitializationStatusConsumer(callback);
+ SandboxedDetectionInitializer.createInitializationStatusConsumer(callback);
onUpdateState(options, sharedMemory, UPDATE_TIMEOUT_MILLIS, intConsumer);
}
diff --git a/core/java/android/service/voice/HotwordDetector.java b/core/java/android/service/voice/HotwordDetector.java
index 22d97b7bbcaa..93fcec14cf1c 100644
--- a/core/java/android/service/voice/HotwordDetector.java
+++ b/core/java/android/service/voice/HotwordDetector.java
@@ -283,9 +283,9 @@ public interface HotwordDetector {
*
* @param status Info about initialization state of {@link HotwordDetectionService} or
* {@link VisualQueryDetectionService}; allowed values are
- * {@link SandboxedDetectionServiceBase#INITIALIZATION_STATUS_SUCCESS},
- * 1<->{@link SandboxedDetectionServiceBase#getMaxCustomInitializationStatus()},
- * {@link SandboxedDetectionServiceBase#INITIALIZATION_STATUS_UNKNOWN}.
+ * {@link SandboxedDetectionInitializer#INITIALIZATION_STATUS_SUCCESS},
+ * 1<->{@link SandboxedDetectionInitializer#getMaxCustomInitializationStatus()},
+ * {@link SandboxedDetectionInitializer#INITIALIZATION_STATUS_UNKNOWN}.
*/
void onHotwordDetectionServiceInitialized(int status);
diff --git a/core/java/android/service/voice/IVoiceInteractionService.aidl b/core/java/android/service/voice/IVoiceInteractionService.aidl
index 6a5460605f32..491056e802e5 100644
--- a/core/java/android/service/voice/IVoiceInteractionService.aidl
+++ b/core/java/android/service/voice/IVoiceInteractionService.aidl
@@ -32,4 +32,5 @@ oneway interface IVoiceInteractionService {
in IVoiceActionCheckCallback callback);
void prepareToShowSession(in Bundle args, int flags);
void showSessionFailed(in Bundle args);
+ void detectorRemoteExceptionOccurred(in IBinder token, int detectorType);
}
diff --git a/core/java/android/service/voice/SandboxedDetectionServiceBase.java b/core/java/android/service/voice/SandboxedDetectionInitializer.java
index 43331642bd1e..4a41968395a7 100644
--- a/core/java/android/service/voice/SandboxedDetectionServiceBase.java
+++ b/core/java/android/service/voice/SandboxedDetectionInitializer.java
@@ -28,12 +28,12 @@ import android.os.SharedMemory;
import java.util.function.IntConsumer;
/**
- * Base for all sandboxed detection services, providing a common interface for initialization.
+ * Provides common initialzation methods for sandboxed detection services.
*
* @hide
*/
@SystemApi
-public interface SandboxedDetectionServiceBase {
+public interface SandboxedDetectionInitializer {
/**
* Indicates that the updated status is successful.
@@ -77,7 +77,7 @@ public interface SandboxedDetectionServiceBase {
if (callback != null) {
intConsumer =
value -> {
- if (value > SandboxedDetectionServiceBase
+ if (value > SandboxedDetectionInitializer
.getMaxCustomInitializationStatus()) {
throw new IllegalArgumentException(
"The initialization status is invalid for " + value);
diff --git a/core/java/android/service/voice/SoftwareHotwordDetector.java b/core/java/android/service/voice/SoftwareHotwordDetector.java
index d4b6f3bf5c4c..767fe378a30c 100644
--- a/core/java/android/service/voice/SoftwareHotwordDetector.java
+++ b/core/java/android/service/voice/SoftwareHotwordDetector.java
@@ -77,6 +77,13 @@ class SoftwareHotwordDetector extends AbstractDetector {
DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE);
}
+ void onDetectorRemoteException() {
+ Binder.withCleanCallingIdentity(() -> mExecutor.execute(() ->
+ mCallback.onFailure(new HotwordDetectionServiceFailure(
+ HotwordDetectionServiceFailure.ERROR_CODE_REMOTE_EXCEPTION,
+ "Detector remote exception occurs"))));
+ }
+
@RequiresPermission(RECORD_AUDIO)
@Override
public boolean startRecognition() throws IllegalDetectorStateException {
diff --git a/core/java/android/service/voice/VisualQueryDetectionService.java b/core/java/android/service/voice/VisualQueryDetectionService.java
index 2e455c2eeb29..cbe7666ddf43 100644
--- a/core/java/android/service/voice/VisualQueryDetectionService.java
+++ b/core/java/android/service/voice/VisualQueryDetectionService.java
@@ -20,9 +20,11 @@ import android.annotation.DurationMillisLong;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.app.Service;
import android.content.ContentCaptureOptions;
+import android.content.Context;
import android.content.Intent;
import android.hardware.soundtrigger.SoundTrigger;
import android.media.AudioFormat;
@@ -35,6 +37,7 @@ import android.os.RemoteException;
import android.os.SharedMemory;
import android.speech.IRecognitionServiceManager;
import android.util.Log;
+import android.view.contentcapture.ContentCaptureManager;
import android.view.contentcapture.IContentCaptureManager;
import java.util.Objects;
@@ -49,7 +52,7 @@ import java.util.function.IntConsumer;
* {@link VoiceInteractionService#createVisualQueryDetector(PersistableBundle, SharedMemory,
* Executor, VisualQueryDetector.Callback)} is called, the system will bind the application's
* {@link VisualQueryDetectionService}. When requested from {@link VoiceInteractionService}, the
- * system calls into the {@link VisualQueryDetectionService#onStartDetection(Callback)} to enable
+ * system calls into the {@link VisualQueryDetectionService#onStartDetection()} to enable
* detection. This method MUST be implemented to support visual query detection service.
*
* Note: Methods in this class may be called concurrently.
@@ -58,7 +61,7 @@ import java.util.function.IntConsumer;
*/
@SystemApi
public abstract class VisualQueryDetectionService extends Service
- implements SandboxedDetectionServiceBase {
+ implements SandboxedDetectionInitializer {
private static final String TAG = VisualQueryDetectionService.class.getSimpleName();
@@ -78,6 +81,12 @@ public abstract class VisualQueryDetectionService extends Service
/** @hide */
public static final String KEY_INITIALIZATION_STATUS = "initialization_status";
+ private IDetectorSessionVisualQueryDetectionCallback mRemoteCallback = null;
+ @Nullable
+ private ContentCaptureManager mContentCaptureManager;
+ @Nullable
+ private IRecognitionServiceManager mIRecognitionServiceManager;
+
private final ISandboxedDetectionService mInterface = new ISandboxedDetectionService.Stub() {
@@ -85,7 +94,8 @@ public abstract class VisualQueryDetectionService extends Service
public void detectWithVisualSignals(
IDetectorSessionVisualQueryDetectionCallback callback) {
Log.v(TAG, "#detectWithVisualSignals");
- VisualQueryDetectionService.this.onStartDetection(new Callback(callback));
+ mRemoteCallback = callback;
+ VisualQueryDetectionService.this.onStartDetection();
}
@Override
@@ -136,15 +146,29 @@ public abstract class VisualQueryDetectionService extends Service
@Override
public void updateContentCaptureManager(IContentCaptureManager manager,
ContentCaptureOptions options) {
- Log.v(TAG, "Ignore #updateContentCaptureManager");
+ mContentCaptureManager = new ContentCaptureManager(
+ VisualQueryDetectionService.this, manager, options);
}
@Override
public void updateRecognitionServiceManager(IRecognitionServiceManager manager) {
- Log.v(TAG, "Ignore #updateRecognitionServiceManager");
+ mIRecognitionServiceManager = manager;
}
};
+ @Override
+ @SuppressLint("OnNameExpected")
+ public @Nullable Object getSystemService(@ServiceName @NonNull String name) {
+ if (Context.CONTENT_CAPTURE_MANAGER_SERVICE.equals(name)) {
+ return mContentCaptureManager;
+ } else if (Context.SPEECH_RECOGNITION_SERVICE.equals(name)
+ && mIRecognitionServiceManager != null) {
+ return mIRecognitionServiceManager.asBinder();
+ } else {
+ return super.getSystemService(name);
+ }
+ }
+
/**
* {@inheritDoc}
* @hide
@@ -172,22 +196,47 @@ public abstract class VisualQueryDetectionService extends Service
private void onUpdateStateInternal(@Nullable PersistableBundle options,
@Nullable SharedMemory sharedMemory, IRemoteCallback callback) {
IntConsumer intConsumer =
- SandboxedDetectionServiceBase.createInitializationStatusConsumer(callback);
+ SandboxedDetectionInitializer.createInitializationStatusConsumer(callback);
onUpdateState(options, sharedMemory, UPDATE_TIMEOUT_MILLIS, intConsumer);
}
/**
* This is called after the service is set up and the client should open the camera and the
- * microphone to start recognition.
- *
- * Called when the {@link VoiceInteractionService} requests that this service
- * {@link HotwordDetector#startRecognition()} start recognition on audio coming directly
+ * microphone to start recognition. When the {@link VoiceInteractionService} requests that this
+ * service {@link HotwordDetector#startRecognition()} start recognition on audio coming directly
* from the device microphone.
- *
- * @param callback The callback to use for responding to the detection request.
- *
+ * <p>
+ * Signal senders that return attention and query results are also expected to be called in this
+ * method according to the detection outcomes.
+ * <p>
+ * On successful user attention, developers should call
+ * {@link VisualQueryDetectionService#gainedAttention()} to enable the streaming of the query.
+ * <p>
+ * On user attention is lost, developers should call
+ * {@link VisualQueryDetectionService#lostAttention()} to disable the streaming of the query.
+ * <p>
+ * On query is detected and ready to stream, developers should call
+ * {@link VisualQueryDetectionService#streamQuery(String)} to return detected query to the
+ * {@link VisualQueryDetector}.
+ * <p>
+ * On streamed query should be rejected, clients should call
+ * {@link VisualQueryDetectionService#rejectQuery()} to abandon query streamed to the
+ * {@link VisualQueryDetector}.
+ * <p>
+ * On streamed query is finished, clients should call
+ * {@link VisualQueryDetectionService#finishQuery()} to complete query streamed to
+ * {@link VisualQueryDetector}.
+ * <p>
+ * Before a call for {@link VisualQueryDetectionService#streamQuery(String)} is triggered,
+ * {@link VisualQueryDetectionService#gainedAttention()} MUST be called to enable the streaming
+ * of query. A query streaming is also expected to be finished by calling either
+ * {@link VisualQueryDetectionService#finishQuery()} or
+ * {@link VisualQueryDetectionService#rejectQuery()} before a new query should start streaming.
+ * When the service enters the state where query streaming should be disabled,
+ * {@link VisualQueryDetectionService#lostAttention()} MUST be called to block unnecessary
+ * streaming.
*/
- public void onStartDetection(@NonNull Callback callback) {
+ public void onStartDetection() {
throw new UnsupportedOperationException();
}
@@ -199,118 +248,78 @@ public abstract class VisualQueryDetectionService extends Service
}
/**
- * Callback for sending out signals and returning query results.
- *
- * On successful user attention, developers should call {@link Callback#onAttentionGained()}
- * to enable the streaming of the query.
- * <p>
- * On user attention is lost, developers should call {@link Callback#onAttentionLost()} to
- * disable the streaming of the query.
- * <p>
- * On query is detected and ready to stream, developers should call
- * {@link Callback#onQueryDetected(String)} to return detected query to the
- * {@link VisualQueryDetector}.
- * <p>
- * On streamed query should be rejected, clients should call {@link Callback#onQueryRejected()}
- * to abandon query streamed to the {@link VisualQueryDetector}.
- * <p>
- * On streamed query is finished, clients should call {@link Callback#onQueryFinished()} to
- * complete query streamed to {@link VisualQueryDetector}.
- * <p>
- * Before a call for {@link Callback#onQueryDetected(String)} is triggered,
- * {@link Callback#onAttentionGained()} MUST be called to enable the streaming of query. A query
- * streaming is also expected to be finished by calling either
- * {@link Callback#onQueryFinished()} or {@link Callback#onQueryRejected()} before a new query
- * should start streaming. When the service enters the state where query streaming should be
- * disabled, {@link Callback#onAttentionLost()} MUST be called to block unnecessary streaming.
+ * Informs the system that the user attention is gained so queries can be streamed.
*/
- public static final class Callback {
-
- // TODO: consider making the constructor a test api for testing purpose
- public Callback() {
- mRemoteCallback = null;
- }
-
- private final IDetectorSessionVisualQueryDetectionCallback mRemoteCallback;
-
- private Callback(IDetectorSessionVisualQueryDetectionCallback remoteCallback) {
- mRemoteCallback = remoteCallback;
- }
-
- /**
- * Informs attention listener that the user attention is gained.
- */
- public void onAttentionGained() {
- try {
- mRemoteCallback.onAttentionGained();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ public final void gainedAttention() {
+ try {
+ mRemoteCallback.onAttentionGained();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
+ }
- /**
- * Informs attention listener that the user attention is lost.
- */
- public void onAttentionLost() {
- try {
- mRemoteCallback.onAttentionLost();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ /**
+ * Informs the system that the user attention is lost to stop streaming.
+ */
+ public final void lostAttention() {
+ try {
+ mRemoteCallback.onAttentionLost();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
+ }
- /**
- * Informs the {@link VisualQueryDetector} with the text content being captured about the
- * query from the audio source. {@code partialQuery} is provided to the
- * {@link VisualQueryDetector}. This method is expected to be only triggered if
- * {@link Callback#onAttentionGained()} is called to put the service into the attention
- * gained state.
- *
- * @param partialQuery Partially detected query in string.
- * @throws IllegalStateException if method called without attention gained.
- */
- public void onQueryDetected(@NonNull String partialQuery) throws IllegalStateException {
- Objects.requireNonNull(partialQuery);
- try {
- mRemoteCallback.onQueryDetected(partialQuery);
- } catch (RemoteException e) {
- throw new IllegalStateException("#onQueryDetected must be only be triggered after "
- + "calling #onAttentionGained to be in the attention gained state.");
- }
+ /**
+ * Informs the {@link VisualQueryDetector} with the text content being captured about the
+ * query from the audio source. {@code partialQuery} is provided to the
+ * {@link VisualQueryDetector}. This method is expected to be only triggered if
+ * {@link VisualQueryDetectionService#gainedAttention()} is called to put the service into the
+ * attention gained state.
+ *
+ * @param partialQuery Partially detected query in string.
+ * @throws IllegalStateException if method called without attention gained.
+ */
+ public final void streamQuery(@NonNull String partialQuery) throws IllegalStateException {
+ Objects.requireNonNull(partialQuery);
+ try {
+ mRemoteCallback.onQueryDetected(partialQuery);
+ } catch (RemoteException e) {
+ throw new IllegalStateException("#streamQuery must be only be triggered after "
+ + "calling #gainedAttention to be in the attention gained state.");
}
+ }
- /**
- * Informs the {@link VisualQueryDetector} to abandon the streamed partial query that has
- * been sent to {@link VisualQueryDetector}.This method is expected to be only triggered if
- * {@link Callback#onQueryDetected()} is called to put the service into the query streaming
- * state.
- *
- * @throws IllegalStateException if method called without query streamed.
- */
- public void onQueryRejected() throws IllegalStateException {
- try {
- mRemoteCallback.onQueryRejected();
- } catch (RemoteException e) {
- throw new IllegalStateException("#onQueryRejected must be only be triggered after "
- + "calling #onQueryDetected to be in the query streaming state.");
- }
+ /**
+ * Informs the {@link VisualQueryDetector} to abandon the streamed partial query that has
+ * been sent to {@link VisualQueryDetector}.This method is expected to be only triggered if
+ * {@link VisualQueryDetectionService#streamQuery(String)} is called to put the service into
+ * the query streaming state.
+ *
+ * @throws IllegalStateException if method called without query streamed.
+ */
+ public final void rejectQuery() throws IllegalStateException {
+ try {
+ mRemoteCallback.onQueryRejected();
+ } catch (RemoteException e) {
+ throw new IllegalStateException("#rejectQuery must be only be triggered after "
+ + "calling #streamQuery to be in the query streaming state.");
}
+ }
- /**
- * Informs {@link VisualQueryDetector} with the metadata to complete the streamed partial
- * query that has been sent to {@link VisualQueryDetector}. This method is expected to be
- * only triggered if {@link Callback#onQueryDetected()} is called to put the service into
- * the query streaming state.
- *
- * @throws IllegalStateException if method called without query streamed.
- */
- public void onQueryFinished() throws IllegalStateException {
- try {
- mRemoteCallback.onQueryFinished();
- } catch (RemoteException e) {
- throw new IllegalStateException("#onQueryFinished must be only be triggered after "
- + "calling #onQueryDetected to be in the query streaming state.");
- }
+ /**
+ * Informs {@link VisualQueryDetector} with the metadata to complete the streamed partial
+ * query that has been sent to {@link VisualQueryDetector}. This method is expected to be
+ * only triggered if {@link VisualQueryDetectionService#streamQuery(String)} is called to put
+ * the service into the query streaming state.
+ *
+ * @throws IllegalStateException if method called without query streamed.
+ */
+ public final void finishQuery() throws IllegalStateException {
+ try {
+ mRemoteCallback.onQueryFinished();
+ } catch (RemoteException e) {
+ throw new IllegalStateException("#finishQuery must be only be triggered after "
+ + "calling #streamQuery to be in the query streaming state.");
}
}
diff --git a/core/java/android/service/voice/VisualQueryDetector.java b/core/java/android/service/voice/VisualQueryDetector.java
index 0be3253fc570..7dc0687b549d 100644
--- a/core/java/android/service/voice/VisualQueryDetector.java
+++ b/core/java/android/service/voice/VisualQueryDetector.java
@@ -177,7 +177,8 @@ public class VisualQueryDetector {
public interface Callback {
/**
- * Called when the {@link VisualQueryDetectionService} starts to stream partial queries.
+ * Called when the {@link VisualQueryDetectionService} starts to stream partial queries
+ * with {@link VisualQueryDetectionService#streamQuery(String)}.
*
* @param partialQuery The partial query in a text form being streamed.
*/
@@ -185,12 +186,13 @@ public class VisualQueryDetector {
/**
* Called when the {@link VisualQueryDetectionService} decides to abandon the streamed
- * partial queries.
+ * partial queries with {@link VisualQueryDetectionService#rejectQuery()}.
*/
void onQueryRejected();
/**
- * Called when the {@link VisualQueryDetectionService} finishes streaming partial queries.
+ * Called when the {@link VisualQueryDetectionService} finishes streaming partial queries
+ * with {@link VisualQueryDetectionService#finishQuery()}.
*/
void onQueryFinished();
@@ -199,9 +201,10 @@ public class VisualQueryDetector {
* short amount of time to report its initialization state.
*
* @param status Info about initialization state of {@link VisualQueryDetectionService}; the
- * allowed values are {@link SandboxedDetectionServiceBase#INITIALIZATION_STATUS_SUCCESS},
- * 1<->{@link SandboxedDetectionServiceBase#getMaxCustomInitializationStatus()},
- * {@link SandboxedDetectionServiceBase#INITIALIZATION_STATUS_UNKNOWN}.
+ * allowed values are
+ * {@link SandboxedDetectionInitializer#INITIALIZATION_STATUS_SUCCESS},
+ * 1<->{@link SandboxedDetectionInitializer#getMaxCustomInitializationStatus()},
+ * {@link SandboxedDetectionInitializer#INITIALIZATION_STATUS_UNKNOWN}.
*/
void onVisualQueryDetectionServiceInitialized(int status);
diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java
index a684e41a2a95..fcc64b088def 100644
--- a/core/java/android/service/voice/VoiceInteractionService.java
+++ b/core/java/android/service/voice/VoiceInteractionService.java
@@ -36,8 +36,8 @@ import android.content.Context;
import android.content.Intent;
import android.hardware.soundtrigger.KeyphraseEnrollmentInfo;
import android.hardware.soundtrigger.SoundTrigger;
-import android.media.voice.KeyphraseModelManager;
import android.media.permission.Identity;
+import android.media.voice.KeyphraseModelManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
@@ -180,6 +180,14 @@ public class VoiceInteractionService extends Service {
VoiceInteractionService::onShowSessionFailed,
VoiceInteractionService.this, args));
}
+
+ @Override
+ public void detectorRemoteExceptionOccurred(@NonNull IBinder token, int detectorType) {
+ Log.d(TAG, "detectorRemoteExceptionOccurred");
+ Handler.getMain().executeOrSendMessage(PooledLambda.obtainMessage(
+ VoiceInteractionService::onDetectorRemoteException,
+ VoiceInteractionService.this, token, detectorType));
+ }
};
IVoiceInteractionManagerService mSystemService;
@@ -192,6 +200,28 @@ public class VoiceInteractionService extends Service {
private final Set<HotwordDetector> mActiveDetectors = new ArraySet<>();
+
+ private void onDetectorRemoteException(@NonNull IBinder token, int detectorType) {
+ Log.d(TAG, "onDetectorRemoteException for " + HotwordDetector.detectorTypeToString(
+ detectorType));
+ mActiveDetectors.forEach(detector -> {
+ // TODO: handle normal detector, VQD
+ if (detectorType == HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_DSP
+ && detector instanceof AlwaysOnHotwordDetector) {
+ AlwaysOnHotwordDetector alwaysOnDetector = (AlwaysOnHotwordDetector) detector;
+ if (alwaysOnDetector.isSameToken(token)) {
+ alwaysOnDetector.onDetectorRemoteException();
+ }
+ } else if (detectorType == HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE
+ && detector instanceof SoftwareHotwordDetector) {
+ SoftwareHotwordDetector softwareDetector = (SoftwareHotwordDetector) detector;
+ if (softwareDetector.isSameToken(token)) {
+ softwareDetector.onDetectorRemoteException();
+ }
+ }
+ });
+ }
+
/**
* Called when a user has activated an affordance to launch voice assist from the Keyguard.
*
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 12cd5236017c..26bc5d12d3b9 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -1543,14 +1543,14 @@ public abstract class WallpaperService extends Service {
void doVisibilityChanged(boolean visible) {
if (!mDestroyed) {
mVisible = visible;
- reportVisibility();
+ reportVisibility(false);
if (mReportedVisible) processLocalColors();
} else {
AnimationHandler.requestAnimatorsEnabled(visible, this);
}
}
- void reportVisibility() {
+ void reportVisibility(boolean forceReport) {
if (mScreenshotSurfaceControl != null && mVisible) {
if (DEBUG) Log.v(TAG, "Frozen so don't report visibility change");
return;
@@ -1558,10 +1558,29 @@ public abstract class WallpaperService extends Service {
if (!mDestroyed) {
mDisplayState = mDisplay == null ? Display.STATE_UNKNOWN : mDisplay.getState();
boolean visible = mVisible && mDisplayState != Display.STATE_OFF;
- if (mReportedVisible != visible) {
+ if (DEBUG) {
+ Log.v(
+ TAG,
+ "reportVisibility"
+ + " mReportedVisible="
+ + mReportedVisible
+ + " mVisible="
+ + mVisible
+ + " mDisplayState="
+ + mDisplayState);
+ }
+ if (mReportedVisible != visible || forceReport) {
mReportedVisible = visible;
- if (DEBUG) Log.v(TAG, "onVisibilityChanged(" + visible
- + "): " + this);
+ if (DEBUG) {
+ Log.v(
+ TAG,
+ "onVisibilityChanged("
+ + visible
+ + "): "
+ + this
+ + " forceReport="
+ + forceReport);
+ }
if (visible) {
// If becoming visible, in preview mode the surface
// may have been destroyed so now we need to make
@@ -2198,24 +2217,29 @@ public abstract class WallpaperService extends Service {
}
mCreated = false;
}
- }
- private final DisplayListener mDisplayListener = new DisplayListener() {
- @Override
- public void onDisplayChanged(int displayId) {
- if (mDisplay.getDisplayId() == displayId) {
- reportVisibility();
- }
+ if (mSurfaceControl != null) {
+ mSurfaceControl.release();
+ mSurfaceControl = null;
}
+ }
- @Override
- public void onDisplayRemoved(int displayId) {
- }
+ private final DisplayListener mDisplayListener =
+ new DisplayListener() {
+ @Override
+ public void onDisplayChanged(int displayId) {
+ if (mDisplay.getDisplayId() == displayId) {
+ boolean forceReport = mDisplay.getState() != Display.STATE_DOZE_SUSPEND;
+ reportVisibility(forceReport);
+ }
+ }
- @Override
- public void onDisplayAdded(int displayId) {
- }
- };
+ @Override
+ public void onDisplayRemoved(int displayId) {}
+
+ @Override
+ public void onDisplayAdded(int displayId) {}
+ };
private Surface getOrCreateBLASTSurface(int width, int height, int format) {
Surface ret = null;
diff --git a/core/java/android/speech/RecognitionPart.java b/core/java/android/speech/RecognitionPart.java
index e551cdc9f21f..f4dc64af5135 100644
--- a/core/java/android/speech/RecognitionPart.java
+++ b/core/java/android/speech/RecognitionPart.java
@@ -55,7 +55,7 @@ public final class RecognitionPart implements Parcelable {
public static final int CONFIDENCE_LEVEL_LOW = 1;
/** Second-lowest level of confidence out of five levels. */
- public static final int CONFIDENCE_LEVEL_LOW_MEDIUM = 2;
+ public static final int CONFIDENCE_LEVEL_MEDIUM_LOW = 2;
/** Medium level of confidence out of five levels. */
public static final int CONFIDENCE_LEVEL_MEDIUM = 3;
@@ -152,7 +152,7 @@ public final class RecognitionPart implements Parcelable {
@android.annotation.IntDef(prefix = "CONFIDENCE_LEVEL_", value = {
CONFIDENCE_LEVEL_UNKNOWN,
CONFIDENCE_LEVEL_LOW,
- CONFIDENCE_LEVEL_LOW_MEDIUM,
+ CONFIDENCE_LEVEL_MEDIUM_LOW,
CONFIDENCE_LEVEL_MEDIUM,
CONFIDENCE_LEVEL_MEDIUM_HIGH,
CONFIDENCE_LEVEL_HIGH
@@ -169,8 +169,8 @@ public final class RecognitionPart implements Parcelable {
return "CONFIDENCE_LEVEL_UNKNOWN";
case CONFIDENCE_LEVEL_LOW:
return "CONFIDENCE_LEVEL_LOW";
- case CONFIDENCE_LEVEL_LOW_MEDIUM:
- return "CONFIDENCE_LEVEL_LOW_MEDIUM";
+ case CONFIDENCE_LEVEL_MEDIUM_LOW:
+ return "CONFIDENCE_LEVEL_MEDIUM_LOW";
case CONFIDENCE_LEVEL_MEDIUM:
return "CONFIDENCE_LEVEL_MEDIUM";
case CONFIDENCE_LEVEL_MEDIUM_HIGH:
@@ -196,7 +196,7 @@ public final class RecognitionPart implements Parcelable {
if (!(mConfidenceLevel == CONFIDENCE_LEVEL_UNKNOWN)
&& !(mConfidenceLevel == CONFIDENCE_LEVEL_LOW)
- && !(mConfidenceLevel == CONFIDENCE_LEVEL_LOW_MEDIUM)
+ && !(mConfidenceLevel == CONFIDENCE_LEVEL_MEDIUM_LOW)
&& !(mConfidenceLevel == CONFIDENCE_LEVEL_MEDIUM)
&& !(mConfidenceLevel == CONFIDENCE_LEVEL_MEDIUM_HIGH)
&& !(mConfidenceLevel == CONFIDENCE_LEVEL_HIGH)) {
@@ -204,7 +204,7 @@ public final class RecognitionPart implements Parcelable {
"confidenceLevel was " + mConfidenceLevel + " but must be one of: "
+ "CONFIDENCE_LEVEL_UNKNOWN(" + CONFIDENCE_LEVEL_UNKNOWN + "), "
+ "CONFIDENCE_LEVEL_LOW(" + CONFIDENCE_LEVEL_LOW + "), "
- + "CONFIDENCE_LEVEL_LOW_MEDIUM(" + CONFIDENCE_LEVEL_LOW_MEDIUM + "), "
+ + "CONFIDENCE_LEVEL_MEDIUM_LOW(" + CONFIDENCE_LEVEL_MEDIUM_LOW + "), "
+ "CONFIDENCE_LEVEL_MEDIUM(" + CONFIDENCE_LEVEL_MEDIUM + "), "
+ "CONFIDENCE_LEVEL_MEDIUM_HIGH(" + CONFIDENCE_LEVEL_MEDIUM_HIGH + "), "
+ "CONFIDENCE_LEVEL_HIGH(" + CONFIDENCE_LEVEL_HIGH + ")");
@@ -344,7 +344,7 @@ public final class RecognitionPart implements Parcelable {
if (!(mConfidenceLevel == CONFIDENCE_LEVEL_UNKNOWN)
&& !(mConfidenceLevel == CONFIDENCE_LEVEL_LOW)
- && !(mConfidenceLevel == CONFIDENCE_LEVEL_LOW_MEDIUM)
+ && !(mConfidenceLevel == CONFIDENCE_LEVEL_MEDIUM_LOW)
&& !(mConfidenceLevel == CONFIDENCE_LEVEL_MEDIUM)
&& !(mConfidenceLevel == CONFIDENCE_LEVEL_MEDIUM_HIGH)
&& !(mConfidenceLevel == CONFIDENCE_LEVEL_HIGH)) {
@@ -352,7 +352,7 @@ public final class RecognitionPart implements Parcelable {
"confidenceLevel was " + mConfidenceLevel + " but must be one of: "
+ "CONFIDENCE_LEVEL_UNKNOWN(" + CONFIDENCE_LEVEL_UNKNOWN + "), "
+ "CONFIDENCE_LEVEL_LOW(" + CONFIDENCE_LEVEL_LOW + "), "
- + "CONFIDENCE_LEVEL_LOW_MEDIUM(" + CONFIDENCE_LEVEL_LOW_MEDIUM + "), "
+ + "CONFIDENCE_LEVEL_MEDIUM_LOW(" + CONFIDENCE_LEVEL_MEDIUM_LOW + "), "
+ "CONFIDENCE_LEVEL_MEDIUM(" + CONFIDENCE_LEVEL_MEDIUM + "), "
+ "CONFIDENCE_LEVEL_MEDIUM_HIGH(" + CONFIDENCE_LEVEL_MEDIUM_HIGH + "), "
+ "CONFIDENCE_LEVEL_HIGH(" + CONFIDENCE_LEVEL_HIGH + ")");
@@ -474,10 +474,10 @@ public final class RecognitionPart implements Parcelable {
}
@DataClass.Generated(
- time = 1676294616910L,
+ time = 1677008539189L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/speech/RecognitionPart.java",
- inputSignatures = "public static final int CONFIDENCE_LEVEL_UNKNOWN\npublic static final int CONFIDENCE_LEVEL_LOW\npublic static final int CONFIDENCE_LEVEL_LOW_MEDIUM\npublic static final int CONFIDENCE_LEVEL_MEDIUM\npublic static final int CONFIDENCE_LEVEL_MEDIUM_HIGH\npublic static final int CONFIDENCE_LEVEL_HIGH\nprivate final @android.annotation.NonNull java.lang.String mRawText\nprivate final @android.annotation.Nullable java.lang.String mFormattedText\nprivate final long mTimestampMillis\nprivate final @android.speech.RecognitionPart.ConfidenceLevel int mConfidenceLevel\nprivate static java.lang.String defaultFormattedText()\nprivate static long defaultTimestampMillis()\nprivate static @android.speech.RecognitionPart.ConfidenceLevel int defaultConfidenceLevel()\nprivate void onConstructed()\nclass RecognitionPart extends java.lang.Object implements [android.os.Parcelable]\npublic @android.annotation.NonNull android.speech.RecognitionPart.Builder setFormattedText(java.lang.String)\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genBuilder=true, genEqualsHashCode=true, genHiddenConstDefs=true, genToString=true)\npublic @android.annotation.NonNull android.speech.RecognitionPart.Builder setFormattedText(java.lang.String)\nclass BaseBuilder extends java.lang.Object implements []")
+ inputSignatures = "public static final int CONFIDENCE_LEVEL_UNKNOWN\npublic static final int CONFIDENCE_LEVEL_LOW\npublic static final int CONFIDENCE_LEVEL_MEDIUM_LOW\npublic static final int CONFIDENCE_LEVEL_MEDIUM\npublic static final int CONFIDENCE_LEVEL_MEDIUM_HIGH\npublic static final int CONFIDENCE_LEVEL_HIGH\nprivate final @android.annotation.NonNull java.lang.String mRawText\nprivate final @android.annotation.Nullable java.lang.String mFormattedText\nprivate final long mTimestampMillis\nprivate final @android.speech.RecognitionPart.ConfidenceLevel int mConfidenceLevel\nprivate static java.lang.String defaultFormattedText()\nprivate static long defaultTimestampMillis()\nprivate static @android.speech.RecognitionPart.ConfidenceLevel int defaultConfidenceLevel()\nprivate void onConstructed()\nclass RecognitionPart extends java.lang.Object implements [android.os.Parcelable]\npublic @android.annotation.NonNull android.speech.RecognitionPart.Builder setFormattedText(java.lang.String)\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genBuilder=true, genEqualsHashCode=true, genHiddenConstDefs=true, genToString=true)\npublic @android.annotation.NonNull android.speech.RecognitionPart.Builder setFormattedText(java.lang.String)\nclass BaseBuilder extends java.lang.Object implements []")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/telephony/CellBroadcastIntents.java b/core/java/android/telephony/CellBroadcastIntents.java
index c3ca2866c71c..b9ad7734b24c 100644
--- a/core/java/android/telephony/CellBroadcastIntents.java
+++ b/core/java/android/telephony/CellBroadcastIntents.java
@@ -104,7 +104,7 @@ public class CellBroadcastIntents {
* Put the phone ID and sub ID into an intent as extras.
*/
private static void putPhoneIdAndSubIdExtra(Context context, Intent intent, int phoneId) {
- int subId = getSubIdForPhone(context, phoneId);
+ int subId = SubscriptionManager.getSubscriptionId(phoneId);
if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
intent.putExtra("subscription", subId);
intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
@@ -112,22 +112,4 @@ public class CellBroadcastIntents {
intent.putExtra("phone", phoneId);
intent.putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, phoneId);
}
-
- /**
- * Get the subscription ID for a phone ID, or INVALID_SUBSCRIPTION_ID if the phone does not
- * have an active sub
- * @param phoneId the phoneId to use
- * @return the associated sub id
- */
- private static int getSubIdForPhone(Context context, int phoneId) {
- SubscriptionManager subMan =
- (SubscriptionManager) context.getSystemService(
- Context.TELEPHONY_SUBSCRIPTION_SERVICE);
- int[] subIds = subMan.getSubscriptionIds(phoneId);
- if (subIds != null) {
- return subIds[0];
- } else {
- return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
- }
- }
}
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index f648ad4fbac3..434b1c76113f 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -53,9 +53,7 @@ import com.android.internal.telephony.ITelephonyRegistry;
import java.lang.ref.WeakReference;
import java.util.Arrays;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.WeakHashMap;
@@ -83,15 +81,16 @@ public class TelephonyRegistryManager {
* A mapping between {@link SubscriptionManager.OnSubscriptionsChangedListener} and
* its callback IOnSubscriptionsChangedListener.
*/
- private final Map<SubscriptionManager.OnSubscriptionsChangedListener,
- IOnSubscriptionsChangedListener> mSubscriptionChangedListenerMap = new HashMap<>();
+ private final ConcurrentHashMap<SubscriptionManager.OnSubscriptionsChangedListener,
+ IOnSubscriptionsChangedListener>
+ mSubscriptionChangedListenerMap = new ConcurrentHashMap<>();
/**
* A mapping between {@link SubscriptionManager.OnOpportunisticSubscriptionsChangedListener} and
* its callback IOnSubscriptionsChangedListener.
*/
- private final Map<SubscriptionManager.OnOpportunisticSubscriptionsChangedListener,
- IOnSubscriptionsChangedListener> mOpportunisticSubscriptionChangedListenerMap
- = new HashMap<>();
+ private final ConcurrentHashMap<SubscriptionManager.OnOpportunisticSubscriptionsChangedListener,
+ IOnSubscriptionsChangedListener>
+ mOpportunisticSubscriptionChangedListenerMap = new ConcurrentHashMap<>();
/**
* A mapping between {@link CarrierConfigManager.CarrierConfigChangeListener} and its callback
diff --git a/core/java/android/text/GraphemeClusterSegmentFinder.java b/core/java/android/text/GraphemeClusterSegmentFinder.java
index 656774f66792..0f6fdaf23c65 100644
--- a/core/java/android/text/GraphemeClusterSegmentFinder.java
+++ b/core/java/android/text/GraphemeClusterSegmentFinder.java
@@ -18,7 +18,8 @@ package android.text;
import android.annotation.IntRange;
import android.annotation.NonNull;
-import android.graphics.Paint;
+import android.graphics.TemporaryBuffer;
+import android.graphics.text.GraphemeBreak;
/**
* Implementation of {@code SegmentFinder} using grapheme clusters as the text segment. Whitespace
@@ -31,8 +32,8 @@ import android.graphics.Paint;
* Segmentation - Grapheme Cluster Boundaries</a>
*/
public class GraphemeClusterSegmentFinder extends SegmentFinder {
- private final CharSequence mText;
- private final TextPaint mTextPaint;
+ private static AutoGrowArray.FloatArray sTempAdvances = null;
+ private final boolean[] mIsGraphemeBreak;
/**
* Constructs a GraphemeClusterSegmentFinder instance for the specified text which uses the
@@ -43,51 +44,73 @@ public class GraphemeClusterSegmentFinder extends SegmentFinder {
*/
public GraphemeClusterSegmentFinder(
@NonNull CharSequence text, @NonNull TextPaint textPaint) {
- mText = text;
- mTextPaint = textPaint;
+
+ if (sTempAdvances == null) {
+ sTempAdvances = new AutoGrowArray.FloatArray(text.length());
+ } else if (sTempAdvances.size() < text.length()) {
+ sTempAdvances.resize(text.length());
+ }
+
+ mIsGraphemeBreak = new boolean[text.length()];
+ float[] advances = sTempAdvances.getRawArray();
+ char[] chars = TemporaryBuffer.obtain(text.length());
+
+ TextUtils.getChars(text, 0, text.length(), chars, 0);
+
+ textPaint.getTextWidths(chars, 0, text.length(), advances);
+
+ GraphemeBreak.isGraphemeBreak(advances, chars, /* start= */ 0, /* end= */ text.length(),
+ mIsGraphemeBreak);
+ TemporaryBuffer.recycle(chars);
+ }
+
+ private int previousBoundary(@IntRange(from = 0) int offset) {
+ if (offset <= 0) return DONE;
+ do {
+ --offset;
+ } while (offset > 0 && !mIsGraphemeBreak[offset]);
+ return offset;
+ }
+
+ private int nextBoundary(@IntRange(from = 0) int offset) {
+ if (offset >= mIsGraphemeBreak.length) return DONE;
+ do {
+ ++offset;
+ } while (offset < mIsGraphemeBreak.length && !mIsGraphemeBreak[offset]);
+ return offset;
}
@Override
public int previousStartBoundary(@IntRange(from = 0) int offset) {
- if (offset == 0) return DONE;
- int boundary = mTextPaint.getTextRunCursor(
- mText, 0, mText.length(), false, offset, Paint.CURSOR_BEFORE);
- return boundary == -1 ? DONE : boundary;
+ return previousBoundary(offset);
}
@Override
public int previousEndBoundary(@IntRange(from = 0) int offset) {
if (offset == 0) return DONE;
- int boundary = mTextPaint.getTextRunCursor(
- mText, 0, mText.length(), false, offset, Paint.CURSOR_BEFORE);
+ int boundary = previousBoundary(offset);
// Check that there is another cursor position before, otherwise this is not a valid
// end boundary.
- if (mTextPaint.getTextRunCursor(
- mText, 0, mText.length(), false, boundary, Paint.CURSOR_BEFORE) == -1) {
+ if (boundary == DONE || previousBoundary(boundary) == DONE) {
return DONE;
}
- return boundary == -1 ? DONE : boundary;
+ return boundary;
}
@Override
public int nextStartBoundary(@IntRange(from = 0) int offset) {
- if (offset == mText.length()) return DONE;
- int boundary = mTextPaint.getTextRunCursor(
- mText, 0, mText.length(), false, offset, Paint.CURSOR_AFTER);
+ if (offset == mIsGraphemeBreak.length) return DONE;
+ int boundary = nextBoundary(offset);
// Check that there is another cursor position after, otherwise this is not a valid
// start boundary.
- if (mTextPaint.getTextRunCursor(
- mText, 0, mText.length(), false, boundary, Paint.CURSOR_AFTER) == -1) {
+ if (boundary == DONE || nextBoundary(boundary) == DONE) {
return DONE;
}
- return boundary == -1 ? DONE : boundary;
+ return boundary;
}
@Override
public int nextEndBoundary(@IntRange(from = 0) int offset) {
- if (offset == mText.length()) return DONE;
- int boundary = mTextPaint.getTextRunCursor(
- mText, 0, mText.length(), false, offset, Paint.CURSOR_AFTER);
- return boundary == -1 ? DONE : boundary;
+ return nextBoundary(offset);
}
}
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index a746dc6c15f0..2ae882c81b50 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -164,10 +164,10 @@ public class FeatureFlagUtils {
*/
public static final String SETTINGS_AUDIO_ROUTING = "settings_audio_routing";
- /** Flag to enable/disable flash alerts
+ /** Flag to enable/disable flash notifications
* @hide
*/
- public static final String SETTINGS_FLASH_ALERTS = "settings_flash_alerts";
+ public static final String SETTINGS_FLASH_NOTIFICATIONS = "settings_flash_notifications";
/**
* Flag to disable/enable showing udfps enroll view in settings. If it's disabled, udfps enroll
@@ -232,7 +232,7 @@ public class FeatureFlagUtils {
DEFAULT_FLAGS.put(SETTINGS_ACCESSIBILITY_HEARING_AID_PAGE, "false");
DEFAULT_FLAGS.put(SETTINGS_PREFER_ACCESSIBILITY_MENU_IN_SYSTEM, "false");
DEFAULT_FLAGS.put(SETTINGS_AUDIO_ROUTING, "false");
- DEFAULT_FLAGS.put(SETTINGS_FLASH_ALERTS, "false");
+ DEFAULT_FLAGS.put(SETTINGS_FLASH_NOTIFICATIONS, "true");
DEFAULT_FLAGS.put(SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS, "true");
DEFAULT_FLAGS.put(SETTINGS_ENABLE_LOCKSCREEN_TRANSFER_API, "false");
DEFAULT_FLAGS.put(SETTINGS_REMOTE_DEVICE_CREDENTIAL_VALIDATION, "false");
diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java
index 98c0d7f4fbf1..5aa0f59024f8 100644
--- a/core/java/android/util/NtpTrustedTime.java
+++ b/core/java/android/util/NtpTrustedTime.java
@@ -477,7 +477,14 @@ public abstract class NtpTrustedTime implements TrustedTime {
return mTimeResult;
}
- /** Clears the last received NTP. Intended for use during tests. */
+ /** Sets the last received NTP time. Intended for use during tests. */
+ public void setCachedTimeResult(TimeResult timeResult) {
+ synchronized (this) {
+ mTimeResult = timeResult;
+ }
+ }
+
+ /** Clears the last received NTP time. Intended for use during tests. */
public void clearCachedTimeResult() {
synchronized (this) {
mTimeResult = null;
diff --git a/core/java/android/util/SparseArrayMap.java b/core/java/android/util/SparseArrayMap.java
index 1a2c4df96b36..b4e1f59874b0 100644
--- a/core/java/android/util/SparseArrayMap.java
+++ b/core/java/android/util/SparseArrayMap.java
@@ -90,6 +90,14 @@ public class SparseArrayMap<K, V> {
}
/**
+ * Removes the data for the keyIndex and mapIndex, if there was any.
+ * @hide
+ */
+ public void deleteAt(int keyIndex, int mapIndex) {
+ mData.valueAt(keyIndex).removeAt(mapIndex);
+ }
+
+ /**
* Get the value associated with the int-K pair.
*/
@Nullable
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 3cf56c0668c8..6804c5ca3e4f 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -172,7 +172,7 @@ public final class AccessibilityInteractionController {
private boolean isVisibleToAccessibilityService(View view) {
return view != null && (mA11yManager.isRequestFromAccessibilityTool()
- || !view.isAccessibilityDataPrivate());
+ || !view.isAccessibilityDataSensitive());
}
public void findAccessibilityNodeInfoByAccessibilityIdClientThread(
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index 4a83bbe7e72b..8c4e90c81147 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -197,6 +197,7 @@ public final class Choreographer {
private int mFPSDivisor = 1;
private DisplayEventReceiver.VsyncEventData mLastVsyncEventData =
new DisplayEventReceiver.VsyncEventData();
+ private final FrameData mFrameData = new FrameData();
/**
* Contains information about the current frame for jank-tracking,
@@ -789,7 +790,7 @@ public final class Choreographer {
Trace.traceBegin(Trace.TRACE_TAG_VIEW,
"Choreographer#doFrame " + vsyncEventData.preferredFrameTimeline().vsyncId);
}
- FrameData frameData = new FrameData(frameTimeNanos, vsyncEventData);
+ mFrameData.update(frameTimeNanos, vsyncEventData);
synchronized (mLock) {
if (!mFrameScheduled) {
traceMessage("Frame not scheduled");
@@ -827,7 +828,7 @@ public final class Choreographer {
+ " ms in the past.");
}
}
- frameData = getUpdatedFrameData(frameTimeNanos, frameData, jitterNanos);
+ mFrameData.update(frameTimeNanos, mDisplayEventReceiver, jitterNanos);
}
if (frameTimeNanos < mLastFrameTimeNanos) {
@@ -862,17 +863,16 @@ public final class Choreographer {
AnimationUtils.lockAnimationClock(frameTimeNanos / TimeUtils.NANOS_PER_MS);
mFrameInfo.markInputHandlingStart();
- doCallbacks(Choreographer.CALLBACK_INPUT, frameData, frameIntervalNanos);
+ doCallbacks(Choreographer.CALLBACK_INPUT, frameIntervalNanos);
mFrameInfo.markAnimationsStart();
- doCallbacks(Choreographer.CALLBACK_ANIMATION, frameData, frameIntervalNanos);
- doCallbacks(Choreographer.CALLBACK_INSETS_ANIMATION, frameData,
- frameIntervalNanos);
+ doCallbacks(Choreographer.CALLBACK_ANIMATION, frameIntervalNanos);
+ doCallbacks(Choreographer.CALLBACK_INSETS_ANIMATION, frameIntervalNanos);
mFrameInfo.markPerformTraversalsStart();
- doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameData, frameIntervalNanos);
+ doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameIntervalNanos);
- doCallbacks(Choreographer.CALLBACK_COMMIT, frameData, frameIntervalNanos);
+ doCallbacks(Choreographer.CALLBACK_COMMIT, frameIntervalNanos);
} finally {
AnimationUtils.unlockAnimationClock();
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
@@ -886,9 +886,9 @@ public final class Choreographer {
}
}
- void doCallbacks(int callbackType, FrameData frameData, long frameIntervalNanos) {
+ void doCallbacks(int callbackType, long frameIntervalNanos) {
CallbackRecord callbacks;
- long frameTimeNanos = frameData.mFrameTimeNanos;
+ long frameTimeNanos = mFrameData.mFrameTimeNanos;
synchronized (mLock) {
// We use "now" to determine when callbacks become due because it's possible
// for earlier processing phases in a frame to post callbacks that should run
@@ -925,7 +925,7 @@ public final class Choreographer {
}
frameTimeNanos = now - lastFrameOffset;
mLastFrameTimeNanos = frameTimeNanos;
- frameData = getUpdatedFrameData(frameTimeNanos, frameData, jitterNanos);
+ mFrameData.update(frameTimeNanos, mDisplayEventReceiver, jitterNanos);
}
}
}
@@ -937,7 +937,7 @@ public final class Choreographer {
+ ", action=" + c.action + ", token=" + c.token
+ ", latencyMillis=" + (SystemClock.uptimeMillis() - c.dueTime));
}
- c.run(frameData);
+ c.run(mFrameData);
}
} finally {
synchronized (mLock) {
@@ -1039,21 +1039,38 @@ public final class Choreographer {
/** Holds data that describes one possible VSync frame event to render at. */
public static class FrameTimeline {
- FrameTimeline(long vsyncId, long expectedPresentTimeNanos, long deadlineNanos) {
- this.mVsyncId = vsyncId;
- this.mExpectedPresentTimeNanos = expectedPresentTimeNanos;
- this.mDeadlineNanos = deadlineNanos;
+ private long mVsyncId = FrameInfo.INVALID_VSYNC_ID;
+ private long mExpectedPresentationTimeNanos = -1;
+ private long mDeadlineNanos = -1;
+ private boolean mInCallback = false;
+
+ FrameTimeline() {
+ // Intentionally empty; defined so that it is not API/public by default.
+ }
+
+ void setInCallback(boolean inCallback) {
+ mInCallback = inCallback;
}
- private long mVsyncId;
- private long mExpectedPresentTimeNanos;
- private long mDeadlineNanos;
+ private void checkInCallback() {
+ if (!mInCallback) {
+ throw new IllegalStateException(
+ "FrameTimeline is not valid outside of the vsync callback");
+ }
+ }
+
+ void update(long vsyncId, long expectedPresentationTimeNanos, long deadlineNanos) {
+ mVsyncId = vsyncId;
+ mExpectedPresentationTimeNanos = expectedPresentationTimeNanos;
+ mDeadlineNanos = deadlineNanos;
+ }
/**
* The id that corresponds to this frame timeline, used to correlate a frame
* produced by HWUI with the timeline data stored in Surface Flinger.
*/
public long getVsyncId() {
+ checkInCallback();
return mVsyncId;
}
@@ -1062,13 +1079,15 @@ public final class Choreographer {
* presented.
*/
public long getExpectedPresentationTimeNanos() {
- return mExpectedPresentTimeNanos;
+ checkInCallback();
+ return mExpectedPresentationTimeNanos;
}
/**
* The time in {@link System#nanoTime()} timebase which this frame needs to be ready by.
*/
public long getDeadlineNanos() {
+ checkInCallback();
return mDeadlineNanos;
}
}
@@ -1079,24 +1098,21 @@ public final class Choreographer {
* information including deadline and expected present time.
*/
public static class FrameData {
- FrameData(long frameTimeNanos, DisplayEventReceiver.VsyncEventData vsyncEventData) {
- this.mFrameTimeNanos = frameTimeNanos;
- this.mFrameTimelines = convertFrameTimelines(vsyncEventData);
- this.mPreferredFrameTimelineIndex =
- vsyncEventData.preferredFrameTimelineIndex;
- }
-
private long mFrameTimeNanos;
- private final FrameTimeline[] mFrameTimelines;
+ private final FrameTimeline[] mFrameTimelines =
+ new FrameTimeline[DisplayEventReceiver.VsyncEventData.FRAME_TIMELINES_LENGTH];
private int mPreferredFrameTimelineIndex;
+ private boolean mInCallback = false;
- void updateFrameData(long frameTimeNanos, int newPreferredFrameTimelineIndex) {
- mFrameTimeNanos = frameTimeNanos;
- mPreferredFrameTimelineIndex = newPreferredFrameTimelineIndex;
+ FrameData() {
+ for (int i = 0; i < mFrameTimelines.length; i++) {
+ mFrameTimelines[i] = new FrameTimeline();
+ }
}
/** The time in nanoseconds when the frame started being rendered. */
public long getFrameTimeNanos() {
+ checkInCallback();
return mFrameTimeNanos;
}
@@ -1104,58 +1120,83 @@ public final class Choreographer {
@NonNull
@SuppressLint("ArrayReturn") // For API consistency and speed.
public FrameTimeline[] getFrameTimelines() {
+ checkInCallback();
return mFrameTimelines;
}
/** The platform-preferred frame timeline. */
@NonNull
public FrameTimeline getPreferredFrameTimeline() {
+ checkInCallback();
return mFrameTimelines[mPreferredFrameTimelineIndex];
}
- private FrameTimeline[] convertFrameTimelines(
- DisplayEventReceiver.VsyncEventData vsyncEventData) {
- FrameTimeline[] frameTimelines =
- new FrameTimeline[vsyncEventData.frameTimelines.length];
+ void setInCallback(boolean inCallback) {
+ mInCallback = inCallback;
+ for (int i = 0; i < mFrameTimelines.length; i++) {
+ mFrameTimelines[i].setInCallback(inCallback);
+ }
+ }
+
+ private void checkInCallback() {
+ if (!mInCallback) {
+ throw new IllegalStateException(
+ "FrameData is not valid outside of the vsync callback");
+ }
+ }
+
+ /**
+ * Update the frame data with a {@code DisplayEventReceiver.VsyncEventData} received from
+ * native.
+ */
+ void update(long frameTimeNanos, DisplayEventReceiver.VsyncEventData vsyncEventData) {
+ if (vsyncEventData.frameTimelines.length != mFrameTimelines.length) {
+ throw new IllegalStateException(
+ "Length of native frame timelines received does not match Java. Did "
+ + "FRAME_TIMELINES_LENGTH or kFrameTimelinesLength (native) "
+ + "change?");
+ }
+ mFrameTimeNanos = frameTimeNanos;
+ mPreferredFrameTimelineIndex = vsyncEventData.preferredFrameTimelineIndex;
for (int i = 0; i < vsyncEventData.frameTimelines.length; i++) {
DisplayEventReceiver.VsyncEventData.FrameTimeline frameTimeline =
vsyncEventData.frameTimelines[i];
- frameTimelines[i] = new FrameTimeline(frameTimeline.vsyncId,
- frameTimeline.expectedPresentTime, frameTimeline.deadline);
+ mFrameTimelines[i].update(frameTimeline.vsyncId,
+ frameTimeline.expectedPresentationTime, frameTimeline.deadline);
}
- return frameTimelines;
}
- }
- /**
- * Update the frame data when the frame is late.
- *
- * @param jitterNanos currentTime - frameTime
- */
- private FrameData getUpdatedFrameData(long frameTimeNanos, FrameData frameData,
- long jitterNanos) {
- int newPreferredIndex = 0;
- FrameTimeline[] frameTimelines = frameData.getFrameTimelines();
- final long minimumDeadline =
- frameData.getPreferredFrameTimeline().getDeadlineNanos() + jitterNanos;
- // Look for a non-past deadline timestamp in the existing frame data. Otherwise, binder
- // query for new frame data. Note that binder is relatively slow, O(ms), so it is
- // only called when the existing frame data does not hold a valid frame.
- while (newPreferredIndex < frameTimelines.length - 1
- && frameTimelines[newPreferredIndex].getDeadlineNanos()
- < minimumDeadline) {
- newPreferredIndex++;
+ /**
+ * Update the frame data when the frame is late.
+ *
+ * @param jitterNanos currentTime - frameTime
+ */
+ void update(
+ long frameTimeNanos, DisplayEventReceiver displayEventReceiver, long jitterNanos) {
+ int newPreferredIndex = 0;
+ final long minimumDeadline =
+ mFrameTimelines[mPreferredFrameTimelineIndex].mDeadlineNanos + jitterNanos;
+ // Look for a non-past deadline timestamp in the existing frame data. Otherwise, binder
+ // query for new frame data. Note that binder is relatively slow, O(ms), so it is
+ // only called when the existing frame data does not hold a valid frame.
+ while (newPreferredIndex < mFrameTimelines.length - 1
+ && mFrameTimelines[newPreferredIndex].mDeadlineNanos < minimumDeadline) {
+ newPreferredIndex++;
+ }
+
+ long newPreferredDeadline = mFrameTimelines[newPreferredIndex].mDeadlineNanos;
+ if (newPreferredDeadline < minimumDeadline) {
+ DisplayEventReceiver.VsyncEventData latestVsyncEventData =
+ displayEventReceiver.getLatestVsyncEventData();
+ update(frameTimeNanos, latestVsyncEventData);
+ } else {
+ update(frameTimeNanos, newPreferredIndex);
+ }
}
- long newPreferredDeadline =
- frameData.getFrameTimelines()[newPreferredIndex].getDeadlineNanos();
- if (newPreferredDeadline < minimumDeadline) {
- DisplayEventReceiver.VsyncEventData latestVsyncEventData =
- mDisplayEventReceiver.getLatestVsyncEventData();
- return new FrameData(frameTimeNanos, latestVsyncEventData);
- } else {
- frameData.updateFrameData(frameTimeNanos, newPreferredIndex);
- return frameData;
+ void update(long frameTimeNanos, int newPreferredFrameTimelineIndex) {
+ mFrameTimeNanos = frameTimeNanos;
+ mPreferredFrameTimelineIndex = newPreferredFrameTimelineIndex;
}
}
@@ -1280,11 +1321,13 @@ public final class Choreographer {
}
void run(FrameData frameData) {
+ frameData.setInCallback(true);
if (token == VSYNC_CALLBACK_TOKEN) {
((VsyncCallback) action).onVsync(frameData);
} else {
run(frameData.getFrameTimeNanos());
}
+ frameData.setInCallback(false);
}
}
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 20be9d65ab8e..547608899259 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -1261,20 +1261,17 @@ public final class Display {
/**
* @hide
- * Returns the display's HDR supported types.
+ * Returns the current mode's supported HDR types.
*
* @see #isHdr()
- * @see HdrCapabilities#getSupportedHdrTypes()
+ * @see Mode#getSupportedHdrTypes()
*/
@TestApi
@NonNull
public int[] getReportedHdrTypes() {
synchronized (mLock) {
updateDisplayInfoLocked();
- if (mDisplayInfo.hdrCapabilities == null) {
- return new int[0];
- }
- return mDisplayInfo.hdrCapabilities.getSupportedHdrTypes();
+ return mDisplayInfo.getMode().getSupportedHdrTypes();
}
}
diff --git a/core/java/android/view/DisplayEventReceiver.java b/core/java/android/view/DisplayEventReceiver.java
index edce00181335..07ac5977c4e3 100644
--- a/core/java/android/view/DisplayEventReceiver.java
+++ b/core/java/android/view/DisplayEventReceiver.java
@@ -145,11 +145,16 @@ public abstract class DisplayEventReceiver {
static final FrameTimeline[] INVALID_FRAME_TIMELINES =
{new FrameTimeline(FrameInfo.INVALID_VSYNC_ID, Long.MAX_VALUE, Long.MAX_VALUE)};
+ // The amount of frame timeline choices.
+ // Must be in sync with VsyncEventData::kFrameTimelinesLength in
+ // frameworks/native/libs/gui/include/gui/VsyncEventData.h. If they do not match, a runtime
+ // assertion is thrown when Choreographer is processing VsyncEventData.
+ static final int FRAME_TIMELINES_LENGTH = 7;
public static class FrameTimeline {
- FrameTimeline(long vsyncId, long expectedPresentTime, long deadline) {
+ FrameTimeline(long vsyncId, long expectedPresentationTime, long deadline) {
this.vsyncId = vsyncId;
- this.expectedPresentTime = expectedPresentTime;
+ this.expectedPresentationTime = expectedPresentationTime;
this.deadline = deadline;
}
@@ -158,7 +163,7 @@ public abstract class DisplayEventReceiver {
public final long vsyncId;
// The frame timestamp for when the frame is expected to be presented.
- public final long expectedPresentTime;
+ public final long expectedPresentationTime;
// The frame deadline timestamp in {@link System#nanoTime()} timebase that it is
// allotted for the frame to be completed.
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 03689188a9b3..e31adcfd699e 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -24,6 +24,7 @@ import static android.view.DisplayInfoProto.LOGICAL_HEIGHT;
import static android.view.DisplayInfoProto.LOGICAL_WIDTH;
import static android.view.DisplayInfoProto.NAME;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.WindowConfiguration;
import android.compat.annotation.UnsupportedAppUsage;
@@ -37,6 +38,7 @@ import android.os.Parcelable;
import android.os.Process;
import android.util.ArraySet;
import android.util.DisplayMetrics;
+import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
import com.android.internal.display.BrightnessSynchronizer;
@@ -348,6 +350,12 @@ public final class DisplayInfo implements Parcelable {
*/
public float hdrSdrRatio = Float.NaN;
+ /**
+ * RefreshRateRange limitation for @Temperature.ThrottlingStatus
+ */
+ @NonNull
+ public SparseArray<SurfaceControl.RefreshRateRange> refreshRateThermalThrottling =
+ new SparseArray<>();
public static final @android.annotation.NonNull Creator<DisplayInfo> CREATOR = new Creator<DisplayInfo>() {
@Override
@@ -425,7 +433,8 @@ public final class DisplayInfo implements Parcelable {
&& installOrientation == other.installOrientation
&& Objects.equals(displayShape, other.displayShape)
&& Objects.equals(layoutLimitedRefreshRate, other.layoutLimitedRefreshRate)
- && BrightnessSynchronizer.floatEquals(hdrSdrRatio, other.hdrSdrRatio);
+ && BrightnessSynchronizer.floatEquals(hdrSdrRatio, other.hdrSdrRatio)
+ && refreshRateThermalThrottling.contentEquals(other.refreshRateThermalThrottling);
}
@Override
@@ -482,6 +491,7 @@ public final class DisplayInfo implements Parcelable {
displayShape = other.displayShape;
layoutLimitedRefreshRate = other.layoutLimitedRefreshRate;
hdrSdrRatio = other.hdrSdrRatio;
+ refreshRateThermalThrottling = other.refreshRateThermalThrottling;
}
public void readFromParcel(Parcel source) {
@@ -544,6 +554,8 @@ public final class DisplayInfo implements Parcelable {
displayShape = source.readTypedObject(DisplayShape.CREATOR);
layoutLimitedRefreshRate = source.readTypedObject(SurfaceControl.RefreshRateRange.CREATOR);
hdrSdrRatio = source.readFloat();
+ refreshRateThermalThrottling = source.readSparseArray(null,
+ SurfaceControl.RefreshRateRange.class);
}
@Override
@@ -604,6 +616,7 @@ public final class DisplayInfo implements Parcelable {
dest.writeTypedObject(displayShape, flags);
dest.writeTypedObject(layoutLimitedRefreshRate, flags);
dest.writeFloat(hdrSdrRatio);
+ dest.writeSparseArray(refreshRateThermalThrottling);
}
@Override
@@ -871,6 +884,8 @@ public final class DisplayInfo implements Parcelable {
} else {
sb.append(hdrSdrRatio);
}
+ sb.append(", refreshRateThermalThrottling ");
+ sb.append(refreshRateThermalThrottling);
sb.append("}");
return sb.toString();
}
diff --git a/core/java/android/view/HandwritingDelegateConfiguration.java b/core/java/android/view/HandwritingDelegateConfiguration.java
deleted file mode 100644
index 719c614f42f0..000000000000
--- a/core/java/android/view/HandwritingDelegateConfiguration.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.annotation.IdRes;
-import android.annotation.NonNull;
-
-/**
- * Configuration for a view to act as a handwriting initiation delegate. This allows handwriting
- * mode for a delegator editor view to be initiated by stylus movement on the delegate view.
- *
- * <p>If a stylus {@link MotionEvent} occurs within the delegate view's bounds, the callback
- * returned by {@link #getInitiationCallback()} will be called. The callback implementation is
- * expected to show and focus the delegator editor view. If a view with identifier matching {@link
- * #getDelegatorViewId()} creates an input connection while the same stylus {@link MotionEvent}
- * sequence is ongoing, handwriting mode will be initiated for that view.
- *
- * <p>A common use case is a custom view which looks like a text editor but does not actually
- * support text editing itself, and clicking on the custom view causes an EditText to be shown. To
- * support handwriting initiation in this case, {@link View#setHandwritingDelegateConfiguration} can
- * be called on the custom view to configure it as a delegate, and set the EditText as the delegator
- * by passing the EditText's identifier as the {@code delegatorViewId}. The {@code
- * initiationCallback} implementation is typically the same as the click listener implementation
- * which shows the EditText.
- */
-public class HandwritingDelegateConfiguration {
- @IdRes private final int mDelegatorViewId;
- @NonNull private final Runnable mInitiationCallback;
-
- /**
- * Constructs a HandwritingDelegateConfiguration instance.
- *
- * @param delegatorViewId identifier of the delegator editor view for which handwriting mode
- * should be initiated
- * @param initiationCallback callback called when a stylus {@link MotionEvent} occurs within
- * this view's bounds. This will be called from the UI thread.
- */
- public HandwritingDelegateConfiguration(
- @IdRes int delegatorViewId, @NonNull Runnable initiationCallback) {
- mDelegatorViewId = delegatorViewId;
- mInitiationCallback = initiationCallback;
- }
-
- /**
- * Returns the identifier of the delegator editor view for which handwriting mode should be
- * initiated.
- */
- public int getDelegatorViewId() {
- return mDelegatorViewId;
- }
-
- /**
- * Returns the callback which should be called when a stylus {@link MotionEvent} occurs within
- * the delegate view's bounds. The callback should only be called from the UI thread.
- */
- @NonNull
- public Runnable getInitiationCallback() {
- return mInitiationCallback;
- }
-}
diff --git a/core/java/android/view/HandwritingInitiator.java b/core/java/android/view/HandwritingInitiator.java
index 8d221ab0b70a..fa926129b823 100644
--- a/core/java/android/view/HandwritingInitiator.java
+++ b/core/java/android/view/HandwritingInitiator.java
@@ -16,7 +16,6 @@
package android.view;
-import android.annotation.IdRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
@@ -172,15 +171,15 @@ public class HandwritingInitiator {
if (candidateView != null) {
if (candidateView == getConnectedView()) {
startHandwriting(candidateView);
- } else if (candidateView.getHandwritingDelegateConfiguration() != null) {
- mState.mDelegatorViewId =
- candidateView
- .getHandwritingDelegateConfiguration()
- .getDelegatorViewId();
- candidateView
- .getHandwritingDelegateConfiguration()
- .getInitiationCallback()
- .run();
+ } else if (candidateView.getHandwritingDelegatorCallback() != null) {
+ String delegatePackageName =
+ candidateView.getAllowedHandwritingDelegatePackageName();
+ if (delegatePackageName == null) {
+ delegatePackageName = candidateView.getContext().getOpPackageName();
+ }
+ mImm.prepareStylusHandwritingDelegation(
+ candidateView, delegatePackageName);
+ candidateView.getHandwritingDelegatorCallback().run();
} else {
if (candidateView.getRevealOnFocusHint()) {
candidateView.setRevealOnFocusHint(false);
@@ -227,6 +226,9 @@ public class HandwritingInitiator {
} else {
mConnectedView = new WeakReference<>(view);
mConnectionCount = 1;
+ if (view.isHandwritingDelegate() && tryAcceptStylusHandwritingDelegation(view)) {
+ return;
+ }
if (mState != null && mState.mShouldInitHandwriting) {
tryStartHandwriting();
}
@@ -279,17 +281,15 @@ public class HandwritingInitiator {
}
final Rect handwritingArea = getViewHandwritingArea(connectedView);
- if ((mState.mDelegatorViewId != View.NO_ID
- && mState.mDelegatorViewId == connectedView.getId())
- || isInHandwritingArea(
- handwritingArea, mState.mStylusDownX, mState.mStylusDownY, connectedView)) {
+ if (isInHandwritingArea(
+ handwritingArea, mState.mStylusDownX, mState.mStylusDownY, connectedView)) {
startHandwriting(connectedView);
} else {
mState.mShouldInitHandwriting = false;
}
}
- /** For test only. */
+ /** Starts a stylus handwriting session for the view. */
@VisibleForTesting
public void startHandwriting(@NonNull View view) {
mImm.startStylusHandwriting(view);
@@ -298,6 +298,27 @@ public class HandwritingInitiator {
}
/**
+ * Starts a stylus handwriting session for the delegate view, if {@link
+ * InputMethodManager#prepareStylusHandwritingDelegation} was previously called.
+ */
+ @VisibleForTesting
+ public boolean tryAcceptStylusHandwritingDelegation(@NonNull View view) {
+ String delegatorPackageName =
+ view.getAllowedHandwritingDelegatorPackageName();
+ if (delegatorPackageName == null) {
+ delegatorPackageName = view.getContext().getOpPackageName();
+ }
+ if (mImm.acceptStylusHandwritingDelegation(view, delegatorPackageName)) {
+ if (mState != null) {
+ mState.mHasInitiatedHandwriting = true;
+ mState.mShouldInitHandwriting = false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
* Notify that the handwriting area for the given view might be updated.
* @param view the view whose handwriting area might be updated.
*/
@@ -542,13 +563,6 @@ public class HandwritingInitiator {
* built InputConnection.
*/
private boolean mExceedHandwritingSlop;
- /**
- * If the current ongoing stylus MotionEvent sequence started over a handwriting initiation
- * delegate view, then this is the view identifier of the corresponding delegator view. If
- * the delegator view creates an input connection while the MotionEvent sequence is still
- * ongoing, then handwriting mode will be initiated for the delegator view.
- */
- @IdRes private int mDelegatorViewId = View.NO_ID;
/** The pointer id of the stylus pointer that is being tracked. */
private final int mStylusPointerId;
diff --git a/core/java/android/view/InsetsSource.java b/core/java/android/view/InsetsSource.java
index 17ab83c0df16..39477380e196 100644
--- a/core/java/android/view/InsetsSource.java
+++ b/core/java/android/view/InsetsSource.java
@@ -20,7 +20,6 @@ import static android.view.InsetsSourceProto.FRAME;
import static android.view.InsetsSourceProto.TYPE;
import static android.view.InsetsSourceProto.VISIBLE;
import static android.view.InsetsSourceProto.VISIBLE_FRAME;
-import static android.view.ViewRootImpl.CAPTION_ON_SHELL;
import static android.view.WindowInsets.Type.ime;
import android.annotation.IntRange;
@@ -133,7 +132,7 @@ public class InsetsSource implements Parcelable {
return mVisibleFrame == null || !mVisibleFrame.isEmpty();
}
- public boolean getInsetsRoundedCornerFrame() {
+ public boolean insetsRoundedCornerFrame() {
return mInsetsRoundedCornerFrame;
}
@@ -169,7 +168,7 @@ public class InsetsSource implements Parcelable {
// During drag-move and drag-resizing, the caption insets position may not get updated
// before the app frame get updated. To layout the app content correctly during drag events,
// we always return the insets with the corresponding height covering the top.
- if (!CAPTION_ON_SHELL && getType() == WindowInsets.Type.captionBar()) {
+ if (getType() == WindowInsets.Type.captionBar()) {
return Insets.of(0, frame.height(), 0, 0);
}
// Checks for whether there is shared edge with insets for 0-width/height window.
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index ba7d823750a3..997e4a553063 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -275,7 +275,7 @@ public class InsetsState implements Parcelable {
final Rect roundedCornerFrame = new Rect(mRoundedCornerFrame);
for (int i = mSources.size() - 1; i >= 0; i--) {
final InsetsSource source = mSources.valueAt(i);
- if (source.getInsetsRoundedCornerFrame()) {
+ if (source.insetsRoundedCornerFrame()) {
final Insets insets = source.calculateInsets(roundedCornerFrame, false);
roundedCornerFrame.inset(insets);
}
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 66442bb9e2c9..ab8134559189 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -1445,7 +1445,7 @@ public class KeyEvent extends InputEvent implements Parcelable {
private KeyEvent() {
this(/* downTime= */ 0, /* eventTime= */ 0, /* action= */ 0, /* code= */0, /* repeat= */ 0,
/* metaState= */ 0, /* deviceId= */ 0, /* scancode= */ 0, /* flags= */ 0,
- /* source= */ 0);
+ /* source= */ 0, /* characters= */ null);
}
/**
@@ -1458,7 +1458,7 @@ public class KeyEvent extends InputEvent implements Parcelable {
public KeyEvent(int action, int code) {
this(/* downTime= */ 0, /* eventTime= */ 0, action, code, /* repeat= */ 0,
/* metaState= */ 0, /* deviceId= */ KeyCharacterMap.VIRTUAL_KEYBOARD,
- /* scancode= */ 0, /* flags= */ 0, /* source= */ 0);
+ /* scancode= */ 0, /* flags= */ 0, /* source= */ 0, /* characters= */ null);
}
/**
@@ -1478,7 +1478,7 @@ public class KeyEvent extends InputEvent implements Parcelable {
int code, int repeat) {
this(downTime, eventTime, action, code, repeat, /* metaState= */ 0,
KeyCharacterMap.VIRTUAL_KEYBOARD, /* scancode= */ 0, /* flags= */ 0,
- /* source= */ 0);
+ /* source= */ 0, /* characters= */ null);
}
/**
@@ -1498,7 +1498,7 @@ public class KeyEvent extends InputEvent implements Parcelable {
public KeyEvent(long downTime, long eventTime, int action,
int code, int repeat, int metaState) {
this(downTime, eventTime, action, code, repeat, metaState, KeyCharacterMap.VIRTUAL_KEYBOARD,
- /* scancode= */ 0, /* flags= */ 0, /* source= */ 0);
+ /* scancode= */ 0, /* flags= */ 0, /* source= */ 0, /* characters= */ null);
}
/**
@@ -1521,7 +1521,7 @@ public class KeyEvent extends InputEvent implements Parcelable {
int code, int repeat, int metaState,
int deviceId, int scancode) {
this(downTime, eventTime, action, code, repeat, metaState, deviceId, scancode,
- /* flags= */ 0, /* source= */ 0);
+ /* flags= */ 0, /* source= */ 0, /* characters= */ null);
}
/**
@@ -1545,7 +1545,7 @@ public class KeyEvent extends InputEvent implements Parcelable {
int code, int repeat, int metaState,
int deviceId, int scancode, int flags) {
this(downTime, eventTime, action, code, repeat, metaState, deviceId, scancode, flags,
- /* source= */ 0);
+ /* source= */ 0, /* characters= */ null);
}
/**
@@ -1569,7 +1569,13 @@ public class KeyEvent extends InputEvent implements Parcelable {
public KeyEvent(long downTime, long eventTime, int action,
int code, int repeat, int metaState,
int deviceId, int scancode, int flags, int source) {
- // NOTE: this is the canonical constructor, every other constructor that takes KeyEvent
+ this(downTime, eventTime, action, code, repeat, metaState, deviceId, scancode, flags,
+ source, /* characters= */ null);
+ }
+
+ private KeyEvent(long downTime, long eventTime, int action, int code, int repeat, int metaState,
+ int deviceId, int scancode, int flags, int source, @Nullable String characters) {
+ // NOTE: this is the canonical constructor, other constructors that takes KeyEvent
// attributes should call it
mId = nativeNextId();
mDownTime = TimeUnit.NANOSECONDS.convert(downTime, TimeUnit.MILLISECONDS);
@@ -1582,6 +1588,7 @@ public class KeyEvent extends InputEvent implements Parcelable {
mScanCode = scancode;
mFlags = flags;
mSource = source;
+ mCharacters = characters;
}
/**
@@ -1599,7 +1606,7 @@ public class KeyEvent extends InputEvent implements Parcelable {
public KeyEvent(long time, String characters, int deviceId, int flags) {
this(/* downTime= */ time, /* eventTime= */ time, ACTION_MULTIPLE, KEYCODE_UNKNOWN,
/* repeat= */ 0, /* metaState= */ 0, deviceId, /* scancode= */ 0, flags,
- /* source= */ InputDevice.SOURCE_KEYBOARD);
+ /* source= */ InputDevice.SOURCE_KEYBOARD, characters);
}
/**
diff --git a/core/java/android/view/MotionPredictor.java b/core/java/android/view/MotionPredictor.java
index 4d32efea9081..7d452f954fb0 100644
--- a/core/java/android/view/MotionPredictor.java
+++ b/core/java/android/view/MotionPredictor.java
@@ -17,14 +17,11 @@
package android.view;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
import libcore.util.NativeAllocationRegistry;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
/**
* Calculate motion predictions.
*
@@ -68,9 +65,12 @@ public final class MotionPredictor {
/**
* Record a movement so that in the future, a prediction for the current gesture can be
- * generated. Ensure to add all motions from the gesture of interest to generate correct
- * predictions.
+ * generated. Only gestures from one input device at a time should be provided to an instance of
+ * MotionPredictor.
+ *
* @param event The received event
+ *
+ * @throws IllegalArgumentException if an inconsistent MotionEvent stream is sent.
*/
public void record(@NonNull MotionEvent event) {
if (!isPredictionEnabled()) {
@@ -80,28 +80,24 @@ public final class MotionPredictor {
}
/**
- * Get predicted events for all gestures that have been provided to {@link #record}.
- * If events from multiple devices were sent to 'record', this will produce a separate
- * {@link MotionEvent} for each device. The returned list may be empty if no predictions for
- * any of the added events/devices are available.
+ * Get a predicted event for the gesture that has been provided to {@link #record}.
* Predictions may not reach the requested timestamp if the confidence in the prediction results
* is low.
*
* @param predictionTimeNanos The time that the prediction should target, in the
* {@link android.os.SystemClock#uptimeMillis} time base, but in nanoseconds.
*
- * @return A list of predicted motion events, with at most one for each device observed by
- * {@link #record}. Be sure to check the historical data in addition to the latest
- * ({@link MotionEvent#getX getX()}, {@link MotionEvent#getY getY()}) coordinates for smooth
- * prediction curves. An empty list is returned if predictions are not supported, or not
- * possible for the current set of gestures.
+ * @return The predicted motion event, or `null` if predictions are not supported, or not
+ * possible for the current gesture. Be sure to check the historical data in addition to the
+ * latest ({@link MotionEvent#getX getX()}, {@link MotionEvent#getY getY()}) coordinates for
+ * smooth prediction curves.
*/
- @NonNull
- public List<MotionEvent> predict(long predictionTimeNanos) {
+ @Nullable
+ public MotionEvent predict(long predictionTimeNanos) {
if (!isPredictionEnabled()) {
- return Collections.emptyList();
+ return null;
}
- return Arrays.asList(nativePredict(mPtr, predictionTimeNanos));
+ return nativePredict(mPtr, predictionTimeNanos);
}
private boolean isPredictionEnabled() {
@@ -129,7 +125,7 @@ public final class MotionPredictor {
private static native long nativeInitialize(int offsetNanos);
private static native void nativeRecord(long nativePtr, MotionEvent event);
- private static native MotionEvent[] nativePredict(long nativePtr, long predictionTimeNanos);
+ private static native MotionEvent nativePredict(long nativePtr, long predictionTimeNanos);
private static native boolean nativeIsPredictionAvailable(long nativePtr, int deviceId,
int source);
private static native long nativeGetNativeMotionPredictorFinalizer();
diff --git a/core/java/android/view/OWNERS b/core/java/android/view/OWNERS
index 9e1762065367..b574ecf32dd8 100644
--- a/core/java/android/view/OWNERS
+++ b/core/java/android/view/OWNERS
@@ -31,6 +31,7 @@ per-file Input*.java = file:/services/core/java/com/android/server/input/OWNERS
per-file Input*.aidl = file:/services/core/java/com/android/server/input/OWNERS
per-file KeyEvent.java = file:/services/core/java/com/android/server/input/OWNERS
per-file MotionEvent.java = file:/services/core/java/com/android/server/input/OWNERS
+per-file MotionPredictor.java = file:/services/core/java/com/android/server/input/OWNERS
per-file PointerIcon.java = file:/services/core/java/com/android/server/input/OWNERS
per-file SimulatedDpad.java = file:/services/core/java/com/android/server/input/OWNERS
per-file BatchedInputEventReceiver.java = file:/services/core/java/com/android/server/input/OWNERS
diff --git a/core/java/android/view/TaskTransitionSpec.java b/core/java/android/view/TaskTransitionSpec.java
index 5f498a19f196..9a2d3ba048fb 100644
--- a/core/java/android/view/TaskTransitionSpec.java
+++ b/core/java/android/view/TaskTransitionSpec.java
@@ -18,9 +18,6 @@ package android.view;
import android.os.Parcel;
import android.os.Parcelable;
-import android.util.ArraySet;
-
-import java.util.Set;
/**
* Holds information about how to execute task transition animations.
@@ -36,32 +33,12 @@ public class TaskTransitionSpec implements Parcelable {
*/
public final int backgroundColor;
- /**
- * TEMPORARY FIELD (b/202383002)
- * TODO: Remove once we use surfaceflinger rounded corners on tasks rather than taskbar overlays
- * or when shell transitions are fully enabled
- *
- * A set of {@InsetsState.InternalInsetsType}s we want to use as the source to set the bounds
- * of the task during the animation. Used to make sure that task animate above the taskbar.
- * Will also be used to crop to the frame size of the inset source to the inset size to prevent
- * the taskbar rounded corners overlay from being invisible during task transition animation.
- */
- public final Set<Integer> animationBoundInsets;
-
- public TaskTransitionSpec(
- int backgroundColor, Set<Integer> animationBoundInsets) {
+ public TaskTransitionSpec(int backgroundColor) {
this.backgroundColor = backgroundColor;
- this.animationBoundInsets = animationBoundInsets;
}
public TaskTransitionSpec(Parcel in) {
this.backgroundColor = in.readInt();
-
- int animationBoundInsetsSize = in.readInt();
- this.animationBoundInsets = new ArraySet<>(animationBoundInsetsSize);
- for (int i = 0; i < animationBoundInsetsSize; i++) {
- this.animationBoundInsets.add(in.readInt());
- }
}
@Override
@@ -72,11 +49,6 @@ public class TaskTransitionSpec implements Parcelable {
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(backgroundColor);
-
- dest.writeInt(animationBoundInsets.size());
- for (int insetType : animationBoundInsets) {
- dest.writeInt(insetType);
- }
}
public static final @android.annotation.NonNull Parcelable.Creator<TaskTransitionSpec>
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 7d18bf082bcb..869efc69872e 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3114,33 +3114,33 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* Accessibility interactions from services without {@code isAccessibilityTool} set to true are
* disallowed for any of the following conditions:
* <li>this view sets {@link #getFilterTouchesWhenObscured()}.</li>
- * <li>any parent of this view returns true from {@link #isAccessibilityDataPrivate()}.</li>
+ * <li>any parent of this view returns true from {@link #isAccessibilityDataSensitive()}.</li>
* </p>
*/
- public static final int ACCESSIBILITY_DATA_PRIVATE_AUTO = 0x00000000;
+ public static final int ACCESSIBILITY_DATA_SENSITIVE_AUTO = 0x00000000;
/**
* Only allow interactions from {@link android.accessibilityservice.AccessibilityService}s
* with the {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool}
* property set to true.
*/
- public static final int ACCESSIBILITY_DATA_PRIVATE_YES = 0x00000001;
+ public static final int ACCESSIBILITY_DATA_SENSITIVE_YES = 0x00000001;
/**
* Allow interactions from all {@link android.accessibilityservice.AccessibilityService}s,
* regardless of their
* {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property.
*/
- public static final int ACCESSIBILITY_DATA_PRIVATE_NO = 0x00000002;
+ public static final int ACCESSIBILITY_DATA_SENSITIVE_NO = 0x00000002;
/** @hide */
- @IntDef(prefix = { "ACCESSIBILITY_DATA_PRIVATE_" }, value = {
- ACCESSIBILITY_DATA_PRIVATE_AUTO,
- ACCESSIBILITY_DATA_PRIVATE_YES,
- ACCESSIBILITY_DATA_PRIVATE_NO,
+ @IntDef(prefix = { "ACCESSIBILITY_DATA_SENSITIVE_" }, value = {
+ ACCESSIBILITY_DATA_SENSITIVE_AUTO,
+ ACCESSIBILITY_DATA_SENSITIVE_YES,
+ ACCESSIBILITY_DATA_SENSITIVE_NO,
})
@Retention(RetentionPolicy.SOURCE)
- public @interface AccessibilityDataPrivate {}
+ public @interface AccessibilityDataSensitive {}
/**
* Mask for obtaining the bits which specify how to determine
@@ -4611,9 +4611,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property
* set to true.
*/
- private int mExplicitAccessibilityDataPrivate = ACCESSIBILITY_DATA_PRIVATE_AUTO;
- /** Used to calculate and cache {@link #isAccessibilityDataPrivate()}. */
- private int mInferredAccessibilityDataPrivate = ACCESSIBILITY_DATA_PRIVATE_AUTO;
+ private int mExplicitAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_AUTO;
+ /** Used to calculate and cache {@link #isAccessibilityDataSensitive()}. */
+ private int mInferredAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_AUTO;
/**
* Specifies the id of a view for which this view serves as a label for
@@ -5101,12 +5101,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
private boolean mHoveringTouchDelegate = false;
- /**
- * Configuration for this view to act as a handwriting initiation delegate. This allows
- * handwriting mode for a delegator editor view to be initiated by stylus movement on this
- * delegate view.
- */
- private HandwritingDelegateConfiguration mHandwritingDelegateConfiguration;
+ // These two fields are set if the view is a handwriting delegator.
+ private Runnable mHandwritingDelegatorCallback;
+ private String mAllowedHandwritingDelegatePackageName;
+
+ // These two fields are set if the view is a handwriting delegate.
+ private boolean mIsHandwritingDelegate;
+ private String mAllowedHandwritingDelegatorPackageName;
/**
* Solid color to use as a background when creating the drawing cache. Enables
@@ -6015,9 +6016,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
setImportantForAccessibility(a.getInt(attr,
IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
break;
- case R.styleable.View_accessibilityDataPrivate:
- setAccessibilityDataPrivate(a.getInt(attr,
- ACCESSIBILITY_DATA_PRIVATE_AUTO));
+ case R.styleable.View_accessibilityDataSensitive:
+ setAccessibilityDataSensitive(a.getInt(attr,
+ ACCESSIBILITY_DATA_SENSITIVE_AUTO));
break;
case R.styleable.View_accessibilityLiveRegion:
setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
@@ -8659,9 +8660,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* is responsible for handling this call.
* </p>
* <p>
- * If this view sets {@link #isAccessibilityDataPrivate()} then this view should only append
+ * If this view sets {@link #isAccessibilityDataSensitive()} then this view should only append
* sensitive information to an event that also sets
- * {@link AccessibilityEvent#isAccessibilityDataPrivate()}.
+ * {@link AccessibilityEvent#isAccessibilityDataSensitive()}.
* </p>
* <p>
* <em>Note:</em> Accessibility events of certain types are not dispatched for
@@ -10696,6 +10697,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
info.setVisibleToUser(isVisibleToUser());
info.setImportantForAccessibility(isImportantForAccessibility());
+ info.setAccessibilityDataSensitive(isAccessibilityDataSensitive());
info.setPackageName(mContext.getPackageName());
info.setClassName(getAccessibilityClassName());
info.setStateDescription(getStateDescription());
@@ -12410,27 +12412,143 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
- * Configures this view to act as a handwriting initiation delegate. This allows handwriting
- * mode for a delegator editor view to be initiated by stylus movement on this delegate view.
+ * Sets a callback which should be called when a stylus {@link MotionEvent} occurs within this
+ * view's bounds. The callback will be called from the UI thread.
+ *
+ * <p>Setting a callback allows this view to act as a handwriting delegator, so that handwriting
+ * mode for a delegate editor view can be initiated by stylus movement on this delegator view.
+ * The callback implementation is expected to show and focus the delegate editor view. If a view
+ * which returns {@code true} for {@link #isHandwritingDelegate()} creates an input connection
+ * while the same stylus {@link MotionEvent} sequence is ongoing, handwriting mode will be
+ * initiated for that view.
+ *
+ * <p>A common use case is a custom view which looks like a text editor but does not actually
+ * support text editing itself, and clicking on the custom view causes an EditText to be shown.
+ * To support handwriting initiation in this case, this method can be called on the custom view
+ * to configure it as a delegator. The EditText should call {@link #setIsHandwritingDelegate} to
+ * set it as a delegate. The {@code callback} implementation is typically the same as the click
+ * listener implementation which shows the EditText.
*
* <p>If {@code null} is passed, this view will no longer act as a handwriting initiation
- * delegate.
+ * delegator.
+ *
+ * @param callback a callback which should be called when a stylus {@link MotionEvent} occurs
+ * within this view's bounds
*/
- public void setHandwritingDelegateConfiguration(
- @Nullable HandwritingDelegateConfiguration configuration) {
- mHandwritingDelegateConfiguration = configuration;
- if (configuration != null) {
+ public void setHandwritingDelegatorCallback(@Nullable Runnable callback) {
+ mHandwritingDelegatorCallback = callback;
+ if (callback != null) {
setHandwritingArea(new Rect(0, 0, getWidth(), getHeight()));
}
}
/**
- * If this view has been configured as a handwriting initiation delegate, returns the delegate
- * configuration.
+ * Returns the callback set by {@link #setHandwritingDelegatorCallback} which should be called
+ * when a stylus {@link MotionEvent} occurs within this view's bounds. The callback should only
+ * be called from the UI thread.
+ */
+ @Nullable
+ public Runnable getHandwritingDelegatorCallback() {
+ return mHandwritingDelegatorCallback;
+ }
+
+ /**
+ * Specifies that this view may act as a handwriting initiation delegator for a delegate editor
+ * view from the specified package. If this method is not called, delegators may only be used to
+ * initiate handwriting mode for a delegate editor view from the same package as the delegator
+ * view. This method allows specifying a different trusted package which may contain a delegate
+ * editor view linked to this delegator view.
+ *
+ * <p>This method has no effect unless {@link #setHandwritingDelegatorCallback} is also called
+ * to configure this view to act as a handwriting delegator.
+ *
+ * <p>If this method is called on the delegator view, then {@link
+ * #setAllowedHandwritingDelegatorPackage} should also be called on the delegate editor view.
+ *
+ * <p>For example, to configure a delegator view in package 1:
+ *
+ * <pre>
+ * delegatorView.setHandwritingDelegatorCallback(callback);
+ * delegatorView.setAllowedHandwritingDelegatePackage(package2);</pre>
+ *
+ * Then to configure the corresponding delegate editor view in package 2:
+ *
+ * <pre>
+ * delegateEditorView.setIsHandwritingDelegate(true);
+ * delegateEditorView.setAllowedHandwritingDelegatorPackage(package1);</pre>
+ *
+ * @param allowedPackageName the package name of a delegate editor view linked to this delegator
+ * view, or {@code null} to restore the default behavior of only allowing delegate editor
+ * views from the same package as this delegator view
+ */
+ public void setAllowedHandwritingDelegatePackage(@Nullable String allowedPackageName) {
+ mAllowedHandwritingDelegatePackageName = allowedPackageName;
+ }
+
+ /**
+ * Returns the allowed package for delegate editor views for which this view may act as a
+ * handwriting delegator, as set by {@link #setAllowedHandwritingDelegatePackage}. If {@link
+ * #setAllowedHandwritingDelegatePackage} has not been called, or called with {@code null}
+ * argument, this will return {@code null}, meaning that this delegator view may only be used to
+ * initiate handwriting mode for a delegate editor view from the same package as this delegator
+ * view.
+ */
+ @Nullable
+ public String getAllowedHandwritingDelegatePackageName() {
+ return mAllowedHandwritingDelegatePackageName;
+ }
+
+ /**
+ * Sets this view to be a handwriting delegate. If a delegate view creates an input connection
+ * while a stylus {@link MotionEvent} sequence from a delegator view is ongoing, handwriting
+ * mode will be initiated for the delegate view.
+ *
+ * @param isHandwritingDelegate whether this view is a handwriting initiation delegate
+ * @see #setHandwritingDelegatorCallback(Runnable)
+ */
+ public void setIsHandwritingDelegate(boolean isHandwritingDelegate) {
+ mIsHandwritingDelegate = isHandwritingDelegate;
+ }
+
+ /**
+ * Returns whether this view has been set as a handwriting delegate by {@link
+ * #setIsHandwritingDelegate}.
+ */
+ public boolean isHandwritingDelegate() {
+ return mIsHandwritingDelegate;
+ }
+
+ /**
+ * Specifies that a view from the specified package may act as a handwriting delegator for this
+ * delegate editor view. If this method is not called, only views from the same package as this
+ * delegate editor view may act as a handwriting delegator. This method allows specifying a
+ * different trusted package which may contain a delegator view linked to this delegate editor
+ * view.
+ *
+ * <p>This method has no effect unless {@link #setIsHandwritingDelegate} is also called to
+ * configure this view to act as a handwriting delegate.
+ *
+ * <p>If this method is called on the delegate editor view, then {@link
+ * #setAllowedHandwritingDelegatePackage} should also be called on the delegator view.
+ *
+ * @param allowedPackageName the package name of a delegator view linked to this delegate editor
+ * view, or {@code null} to restore the default behavior of only allowing delegator views
+ * from the same package as this delegate editor view
+ */
+ public void setAllowedHandwritingDelegatorPackage(@Nullable String allowedPackageName) {
+ mAllowedHandwritingDelegatorPackageName = allowedPackageName;
+ }
+
+ /**
+ * Returns the allowed package for views which may act as a handwriting delegator for this
+ * delegate editor view, as set by {@link #setAllowedHandwritingDelegatorPackage}. If {@link
+ * #setAllowedHandwritingDelegatorPackage} has not been called, or called with {@code null}
+ * argument, this will return {@code null}, meaning that only views from the same package as
+ * this delegator editor view may act as a handwriting delegator.
*/
@Nullable
- public HandwritingDelegateConfiguration getHandwritingDelegateConfiguration() {
- return mHandwritingDelegateConfiguration;
+ public String getAllowedHandwritingDelegatorPackageName() {
+ return mAllowedHandwritingDelegatorPackageName;
}
/**
@@ -13464,7 +13582,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
public void setFilterTouchesWhenObscured(boolean enabled) {
setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
FILTER_TOUCHES_WHEN_OBSCURED);
- calculateAccessibilityDataPrivate();
+ calculateAccessibilityDataSensitive();
}
/**
@@ -14700,7 +14818,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// source View's AccessibilityDataPrivate value, and then filtering is done when
// AccessibilityManagerService propagates events to each recipient AccessibilityService.
if (!AccessibilityManager.getInstance(mContext).isRequestFromAccessibilityTool()
- && isAccessibilityDataPrivate()) {
+ && isAccessibilityDataSensitive()) {
return false;
}
}
@@ -14716,43 +14834,43 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* set to true.
*
* <p>
- * See default behavior provided by {@link #ACCESSIBILITY_DATA_PRIVATE_AUTO}. Otherwise,
- * returns true for {@link #ACCESSIBILITY_DATA_PRIVATE_YES} or false for {@link
- * #ACCESSIBILITY_DATA_PRIVATE_NO}.
+ * See default behavior provided by {@link #ACCESSIBILITY_DATA_SENSITIVE_AUTO}. Otherwise,
+ * returns true for {@link #ACCESSIBILITY_DATA_SENSITIVE_YES} or false for {@link
+ * #ACCESSIBILITY_DATA_SENSITIVE_NO}.
* </p>
*
* @return True if this view should restrict accessibility service access to services that have
* the isAccessibilityTool property.
*/
@ViewDebug.ExportedProperty(category = "accessibility")
- public boolean isAccessibilityDataPrivate() {
- if (mInferredAccessibilityDataPrivate == ACCESSIBILITY_DATA_PRIVATE_AUTO) {
- calculateAccessibilityDataPrivate();
+ public boolean isAccessibilityDataSensitive() {
+ if (mInferredAccessibilityDataSensitive == ACCESSIBILITY_DATA_SENSITIVE_AUTO) {
+ calculateAccessibilityDataSensitive();
}
- return mInferredAccessibilityDataPrivate == ACCESSIBILITY_DATA_PRIVATE_YES;
+ return mInferredAccessibilityDataSensitive == ACCESSIBILITY_DATA_SENSITIVE_YES;
}
/**
- * Calculate and cache the inferred value for {@link #isAccessibilityDataPrivate()}.
+ * Calculate and cache the inferred value for {@link #isAccessibilityDataSensitive()}.
*
* <p>
* <strong>Note:</strong> This method needs to be called any time one of the below conditions
* changes, to recalculate the new value.
* </p>
*/
- void calculateAccessibilityDataPrivate() {
+ void calculateAccessibilityDataSensitive() {
// Use the explicit value if set.
- if (mExplicitAccessibilityDataPrivate != ACCESSIBILITY_DATA_PRIVATE_AUTO) {
- mInferredAccessibilityDataPrivate = mExplicitAccessibilityDataPrivate;
+ if (mExplicitAccessibilityDataSensitive != ACCESSIBILITY_DATA_SENSITIVE_AUTO) {
+ mInferredAccessibilityDataSensitive = mExplicitAccessibilityDataSensitive;
} else if (getFilterTouchesWhenObscured()) {
- // Views that set filterTouchesWhenObscured default to accessibilityDataPrivate.
- mInferredAccessibilityDataPrivate = ACCESSIBILITY_DATA_PRIVATE_YES;
- } else if (mParent instanceof View && ((View) mParent).isAccessibilityDataPrivate()) {
- // Descendants of an accessibilityDataPrivate View are also accessibilityDataPrivate.
- mInferredAccessibilityDataPrivate = ACCESSIBILITY_DATA_PRIVATE_YES;
+ // Views that set filterTouchesWhenObscured default to accessibilityDataSensitive.
+ mInferredAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_YES;
+ } else if (mParent instanceof View && ((View) mParent).isAccessibilityDataSensitive()) {
+ // Descendants of accessibilityDataSensitive Views are also accessibilityDataSensitive.
+ mInferredAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_YES;
} else {
- // Otherwise, default to not accessibilityDataPrivate.
- mInferredAccessibilityDataPrivate = ACCESSIBILITY_DATA_PRIVATE_NO;
+ // Otherwise, default to not accessibilityDataSensitive.
+ mInferredAccessibilityDataSensitive = ACCESSIBILITY_DATA_SENSITIVE_NO;
}
}
@@ -14762,10 +14880,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property
* set to true.
*/
- public void setAccessibilityDataPrivate(
- @AccessibilityDataPrivate int accessibilityDataPrivate) {
- mExplicitAccessibilityDataPrivate = accessibilityDataPrivate;
- calculateAccessibilityDataPrivate();
+ public void setAccessibilityDataSensitive(
+ @AccessibilityDataSensitive int accessibilityDataSensitive) {
+ mExplicitAccessibilityDataSensitive = accessibilityDataSensitive;
+ calculateAccessibilityDataSensitive();
}
/**
@@ -24474,7 +24592,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
}
rebuildOutline();
- if (onCheckIsTextEditor() || mHandwritingDelegateConfiguration != null) {
+ if (onCheckIsTextEditor() || mHandwritingDelegatorCallback != null) {
setHandwritingArea(new Rect(0, 0, newWidth, newHeight));
}
}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 73d447141cc1..46ae3ea21890 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3921,10 +3921,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
@Override
- void calculateAccessibilityDataPrivate() {
- super.calculateAccessibilityDataPrivate();
+ void calculateAccessibilityDataSensitive() {
+ super.calculateAccessibilityDataSensitive();
for (int i = 0; i < mChildrenCount; i++) {
- mChildren[i].calculateAccessibilityDataPrivate();
+ mChildren[i].calculateAccessibilityDataSensitive();
}
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index e9b3e2808a6d..807af5b54081 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1136,7 +1136,7 @@ public final class ViewRootImpl implements ViewParent,
// Make sure to report the completion of draw for relaunch with preserved window.
reportNextDraw("rebuilt");
// Make sure to resume this root view when relaunching its host activity which was stopped.
- if (mStopped && getHostVisibility() != View.GONE) {
+ if (mStopped) {
setWindowStopped(false);
}
}
@@ -1650,6 +1650,7 @@ public final class ViewRootImpl implements ViewParent,
mAttachInfo.mThreadedRenderer = renderer;
renderer.setSurfaceControl(mSurfaceControl, mBlastBufferQueue);
updateColorModeIfNeeded(attrs.getColorMode());
+ updateRenderHdrSdrRatio();
updateForceDarkMode();
mAttachInfo.mHardwareAccelerated = true;
mAttachInfo.mHardwareAccelerationRequested = true;
@@ -5379,6 +5380,11 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ private void updateRenderHdrSdrRatio() {
+ mRenderHdrSdrRatio = mDisplay.getHdrSdrRatio();
+ mUpdateHdrSdrRatioInfo = true;
+ }
+
private void updateColorModeIfNeeded(@ActivityInfo.ColorMode int colorMode) {
if (mAttachInfo.mThreadedRenderer == null) {
return;
@@ -5396,8 +5402,7 @@ public final class ViewRootImpl implements ViewParent,
float desiredRatio = mAttachInfo.mThreadedRenderer.setColorMode(colorMode);
if (desiredRatio != mDesiredHdrSdrRatio) {
mDesiredHdrSdrRatio = desiredRatio;
- mRenderHdrSdrRatio = mDisplay.getHdrSdrRatio();
- mUpdateHdrSdrRatioInfo = true;
+ updateRenderHdrSdrRatio();
if (mDesiredHdrSdrRatio < 1.01f) {
mDisplay.unregisterHdrSdrRatioChangedListener(mHdrSdrRatioChangedListener);
@@ -8496,6 +8501,7 @@ public final class ViewRootImpl implements ViewParent,
if (mAttachInfo.mThreadedRenderer != null) {
mAttachInfo.mThreadedRenderer.setSurfaceControl(mSurfaceControl, mBlastBufferQueue);
}
+ updateRenderHdrSdrRatio();
if (mPreviousTransformHint != transformHint) {
mPreviousTransformHint = transformHint;
dispatchTransformHintChanged(transformHint);
@@ -10078,9 +10084,12 @@ public final class ViewRootImpl implements ViewParent,
}
void checkThread() {
- if (mThread != Thread.currentThread()) {
+ Thread current = Thread.currentThread();
+ if (mThread != current) {
throw new CalledFromWrongThreadException(
- "Only the original thread that created a view hierarchy can touch its views.");
+ "Only the original thread that created a view hierarchy can touch its views."
+ + " Expected: " + mThread.getName()
+ + " Calling: " + current.getName());
}
}
@@ -11382,6 +11391,10 @@ public final class ViewRootImpl implements ViewParent,
sendBackKeyEvent(KeyEvent.ACTION_DOWN);
sendBackKeyEvent(KeyEvent.ACTION_UP);
};
+ if (mOnBackInvokedDispatcher.hasImeOnBackInvokedDispatcher()) {
+ Log.d(TAG, "Skip registering CompatOnBackInvokedCallback on IME dispatcher");
+ return;
+ }
mOnBackInvokedDispatcher.registerOnBackInvokedCallback(
OnBackInvokedDispatcher.PRIORITY_DEFAULT, mCompatOnBackInvokedCallback);
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index e7cefd60002b..dfb11bcee5ed 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -454,6 +454,11 @@ public interface WindowManager extends ViewManager {
*/
int TRANSIT_WAKE = 11;
/**
+ * The screen is turning off. This is used as a message to stop all animations.
+ * @hide
+ */
+ int TRANSIT_SLEEP = 12;
+ /**
* The first slot for custom transition types. Callers (like Shell) can make use of custom
* transition types for dealing with special cases. These types are effectively ignored by
* Core and will just be passed along as part of TransitionInfo objects. An example is
@@ -462,7 +467,7 @@ public interface WindowManager extends ViewManager {
* implementation.
* @hide
*/
- int TRANSIT_FIRST_CUSTOM = 12;
+ int TRANSIT_FIRST_CUSTOM = 13;
/**
* @hide
@@ -480,6 +485,7 @@ public interface WindowManager extends ViewManager {
TRANSIT_KEYGUARD_UNOCCLUDE,
TRANSIT_PIP,
TRANSIT_WAKE,
+ TRANSIT_SLEEP,
TRANSIT_FIRST_CUSTOM
})
@Retention(RetentionPolicy.SOURCE)
@@ -817,6 +823,15 @@ public interface WindowManager extends ViewManager {
}
/**
+ * If the display {@link Configuration#smallestScreenWidthDp} is greater or equal to this value,
+ * we will treat it as a large screen device, which will have some multi window features enabled
+ * by default.
+ * @hide
+ */
+ @TestApi
+ int LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP = 600;
+
+ /**
* Application level {@link android.content.pm.PackageManager.Property PackageManager
* .Property} for an app to inform the system that the app can be opted-in or opted-out
* from the compatibility treatment that avoids {@link
@@ -1428,6 +1443,7 @@ public interface WindowManager extends ViewManager {
case TRANSIT_KEYGUARD_UNOCCLUDE: return "KEYGUARD_UNOCCLUDE";
case TRANSIT_PIP: return "PIP";
case TRANSIT_WAKE: return "WAKE";
+ case TRANSIT_SLEEP: return "SLEEP";
case TRANSIT_FIRST_CUSTOM: return "FIRST_CUSTOM";
default:
if (type > TRANSIT_FIRST_CUSTOM) {
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 33b763bbf0c0..0acc0228ade4 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -56,7 +56,7 @@ import java.util.List;
* accessibility service has not requested to retrieve the window content the event will
* not contain reference to its source. <strong>Note: </strong> for events of type
* {@link #TYPE_NOTIFICATION_STATE_CHANGED} the source is never available, and Views that set
- * {@link android.view.View#isAccessibilityDataPrivate()} may not populate all event properties on
+ * {@link android.view.View#isAccessibilityDataSensitive()} may not populate all event properties on
* events sent from higher up in the view hierarchy.
* </p>
* <p>
@@ -1168,17 +1168,17 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
* set to true.
*
* <p>
- * Initial value matches the {@link android.view.View#isAccessibilityDataPrivate} property from
- * the event's source node, if present, or false by default.
+ * Initial value matches the {@link android.view.View#isAccessibilityDataSensitive} property
+ * from the event's source node, if present, or false by default.
* </p>
*
* @return True if the event should be delivered only to isAccessibilityTool services, false
* otherwise.
- * @see #setAccessibilityDataPrivate
+ * @see #setAccessibilityDataSensitive
*/
@Override
- public boolean isAccessibilityDataPrivate() {
- return super.isAccessibilityDataPrivate();
+ public boolean isAccessibilityDataSensitive() {
+ return super.isAccessibilityDataSensitive();
}
/**
@@ -1193,13 +1193,13 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
* no source) then this method must be called explicitly if you want non-default behavior.
* </p>
*
- * @param accessibilityDataPrivate True if the event should be delivered only to
+ * @param accessibilityDataSensitive True if the event should be delivered only to
* isAccessibilityTool services, false otherwise.
* @throws IllegalStateException If called from an AccessibilityService.
*/
@Override
- public void setAccessibilityDataPrivate(boolean accessibilityDataPrivate) {
- super.setAccessibilityDataPrivate(accessibilityDataPrivate);
+ public void setAccessibilityDataSensitive(boolean accessibilityDataSensitive) {
+ super.setAccessibilityDataSensitive(accessibilityDataSensitive);
}
/**
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index aa631cfa5980..9504852f6e98 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -2068,12 +2068,14 @@ public final class AccessibilityManager {
* {@link android.view.Display#INVALID_DISPLAY}, or is already being proxy-ed.
*
* @throws SecurityException if the app does not hold the
- * {@link Manifest.permission#MANAGE_ACCESSIBILITY} permission.
+ * {@link Manifest.permission#MANAGE_ACCESSIBILITY} permission or the
+ * {@link Manifest.permission#CREATE_VIRTUAL_DEVICE} permission.
*
* @hide
*/
@SystemApi
- @RequiresPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
+ @RequiresPermission(allOf = {Manifest.permission.MANAGE_ACCESSIBILITY,
+ Manifest.permission.CREATE_VIRTUAL_DEVICE})
public boolean registerDisplayProxy(@NonNull AccessibilityDisplayProxy proxy) {
final IAccessibilityManager service;
synchronized (mLock) {
@@ -2096,12 +2098,14 @@ public final class AccessibilityManager {
* @return {@code true} if the proxy is successfully unregistered.
*
* @throws SecurityException if the app does not hold the
- * {@link Manifest.permission#MANAGE_ACCESSIBILITY} permission.
+ * {@link Manifest.permission#MANAGE_ACCESSIBILITY} permission or the
+ * {@link Manifest.permission#CREATE_VIRTUAL_DEVICE} permission.
*
* @hide
*/
@SystemApi
- @RequiresPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
+ @RequiresPermission(allOf = {Manifest.permission.MANAGE_ACCESSIBILITY,
+ Manifest.permission.CREATE_VIRTUAL_DEVICE})
public boolean unregisterDisplayProxy(@NonNull AccessibilityDisplayProxy proxy) {
final IAccessibilityManager service;
synchronized (mLock) {
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 247e0262d13f..9d82b7900689 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -834,6 +834,8 @@ public class AccessibilityNodeInfo implements Parcelable {
private static final int BOOLEAN_PROPERTY_REQUEST_TOUCH_PASSTHROUGH = 1 << 25;
+ private static final int BOOLEAN_PROPERTY_ACCESSIBILITY_DATA_SENSITIVE = 1 << 26;
+
/**
* Bits that provide the id of a virtual descendant of a view.
*/
@@ -2644,6 +2646,34 @@ public class AccessibilityNodeInfo implements Parcelable {
}
/**
+ * Gets if the node's accessibility data is considered sensitive.
+ *
+ * @return True if the node is editable, false otherwise.
+ * @see View#isAccessibilityDataSensitive()
+ */
+ public boolean isAccessibilityDataSensitive() {
+ return getBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_DATA_SENSITIVE);
+ }
+
+ /**
+ * Sets whether this node's accessibility data is considered sensitive.
+ *
+ * <p>
+ * <strong>Note:</strong> Cannot be called from an {@link AccessibilityService}.
+ * This class is made immutable before being delivered to an AccessibilityService.
+ * </p>
+ *
+ * @param accessibilityDataSensitive True if the node's accessibility data is considered
+ * sensitive.
+ * @throws IllegalStateException If called from an AccessibilityService.
+ * @see View#setAccessibilityDataSensitive
+ */
+ public void setAccessibilityDataSensitive(boolean accessibilityDataSensitive) {
+ setBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_DATA_SENSITIVE,
+ accessibilityDataSensitive);
+ }
+
+ /**
* If this node represents a visually distinct region of the screen that may update separately
* from the rest of the window, it is considered a pane. Set the pane title to indicate that
* the node is a pane, and to provide a title for it.
diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java
index 789c740bbba2..38b564ade07d 100644
--- a/core/java/android/view/accessibility/AccessibilityRecord.java
+++ b/core/java/android/view/accessibility/AccessibilityRecord.java
@@ -72,7 +72,7 @@ public class AccessibilityRecord {
private static final int PROPERTY_FULL_SCREEN = 0x00000080;
private static final int PROPERTY_SCROLLABLE = 0x00000100;
private static final int PROPERTY_IMPORTANT_FOR_ACCESSIBILITY = 0x00000200;
- private static final int PROPERTY_ACCESSIBILITY_DATA_PRIVATE = 0x00000400;
+ private static final int PROPERTY_ACCESSIBILITY_DATA_SENSITIVE = 0x00000400;
private static final int GET_SOURCE_PREFETCH_FLAGS =
AccessibilityNodeInfo.FLAG_PREFETCH_ANCESTORS
@@ -160,8 +160,8 @@ public class AccessibilityRecord {
important = root.isImportantForAccessibility();
rootViewId = root.getAccessibilityViewId();
mSourceWindowId = root.getAccessibilityWindowId();
- setBooleanProperty(PROPERTY_ACCESSIBILITY_DATA_PRIVATE,
- root.isAccessibilityDataPrivate());
+ setBooleanProperty(PROPERTY_ACCESSIBILITY_DATA_SENSITIVE,
+ root.isAccessibilityDataSensitive());
}
setBooleanProperty(PROPERTY_IMPORTANT_FOR_ACCESSIBILITY, important);
mSourceNodeId = AccessibilityNodeInfo.makeNodeId(rootViewId, virtualDescendantId);
@@ -391,20 +391,20 @@ public class AccessibilityRecord {
}
/**
- * @see AccessibilityEvent#isAccessibilityDataPrivate
+ * @see AccessibilityEvent#isAccessibilityDataSensitive
* @hide
*/
- boolean isAccessibilityDataPrivate() {
- return getBooleanProperty(PROPERTY_ACCESSIBILITY_DATA_PRIVATE);
+ boolean isAccessibilityDataSensitive() {
+ return getBooleanProperty(PROPERTY_ACCESSIBILITY_DATA_SENSITIVE);
}
/**
- * @see AccessibilityEvent#setAccessibilityDataPrivate
+ * @see AccessibilityEvent#setAccessibilityDataSensitive
* @hide
*/
- void setAccessibilityDataPrivate(boolean accessibilityDataPrivate) {
+ void setAccessibilityDataSensitive(boolean accessibilityDataSensitive) {
enforceNotSealed();
- setBooleanProperty(PROPERTY_ACCESSIBILITY_DATA_PRIVATE, accessibilityDataPrivate);
+ setBooleanProperty(PROPERTY_ACCESSIBILITY_DATA_SENSITIVE, accessibilityDataSensitive);
}
/**
@@ -962,7 +962,7 @@ public class AccessibilityRecord {
appendUnless(false, PROPERTY_FULL_SCREEN, builder);
appendUnless(false, PROPERTY_SCROLLABLE, builder);
appendUnless(false, PROPERTY_IMPORTANT_FOR_ACCESSIBILITY, builder);
- appendUnless(false, PROPERTY_ACCESSIBILITY_DATA_PRIVATE, builder);
+ appendUnless(false, PROPERTY_ACCESSIBILITY_DATA_SENSITIVE, builder);
append(builder, "BeforeText", mBeforeText);
append(builder, "FromIndex", mFromIndex);
@@ -996,8 +996,8 @@ public class AccessibilityRecord {
case PROPERTY_SCROLLABLE: return "Scrollable";
case PROPERTY_IMPORTANT_FOR_ACCESSIBILITY:
return "ImportantForAccessibility";
- case PROPERTY_ACCESSIBILITY_DATA_PRIVATE:
- return "AccessibilityDataPrivate";
+ case PROPERTY_ACCESSIBILITY_DATA_SENSITIVE:
+ return "AccessibilityDataSensitive";
default: return Integer.toHexString(prop);
}
}
diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.java b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
index d84e0fb421cf..13ac329815f5 100644
--- a/core/java/android/view/accessibility/AccessibilityWindowInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
@@ -839,6 +839,7 @@ public final class AccessibilityWindowInfo implements Parcelable {
mConnectionId = UNDEFINED_WINDOW_ID;
mAnchorId = AccessibilityNodeInfo.UNDEFINED_NODE_ID;
mTitle = null;
+ mTransitionTime = 0;
}
/**
diff --git a/core/java/android/view/accessibility/DirectAccessibilityConnection.java b/core/java/android/view/accessibility/DirectAccessibilityConnection.java
index 8a3bb6fda361..25f5b8cd0270 100644
--- a/core/java/android/view/accessibility/DirectAccessibilityConnection.java
+++ b/core/java/android/view/accessibility/DirectAccessibilityConnection.java
@@ -50,13 +50,13 @@ import android.os.RemoteException;
class DirectAccessibilityConnection extends IAccessibilityServiceConnection.Default {
private final IAccessibilityInteractionConnection mAccessibilityInteractionConnection;
private final AccessibilityManager mAccessibilityManager;
+ private final int mMyProcessId;
// Fetch all views, but do not use prefetching/cache since this "connection" does not
// receive cache invalidation events (as it is not linked to an AccessibilityService).
private static final int FETCH_FLAGS =
AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS
| AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS;
- private static final int PID = Process.myPid();
private static final Region INTERACTIVE_REGION = null;
DirectAccessibilityConnection(
@@ -64,6 +64,7 @@ class DirectAccessibilityConnection extends IAccessibilityServiceConnection.Defa
AccessibilityManager accessibilityManager) {
mAccessibilityInteractionConnection = accessibilityInteractionConnection;
mAccessibilityManager = accessibilityManager;
+ mMyProcessId = Process.myPid();
}
@Override
@@ -74,8 +75,9 @@ class DirectAccessibilityConnection extends IAccessibilityServiceConnection.Defa
IAccessibilityManager.WindowTransformationSpec spec =
mAccessibilityManager.getWindowTransformationSpec(accessibilityWindowId);
mAccessibilityInteractionConnection.findAccessibilityNodeInfoByAccessibilityId(
- accessibilityNodeId, INTERACTIVE_REGION, interactionId, callback, FETCH_FLAGS, PID,
- threadId, spec.magnificationSpec, spec.transformationMatrix, arguments);
+ accessibilityNodeId, INTERACTIVE_REGION, interactionId, callback, FETCH_FLAGS,
+ mMyProcessId, threadId, spec.magnificationSpec, spec.transformationMatrix,
+ arguments);
return new String[0];
}
@@ -87,8 +89,8 @@ class DirectAccessibilityConnection extends IAccessibilityServiceConnection.Defa
IAccessibilityManager.WindowTransformationSpec spec =
mAccessibilityManager.getWindowTransformationSpec(accessibilityWindowId);
mAccessibilityInteractionConnection.findAccessibilityNodeInfosByText(accessibilityNodeId,
- text, INTERACTIVE_REGION, interactionId, callback, FETCH_FLAGS, PID, threadId,
- spec.magnificationSpec, spec.transformationMatrix);
+ text, INTERACTIVE_REGION, interactionId, callback, FETCH_FLAGS, mMyProcessId,
+ threadId, spec.magnificationSpec, spec.transformationMatrix);
return new String[0];
}
@@ -100,8 +102,8 @@ class DirectAccessibilityConnection extends IAccessibilityServiceConnection.Defa
IAccessibilityManager.WindowTransformationSpec spec =
mAccessibilityManager.getWindowTransformationSpec(accessibilityWindowId);
mAccessibilityInteractionConnection.findAccessibilityNodeInfosByViewId(accessibilityNodeId,
- viewId, INTERACTIVE_REGION, interactionId, callback, FETCH_FLAGS, PID, threadId,
- spec.magnificationSpec, spec.transformationMatrix);
+ viewId, INTERACTIVE_REGION, interactionId, callback, FETCH_FLAGS, mMyProcessId,
+ threadId, spec.magnificationSpec, spec.transformationMatrix);
return new String[0];
}
@@ -112,7 +114,7 @@ class DirectAccessibilityConnection extends IAccessibilityServiceConnection.Defa
IAccessibilityManager.WindowTransformationSpec spec =
mAccessibilityManager.getWindowTransformationSpec(accessibilityWindowId);
mAccessibilityInteractionConnection.findFocus(accessibilityNodeId, focusType,
- INTERACTIVE_REGION, interactionId, callback, FETCH_FLAGS, PID, threadId,
+ INTERACTIVE_REGION, interactionId, callback, FETCH_FLAGS, mMyProcessId, threadId,
spec.magnificationSpec, spec.transformationMatrix);
return new String[0];
}
@@ -124,7 +126,7 @@ class DirectAccessibilityConnection extends IAccessibilityServiceConnection.Defa
IAccessibilityManager.WindowTransformationSpec spec =
mAccessibilityManager.getWindowTransformationSpec(accessibilityWindowId);
mAccessibilityInteractionConnection.focusSearch(accessibilityNodeId, direction,
- INTERACTIVE_REGION, interactionId, callback, FETCH_FLAGS, PID, threadId,
+ INTERACTIVE_REGION, interactionId, callback, FETCH_FLAGS, mMyProcessId, threadId,
spec.magnificationSpec, spec.transformationMatrix);
return new String[0];
}
@@ -135,7 +137,7 @@ class DirectAccessibilityConnection extends IAccessibilityServiceConnection.Defa
IAccessibilityInteractionConnectionCallback callback, long threadId)
throws RemoteException {
mAccessibilityInteractionConnection.performAccessibilityAction(accessibilityNodeId, action,
- arguments, interactionId, callback, FETCH_FLAGS, PID, threadId);
+ arguments, interactionId, callback, FETCH_FLAGS, mMyProcessId, threadId);
return true;
}
}
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index bdc7333f2751..aef0e651ff8d 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -899,9 +899,10 @@ public final class AutofillManager {
// 3. Get the activity names substring between the indexes
final int activityStringStartIndex = packageInStringIndex + packageName.length() + 1;
- if (activityStringStartIndex < firstNextSemicolonIndex) {
+ if (activityStringStartIndex >= firstNextSemicolonIndex) {
Log.e(TAG, "Failed to get denied activity names from denylist because it's wrongly "
+ "formatted");
+ return;
}
final String activitySubstring =
denyListString.substring(activityStringStartIndex, firstNextSemicolonIndex);
diff --git a/core/java/android/view/autofill/OWNERS b/core/java/android/view/autofill/OWNERS
index 26c59a68fd53..622b0e208812 100644
--- a/core/java/android/view/autofill/OWNERS
+++ b/core/java/android/view/autofill/OWNERS
@@ -1,10 +1,6 @@
# Bug component: 351486
-augale@google.com
-haoranzhang@google.com
-joannechung@google.com
-markpun@google.com
-lpeter@google.com
simranjit@google.com
-tymtsai@google.com
+haoranzhang@google.com
+skxu@google.com
yunicorn@google.com
diff --git a/core/java/android/view/contentcapture/ContentCaptureContext.java b/core/java/android/view/contentcapture/ContentCaptureContext.java
index 59b5286f6fc5..34c7b8b9889f 100644
--- a/core/java/android/view/contentcapture/ContentCaptureContext.java
+++ b/core/java/android/view/contentcapture/ContentCaptureContext.java
@@ -82,11 +82,19 @@ public final class ContentCaptureContext implements Parcelable {
@SystemApi
public static final int FLAG_RECONNECTED = 0x4;
+ /**
+ * Flag used to disable flush when receiving a VIEW_TREE_APPEARING event.
+ *
+ * @hide
+ */
+ public static final int FLAG_DISABLED_FLUSH_FOR_VIEW_TREE_APPEARING = 1 << 3;
+
/** @hide */
@IntDef(flag = true, prefix = { "FLAG_" }, value = {
FLAG_DISABLED_BY_APP,
FLAG_DISABLED_BY_FLAG_SECURE,
- FLAG_RECONNECTED
+ FLAG_RECONNECTED,
+ FLAG_DISABLED_FLUSH_FOR_VIEW_TREE_APPEARING
})
@Retention(RetentionPolicy.SOURCE)
@interface ContextCreationFlags{}
@@ -252,7 +260,8 @@ public final class ContentCaptureContext implements Parcelable {
* Gets the flags associated with this context.
*
* @return any combination of {@link #FLAG_DISABLED_BY_FLAG_SECURE},
- * {@link #FLAG_DISABLED_BY_APP} and {@link #FLAG_RECONNECTED}.
+ * {@link #FLAG_DISABLED_BY_APP}, {@link #FLAG_RECONNECTED} and {@link
+ * #FLAG_DISABLED_FLUSH_FOR_VIEW_TREE_APPEARING}.
*
* @hide
*/
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index 497f0668107f..668351b949c1 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -51,6 +51,7 @@ import android.view.WindowManager;
import android.view.contentcapture.ContentCaptureSession.FlushReason;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.SyncResultReceiver;
import java.io.PrintWriter;
@@ -343,6 +344,14 @@ public final class ContentCaptureManager {
*/
public static final String DEVICE_CONFIG_PROPERTY_IDLE_UNBIND_TIMEOUT = "idle_unbind_timeout";
+ /**
+ * Sets to disable flush when receiving a VIEW_TREE_APPEARING event.
+ *
+ * @hide
+ */
+ public static final String DEVICE_CONFIG_PROPERTY_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING =
+ "disable_flush_for_view_tree_appearing";
+
/** @hide */
@TestApi
public static final int LOGGING_LEVEL_OFF = 0;
@@ -373,6 +382,8 @@ public final class ContentCaptureManager {
public static final int DEFAULT_TEXT_CHANGE_FLUSHING_FREQUENCY_MS = 1_000;
/** @hide */
public static final int DEFAULT_LOG_HISTORY_SIZE = 10;
+ /** @hide */
+ public static final boolean DEFAULT_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING = false;
private final Object mLock = new Object();
@@ -448,6 +459,7 @@ public final class ContentCaptureManager {
mOptions = Objects.requireNonNull(options, "options cannot be null");
ContentCaptureHelper.setLoggingLevel(mOptions.loggingLevel);
+ setFlushViewTreeAppearingEventDisabled(mOptions.disableFlushForViewTreeAppearing);
if (sVerbose) Log.v(TAG, "Constructor for " + context.getPackageName());
@@ -687,6 +699,38 @@ public final class ContentCaptureManager {
}
/**
+ * Explicitly sets enable or disable flush for view tree appearing event.
+ *
+ * @hide
+ */
+ @VisibleForTesting
+ public void setFlushViewTreeAppearingEventDisabled(boolean disabled) {
+ if (sDebug) {
+ Log.d(TAG, "setFlushViewTreeAppearingEventDisabled(): setting to " + disabled);
+ }
+
+ synchronized (mLock) {
+ if (disabled) {
+ mFlags |= ContentCaptureContext.FLAG_DISABLED_FLUSH_FOR_VIEW_TREE_APPEARING;
+ } else {
+ mFlags &= ~ContentCaptureContext.FLAG_DISABLED_FLUSH_FOR_VIEW_TREE_APPEARING;
+ }
+ }
+ }
+
+ /**
+ * Gets whether content capture is needed to flush for view tree appearing event.
+ *
+ * @hide
+ */
+ public boolean getFlushViewTreeAppearingEventDisabled() {
+ synchronized (mLock) {
+ return (mFlags & ContentCaptureContext.FLAG_DISABLED_FLUSH_FOR_VIEW_TREE_APPEARING)
+ != 0;
+ }
+ }
+
+ /**
* Gets whether content capture is enabled for the given user.
*
* <p>This method is typically used by the content capture service settings page, so it can
diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java
index 0da7e3b95863..62044aa78213 100644
--- a/core/java/android/view/contentcapture/ContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ContentCaptureSession.java
@@ -177,7 +177,15 @@ public abstract class ContentCaptureSession implements AutoCloseable {
public static final int FLUSH_REASON_SESSION_CONNECTED = 7;
/** @hide */
public static final int FLUSH_REASON_FORCE_FLUSH = 8;
+ /** @hide */
+ public static final int FLUSH_REASON_VIEW_TREE_APPEARING = 9;
+ /** @hide */
+ public static final int FLUSH_REASON_VIEW_TREE_APPEARED = 10;
+ /**
+ * After {@link UPSIDE_DOWN_CAKE}, {@link #notifyViewsDisappeared(AutofillId, long[])} wraps
+ * the virtual children with a pair of view tree appearing and view tree appeared events.
+ */
@ChangeId
@EnabledSince(targetSdkVersion = UPSIDE_DOWN_CAKE)
static final long NOTIFY_NODES_DISAPPEAR_NOW_SENDS_TREE_EVENTS = 258825825L;
@@ -191,7 +199,9 @@ public abstract class ContentCaptureSession implements AutoCloseable {
FLUSH_REASON_IDLE_TIMEOUT,
FLUSH_REASON_TEXT_CHANGE_TIMEOUT,
FLUSH_REASON_SESSION_CONNECTED,
- FLUSH_REASON_FORCE_FLUSH
+ FLUSH_REASON_FORCE_FLUSH,
+ FLUSH_REASON_VIEW_TREE_APPEARING,
+ FLUSH_REASON_VIEW_TREE_APPEARED
})
@Retention(RetentionPolicy.SOURCE)
public @interface FlushReason{}
@@ -671,6 +681,10 @@ public abstract class ContentCaptureSession implements AutoCloseable {
return "CONNECTED";
case FLUSH_REASON_FORCE_FLUSH:
return "FORCE_FLUSH";
+ case FLUSH_REASON_VIEW_TREE_APPEARING:
+ return "VIEW_TREE_APPEARING";
+ case FLUSH_REASON_VIEW_TREE_APPEARED:
+ return "VIEW_TREE_APPEARED";
default:
return "UNKOWN-" + reason;
}
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index 8c040e482cdf..6ddfcb825acc 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -458,6 +458,12 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
case ContentCaptureEvent.TYPE_SESSION_FINISHED:
flushReason = FLUSH_REASON_SESSION_FINISHED;
break;
+ case ContentCaptureEvent.TYPE_VIEW_TREE_APPEARING:
+ flushReason = FLUSH_REASON_VIEW_TREE_APPEARING;
+ break;
+ case ContentCaptureEvent.TYPE_VIEW_TREE_APPEARED:
+ flushReason = FLUSH_REASON_VIEW_TREE_APPEARED;
+ break;
default:
flushReason = forceFlush ? FLUSH_REASON_FORCE_FLUSH : FLUSH_REASON_FULL;
}
@@ -774,7 +780,11 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
/** Public because is also used by ViewRootImpl */
public void notifyViewTreeEvent(int sessionId, boolean started) {
final int type = started ? TYPE_VIEW_TREE_APPEARING : TYPE_VIEW_TREE_APPEARED;
- mHandler.post(() -> sendEvent(new ContentCaptureEvent(sessionId, type), FORCE_FLUSH));
+ final boolean disableFlush = mManager.getFlushViewTreeAppearingEventDisabled();
+
+ mHandler.post(() -> sendEvent(
+ new ContentCaptureEvent(sessionId, type),
+ disableFlush ? !started : FORCE_FLUSH));
}
void notifySessionResumed(int sessionId) {
diff --git a/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java b/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java
index 966026198a21..d84acc03826b 100644
--- a/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java
+++ b/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java
@@ -25,6 +25,7 @@ import android.annotation.RequiresNoPermission;
import android.annotation.RequiresPermission;
import android.annotation.UserIdInt;
import android.content.Context;
+import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ResultReceiver;
@@ -33,6 +34,7 @@ import android.view.WindowManager;
import android.window.ImeOnBackInvokedDispatcher;
import com.android.internal.inputmethod.DirectBootAwareness;
+import com.android.internal.inputmethod.IImeTracker;
import com.android.internal.inputmethod.IInputMethodClient;
import com.android.internal.inputmethod.IRemoteAccessibilityInputConnection;
import com.android.internal.inputmethod.IRemoteInputConnection;
@@ -40,7 +42,6 @@ import com.android.internal.inputmethod.InputBindResult;
import com.android.internal.inputmethod.SoftInputShowHideReason;
import com.android.internal.inputmethod.StartInputFlags;
import com.android.internal.inputmethod.StartInputReason;
-import com.android.internal.view.IImeTracker;
import com.android.internal.view.IInputMethodManager;
import java.util.ArrayList;
@@ -505,6 +506,40 @@ final class IInputMethodManagerGlobalInvoker {
}
@AnyThread
+ static void prepareStylusHandwritingDelegation(
+ @NonNull IInputMethodClient client,
+ @NonNull String delegatePackageName,
+ @NonNull String delegatorPackageName) {
+ final IInputMethodManager service = getService();
+ if (service == null) {
+ return;
+ }
+ try {
+ service.prepareStylusHandwritingDelegation(
+ client, delegatePackageName, delegatorPackageName);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ @AnyThread
+ static boolean acceptStylusHandwritingDelegation(
+ @NonNull IInputMethodClient client,
+ @NonNull String delegatePackageName,
+ @NonNull String delegatorPackageName) {
+ final IInputMethodManager service = getService();
+ if (service == null) {
+ return false;
+ }
+ try {
+ return service.acceptStylusHandwritingDelegation(
+ client, delegatePackageName, delegatorPackageName);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ @AnyThread
@RequiresPermission(value = Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional = true)
static boolean isStylusHandwritingAvailableAsUser(@UserIdInt int userId) {
final IInputMethodManager service = getService();
@@ -547,51 +582,57 @@ final class IInputMethodManagerGlobalInvoker {
}
}
+ /** @see com.android.server.inputmethod.ImeTrackerService#onRequestShow */
@AnyThread
- @Nullable
- static IBinder onRequestShow(int uid, @ImeTracker.Origin int origin,
- @SoftInputShowHideReason int reason) {
+ @NonNull
+ static ImeTracker.Token onRequestShow(@NonNull String tag, int uid,
+ @ImeTracker.Origin int origin, @SoftInputShowHideReason int reason) {
final IImeTracker service = getImeTrackerService();
if (service == null) {
- return null;
+ // Create token with "fake" binder if the service was not found.
+ return new ImeTracker.Token(new Binder(), tag);
}
try {
- return service.onRequestShow(uid, origin, reason);
+ return service.onRequestShow(tag, uid, origin, reason);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
+ /** @see com.android.server.inputmethod.ImeTrackerService#onRequestHide */
@AnyThread
- @Nullable
- static IBinder onRequestHide(int uid, @ImeTracker.Origin int origin,
- @SoftInputShowHideReason int reason) {
+ @NonNull
+ static ImeTracker.Token onRequestHide(@NonNull String tag, int uid,
+ @ImeTracker.Origin int origin, @SoftInputShowHideReason int reason) {
final IImeTracker service = getImeTrackerService();
if (service == null) {
- return null;
+ // Create token with "fake" binder if the service was not found.
+ return new ImeTracker.Token(new Binder(), tag);
}
try {
- return service.onRequestHide(uid, origin, reason);
+ return service.onRequestHide(tag, uid, origin, reason);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
+ /** @see com.android.server.inputmethod.ImeTrackerService#onProgress */
@AnyThread
- static void onProgress(@NonNull IBinder statsToken, @ImeTracker.Phase int phase) {
+ static void onProgress(@NonNull IBinder binder, @ImeTracker.Phase int phase) {
final IImeTracker service = getImeTrackerService();
if (service == null) {
return;
}
try {
- service.onProgress(statsToken, phase);
+ service.onProgress(binder, phase);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
+ /** @see com.android.server.inputmethod.ImeTrackerService#onFailed */
@AnyThread
- static void onFailed(@NonNull IBinder statsToken, @ImeTracker.Phase int phase) {
+ static void onFailed(@NonNull ImeTracker.Token statsToken, @ImeTracker.Phase int phase) {
final IImeTracker service = getImeTrackerService();
if (service == null) {
return;
@@ -603,8 +644,9 @@ final class IInputMethodManagerGlobalInvoker {
}
}
+ /** @see com.android.server.inputmethod.ImeTrackerService#onCancelled */
@AnyThread
- static void onCancelled(@NonNull IBinder statsToken, @ImeTracker.Phase int phase) {
+ static void onCancelled(@NonNull ImeTracker.Token statsToken, @ImeTracker.Phase int phase) {
final IImeTracker service = getImeTrackerService();
if (service == null) {
return;
@@ -616,8 +658,9 @@ final class IInputMethodManagerGlobalInvoker {
}
}
+ /** @see com.android.server.inputmethod.ImeTrackerService#onShown */
@AnyThread
- static void onShown(@NonNull IBinder statsToken) {
+ static void onShown(@NonNull ImeTracker.Token statsToken) {
final IImeTracker service = getImeTrackerService();
if (service == null) {
return;
@@ -629,8 +672,9 @@ final class IInputMethodManagerGlobalInvoker {
}
}
+ /** @see com.android.server.inputmethod.ImeTrackerService#onHidden */
@AnyThread
- static void onHidden(@NonNull IBinder statsToken) {
+ static void onHidden(@NonNull ImeTracker.Token statsToken) {
final IImeTracker service = getImeTrackerService();
if (service == null) {
return;
@@ -642,6 +686,7 @@ final class IInputMethodManagerGlobalInvoker {
}
}
+ /** @see com.android.server.inputmethod.ImeTrackerService#hasPendingImeVisibilityRequests */
@AnyThread
@RequiresPermission(Manifest.permission.TEST_INPUT_METHOD)
static boolean hasPendingImeVisibilityRequests() {
diff --git a/core/java/android/view/inputmethod/ImeTracker.java b/core/java/android/view/inputmethod/ImeTracker.java
index e5a99ff8566b..f0d1019ffb06 100644
--- a/core/java/android/view/inputmethod/ImeTracker.java
+++ b/core/java/android/view/inputmethod/ImeTracker.java
@@ -26,7 +26,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityThread;
import android.content.Context;
-import android.os.Binder;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
@@ -47,7 +46,7 @@ import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Locale;
import java.util.Map;
-import java.util.Random;
+import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
/** @hide */
@@ -321,9 +320,8 @@ public interface ImeTracker {
/**
* Creates an IME show request tracking token.
*
- * @param component the component name where the IME show request was created,
- * or {@code null} otherwise
- * (defaulting to {@link ActivityThread#currentProcessName()}).
+ * @param component the name of the component that created the IME request, or {@code null}
+ * otherwise (defaulting to {@link ActivityThread#currentProcessName()}).
* @param uid the uid of the client that requested the IME.
* @param origin the origin of the IME show request.
* @param reason the reason why the IME show request was created.
@@ -337,9 +335,8 @@ public interface ImeTracker {
/**
* Creates an IME hide request tracking token.
*
- * @param component the component name where the IME hide request was created,
- * or {@code null} otherwise
- * (defaulting to {@link ActivityThread#currentProcessName()}).
+ * @param component the name of the component that created the IME request, or {@code null}
+ * otherwise (defaulting to {@link ActivityThread#currentProcessName()}).
* @param uid the uid of the client that requested the IME.
* @param origin the origin of the IME hide request.
* @param reason the reason why the IME hide request was created.
@@ -435,8 +432,7 @@ public interface ImeTracker {
mLogProgress = SystemProperties.getBoolean("persist.debug.imetracker", false);
// Update logging flag dynamically.
SystemProperties.addChangeCallback(() ->
- mLogProgress =
- SystemProperties.getBoolean("persist.debug.imetracker", false));
+ mLogProgress = SystemProperties.getBoolean("persist.debug.imetracker", false));
}
/** Whether progress should be logged. */
@@ -446,10 +442,9 @@ public interface ImeTracker {
@Override
public Token onRequestShow(@Nullable String component, int uid, @Origin int origin,
@SoftInputShowHideReason int reason) {
- IBinder binder = IInputMethodManagerGlobalInvoker.onRequestShow(uid, origin, reason);
- if (binder == null) binder = new Binder();
-
- final Token token = Token.build(binder, component);
+ final var tag = getTag(component);
+ final var token = IInputMethodManagerGlobalInvoker.onRequestShow(tag, uid, origin,
+ reason);
Log.i(TAG, token.mTag + ": onRequestShow at " + Debug.originToString(origin)
+ " reason " + InputMethodDebug.softInputDisplayReasonToString(reason));
@@ -461,10 +456,9 @@ public interface ImeTracker {
@Override
public Token onRequestHide(@Nullable String component, int uid, @Origin int origin,
@SoftInputShowHideReason int reason) {
- IBinder binder = IInputMethodManagerGlobalInvoker.onRequestHide(uid, origin, reason);
- if (binder == null) binder = new Binder();
-
- final Token token = Token.build(binder, component);
+ final var tag = getTag(component);
+ final var token = IInputMethodManagerGlobalInvoker.onRequestHide(tag, uid, origin,
+ reason);
Log.i(TAG, token.mTag + ": onRequestHide at " + Debug.originToString(origin)
+ " reason " + InputMethodDebug.softInputDisplayReasonToString(reason));
@@ -485,7 +479,7 @@ public interface ImeTracker {
@Override
public void onFailed(@Nullable Token token, @Phase int phase) {
if (token == null) return;
- IInputMethodManagerGlobalInvoker.onFailed(token.mBinder, phase);
+ IInputMethodManagerGlobalInvoker.onFailed(token, phase);
Log.i(TAG, token.mTag + ": onFailed at " + Debug.phaseToString(phase));
}
@@ -499,7 +493,7 @@ public interface ImeTracker {
@Override
public void onCancelled(@Nullable Token token, @Phase int phase) {
if (token == null) return;
- IInputMethodManagerGlobalInvoker.onCancelled(token.mBinder, phase);
+ IInputMethodManagerGlobalInvoker.onCancelled(token, phase);
Log.i(TAG, token.mTag + ": onCancelled at " + Debug.phaseToString(phase));
}
@@ -507,7 +501,7 @@ public interface ImeTracker {
@Override
public void onShown(@Nullable Token token) {
if (token == null) return;
- IInputMethodManagerGlobalInvoker.onShown(token.mBinder);
+ IInputMethodManagerGlobalInvoker.onShown(token);
Log.i(TAG, token.mTag + ": onShown");
}
@@ -515,10 +509,24 @@ public interface ImeTracker {
@Override
public void onHidden(@Nullable Token token) {
if (token == null) return;
- IInputMethodManagerGlobalInvoker.onHidden(token.mBinder);
+ IInputMethodManagerGlobalInvoker.onHidden(token);
Log.i(TAG, token.mTag + ": onHidden");
}
+
+ /**
+ * Returns a logging tag using the given component name.
+ *
+ * @param component the name of the component that created the IME request, or {@code null}
+ * otherwise (defaulting to {@link ActivityThread#currentProcessName()}).
+ */
+ @NonNull
+ private String getTag(@Nullable String component) {
+ if (component == null) {
+ component = ActivityThread.currentProcessName();
+ }
+ return component + ":" + Integer.toHexString(ThreadLocalRandom.current().nextInt());
+ }
};
/** The singleton IME tracker instance for instrumenting jank metrics. */
@@ -528,28 +536,31 @@ public interface ImeTracker {
ImeLatencyTracker LATENCY_TRACKER = new ImeLatencyTracker();
/** A token that tracks the progress of an IME request. */
- class Token implements Parcelable {
+ final class Token implements Parcelable {
+ /** The binder used to identify this token. */
@NonNull
- public final IBinder mBinder;
+ private final IBinder mBinder;
+ /** Logging tag, of the shape "component:random_hexadecimal". */
@NonNull
private final String mTag;
- @NonNull
- private static Token build(@NonNull IBinder binder, @Nullable String component) {
- if (component == null) component = ActivityThread.currentProcessName();
- final String tag = component + ":" + Integer.toHexString((new Random().nextInt()));
+ public Token(@NonNull IBinder binder, @NonNull String tag) {
+ mBinder = binder;
+ mTag = tag;
+ }
- return new Token(binder, tag);
+ private Token(@NonNull Parcel in) {
+ mBinder = in.readStrongBinder();
+ mTag = in.readString8();
}
- private Token(@NonNull IBinder binder, @NonNull String tag) {
- mBinder = binder;
- mTag = tag;
+ @NonNull
+ public IBinder getBinder() {
+ return mBinder;
}
- /** Returns the {@link Token#mTag} */
@NonNull
public String getTag() {
return mTag;
@@ -562,7 +573,7 @@ public interface ImeTracker {
}
@Override
- public void writeToParcel(Parcel dest, int flags) {
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeStrongBinder(mBinder);
dest.writeString8(mTag);
}
@@ -571,12 +582,11 @@ public interface ImeTracker {
public static final Creator<Token> CREATOR = new Creator<>() {
@NonNull
@Override
- public Token createFromParcel(Parcel source) {
- final IBinder binder = source.readStrongBinder();
- final String tag = source.readString8();
- return new Token(binder, tag);
+ public Token createFromParcel(@NonNull Parcel in) {
+ return new Token(in);
}
+ @NonNull
@Override
public Token[] newArray(int size) {
return new Token[size];
@@ -589,40 +599,50 @@ public interface ImeTracker {
*
* Note: This is held in a separate class so that it only gets initialized when actually needed.
*/
- class Debug {
+ final class Debug {
+ @NonNull
private static final Map<Integer, String> sTypes =
getFieldMapping(ImeTracker.class, "TYPE_");
+ @NonNull
private static final Map<Integer, String> sStatus =
getFieldMapping(ImeTracker.class, "STATUS_");
+ @NonNull
private static final Map<Integer, String> sOrigins =
getFieldMapping(ImeTracker.class, "ORIGIN_");
+ @NonNull
private static final Map<Integer, String> sPhases =
getFieldMapping(ImeTracker.class, "PHASE_");
+ @NonNull
public static String typeToString(@Type int type) {
return sTypes.getOrDefault(type, "TYPE_" + type);
}
+ @NonNull
public static String statusToString(@Status int status) {
return sStatus.getOrDefault(status, "STATUS_" + status);
}
+ @NonNull
public static String originToString(@Origin int origin) {
return sOrigins.getOrDefault(origin, "ORIGIN_" + origin);
}
+ @NonNull
public static String phaseToString(@Phase int phase) {
return sPhases.getOrDefault(phase, "PHASE_" + phase);
}
- private static Map<Integer, String> getFieldMapping(Class<?> cls, String fieldPrefix) {
+ @NonNull
+ private static Map<Integer, String> getFieldMapping(Class<?> cls,
+ @NonNull String fieldPrefix) {
return Arrays.stream(cls.getDeclaredFields())
.filter(field -> field.getName().startsWith(fieldPrefix))
.collect(Collectors.toMap(Debug::getFieldValue, Field::getName));
}
- private static int getFieldValue(Field field) {
+ private static int getFieldValue(@NonNull Field field) {
try {
return field.getInt(null);
} catch (IllegalAccessException e) {
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index ec1badb637e4..8b55494c75d4 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -18,6 +18,7 @@ package android.view.inputmethod;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
@@ -83,6 +84,22 @@ public final class InputMethodInfo implements Parcelable {
public static final String ACTION_STYLUS_HANDWRITING_SETTINGS =
"android.view.inputmethod.action.STYLUS_HANDWRITING_SETTINGS";
+ /**
+ * Maximal length of a component name
+ * @hide
+ */
+ @TestApi
+ public static final int COMPONENT_NAME_MAX_LENGTH = 1000;
+
+ /**
+ * The maximum amount of IMEs that are loaded per package (in order).
+ * If a package contains more IMEs, they will be ignored and cannot be enabled.
+ * @hide
+ */
+ @TestApi
+ @SuppressLint("MinMaxConstant")
+ public static final int MAX_IMES_PER_PACKAGE = 20;
+
static final String TAG = "InputMethodInfo";
/**
@@ -252,6 +269,13 @@ public final class InputMethodInfo implements Parcelable {
com.android.internal.R.styleable.InputMethod);
settingsActivityComponent = sa.getString(
com.android.internal.R.styleable.InputMethod_settingsActivity);
+ if ((si.name != null && si.name.length() > COMPONENT_NAME_MAX_LENGTH) || (
+ settingsActivityComponent != null
+ && settingsActivityComponent.length() > COMPONENT_NAME_MAX_LENGTH)) {
+ throw new XmlPullParserException(
+ "Activity name exceeds maximum of 1000 characters");
+ }
+
isVrOnly = sa.getBoolean(com.android.internal.R.styleable.InputMethod_isVrOnly, false);
isDefaultResId = sa.getResourceId(
com.android.internal.R.styleable.InputMethod_isDefault, 0);
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 642182b5ddfd..36d2b8a89779 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -99,6 +99,7 @@ import android.view.WindowManager;
import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
+import android.widget.Editor;
import android.window.ImeOnBackInvokedDispatcher;
import android.window.WindowOnBackInvokedDispatcher;
@@ -1552,11 +1553,7 @@ public final class InputMethodManager {
if (fallbackContext == null) {
return false;
}
- if (Settings.Global.getInt(fallbackContext.getContentResolver(),
- Settings.Global.STYLUS_HANDWRITING_ENABLED, 0) == 0) {
- if (DEBUG) {
- Log.d(TAG, "Stylus handwriting is not enabled in settings.");
- }
+ if (!isStylusHandwritingEnabled(fallbackContext)) {
return false;
}
return IInputMethodManagerGlobalInvoker.isStylusHandwritingAvailableAsUser(userId);
@@ -2233,35 +2230,173 @@ public final class InputMethodManager {
* @see #isStylusHandwritingAvailable()
*/
public void startStylusHandwriting(@NonNull View view) {
+ startStylusHandwritingInternal(view, null /* delegatorPackageName */);
+ }
+
+ private boolean startStylusHandwritingInternal(
+ @NonNull View view, @Nullable String delegatorPackageName) {
+ Objects.requireNonNull(view);
+
// Re-dispatch if there is a context mismatch.
final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
if (fallbackImm != null) {
- fallbackImm.startStylusHandwriting(view);
+ fallbackImm.startStylusHandwritingInternal(view, delegatorPackageName);
}
- Objects.requireNonNull(view);
- if (Settings.Global.getInt(view.getContext().getContentResolver(),
- Settings.Global.STYLUS_HANDWRITING_ENABLED, 0) == 0) {
- Log.d(TAG, "Ignoring startStylusHandwriting(view) as stylus handwriting is disabled");
- return;
+ boolean useDelegation = !TextUtils.isEmpty(delegatorPackageName);
+ if (!isStylusHandwritingEnabled(view.getContext())) {
+ Log.w(TAG, "Stylus handwriting pref is disabled. "
+ + "Ignoring calls to start stylus handwriting.");
+ return false;
}
checkFocus();
synchronized (mH) {
if (!hasServedByInputMethodLocked(view)) {
Log.w(TAG,
- "Ignoring startStylusHandwriting() as view=" + view + " is not served.");
- return;
+ "Ignoring startStylusHandwriting as view=" + view + " is not served.");
+ return false;
}
if (view.getViewRootImpl() != mCurRootView) {
- Log.w(TAG, "Ignoring startStylusHandwriting: View's window does not have focus.");
- return;
+ Log.w(TAG,
+ "Ignoring startStylusHandwriting: View's window does not have focus.");
+ return false;
+ }
+ if (useDelegation) {
+ return IInputMethodManagerGlobalInvoker.acceptStylusHandwritingDelegation(
+ mClient, view.getContext().getOpPackageName(), delegatorPackageName);
+ } else {
+ IInputMethodManagerGlobalInvoker.startStylusHandwriting(mClient);
}
+ return false;
+ }
+ }
- IInputMethodManagerGlobalInvoker.startStylusHandwriting(mClient);
- // TODO(b/210039666): do we need any extra work for supporting non-native
- // UI toolkits?
+ private boolean isStylusHandwritingEnabled(@NonNull Context context) {
+ if (Settings.Global.getInt(context.getContentResolver(),
+ Settings.Global.STYLUS_HANDWRITING_ENABLED, 0) == 0) {
+ Log.d(TAG, "Stylus handwriting pref is disabled.");
+ return false;
}
+ return true;
+ }
+
+ /**
+ * Prepares delegation of starting stylus handwriting session to a different editor in same
+ * or different window than the view on which initial handwriting stroke was detected.
+ *
+ * Delegation can be used to start stylus handwriting session before the {@link Editor} view or
+ * its {@link InputConnection} is started. Calling this method starts buffering of stylus
+ * motion events until {@link #acceptStylusHandwritingDelegation(View)} is called, at which
+ * point the handwriting session can be started and the buffered stylus motion events will be
+ * delivered to the IME.
+ * e.g. Delegation can be used when initial handwriting stroke is
+ * on a pseudo {@link Editor} like widget (with no {@link InputConnection}) but actual
+ * {@link Editor} is on a different window.
+ *
+ * <p> Note: If an actual {@link Editor} capable of {@link InputConnection} is being scribbled
+ * upon using stylus, use {@link #startStylusHandwriting(View)} instead.</p>
+ *
+ * @param delegatorView the view that receives initial stylus stroke and delegates it to the
+ * actual editor. Its window must {@link View#hasWindowFocus have focus}.
+ * @see #prepareStylusHandwritingDelegation(View, String)
+ * @see #acceptStylusHandwritingDelegation(View)
+ * @see #startStylusHandwriting(View)
+ */
+ public void prepareStylusHandwritingDelegation(@NonNull View delegatorView) {
+ prepareStylusHandwritingDelegation(
+ delegatorView, delegatorView.getContext().getOpPackageName());
+ }
+
+ /**
+ * Prepares delegation of starting stylus handwriting session to a different editor in same or a
+ * different window in a different package than the view on which initial handwriting stroke
+ * was detected.
+ *
+ * Delegation can be used to start stylus handwriting session before the {@link Editor} view or
+ * its {@link InputConnection} is started. Calling this method starts buffering of stylus
+ * motion events until {@link #acceptStylusHandwritingDelegation(View, String)} is called, at
+ * which point the handwriting session can be started and the buffered stylus motion events will
+ * be delivered to the IME.
+ * e.g. Delegation can be used when initial handwriting stroke is
+ * on a pseudo {@link Editor} like widget (with no {@link InputConnection}) but actual
+ * {@link Editor} is on a different window in the given package.
+ *
+ * <p>Note: If delegator and delegate are in same package use
+ * {@link #prepareStylusHandwritingDelegation(View)} instead.</p>
+ *
+ * @param delegatorView the view that receives initial stylus stroke and delegates it to the
+ * actual editor. Its window must {@link View#hasWindowFocus have focus}.
+ * @param delegatePackageName package name that contains actual {@link Editor} which should
+ * start stylus handwriting session by calling {@link #acceptStylusHandwritingDelegation}.
+ * @see #prepareStylusHandwritingDelegation(View)
+ * @see #acceptStylusHandwritingDelegation(View, String)
+ */
+ public void prepareStylusHandwritingDelegation(
+ @NonNull View delegatorView, @NonNull String delegatePackageName) {
+ Objects.requireNonNull(delegatorView);
+ Objects.requireNonNull(delegatePackageName);
+
+ // Re-dispatch if there is a context mismatch.
+ final InputMethodManager fallbackImm =
+ getFallbackInputMethodManagerIfNecessary(delegatorView);
+ if (fallbackImm != null) {
+ fallbackImm.prepareStylusHandwritingDelegation(delegatorView, delegatePackageName);
+ }
+
+ if (!isStylusHandwritingEnabled(delegatorView.getContext())) {
+ Log.w(TAG, "Stylus handwriting pref is disabled. "
+ + "Ignoring prepareStylusHandwritingDelegation().");
+ return;
+ }
+ IInputMethodManagerGlobalInvoker.prepareStylusHandwritingDelegation(
+ mClient,
+ delegatePackageName,
+ delegatorView.getContext().getOpPackageName());
+ }
+
+ /**
+ * Accepts and starts a stylus handwriting session on the delegate view, if handwriting
+ * initiation delegation was previously requested using
+ * {@link #prepareStylusHandwritingDelegation(View)} from the delegator.
+ *
+ * <p>Note: If delegator and delegate are in different application packages, use
+ * {@link #acceptStylusHandwritingDelegation(View, String)} instead.</p>
+ *
+ * @param delegateView delegate view capable of receiving input via {@link InputConnection}
+ * on which {@link #startStylusHandwriting(View)} will be called.
+ * @return {@code true} if view belongs to same application package as used in
+ * {@link #prepareStylusHandwritingDelegation(View)} and handwriting session can start.
+ * @see #acceptStylusHandwritingDelegation(View, String)
+ * @see #prepareStylusHandwritingDelegation(View)
+ */
+ public boolean acceptStylusHandwritingDelegation(@NonNull View delegateView) {
+ return startStylusHandwritingInternal(
+ delegateView, delegateView.getContext().getOpPackageName());
+ }
+
+ /**
+ * Accepts and starts a stylus handwriting session on the delegate view, if handwriting
+ * initiation delegation was previously requested using
+ * {@link #prepareStylusHandwritingDelegation(View, String)} from te delegator and the view
+ * belongs to a specified delegate package.
+ *
+ * <p>Note: If delegator and delegate are in same application package use
+ * {@link #acceptStylusHandwritingDelegation(View)} instead.</p>
+ *
+ * @param delegateView delegate view capable of receiving input via {@link InputConnection}
+ * on which {@link #startStylusHandwriting(View)} will be called.
+ * @param delegatorPackageName package name of the delegator that handled initial stylus stroke.
+ * @return {@code true} if view belongs to allowed delegate package declared in
+ * {@link #prepareStylusHandwritingDelegation(View, String)} and handwriting session can start.
+ * @see #prepareStylusHandwritingDelegation(View, String)
+ * @see #acceptStylusHandwritingDelegation(View)
+ */
+ public boolean acceptStylusHandwritingDelegation(
+ @NonNull View delegateView, @NonNull String delegatorPackageName) {
+ Objects.requireNonNull(delegatorPackageName);
+
+ return startStylusHandwritingInternal(delegateView, delegatorPackageName);
}
/**
diff --git a/core/java/android/view/textclassifier/TextLinks.java b/core/java/android/view/textclassifier/TextLinks.java
index 445e9ecff54f..b5b6f5ae8af8 100644
--- a/core/java/android/view/textclassifier/TextLinks.java
+++ b/core/java/android/view/textclassifier/TextLinks.java
@@ -478,7 +478,7 @@ public final class TextLinks implements Parcelable {
/**
* Sets the entity configuration to use. This determines what types of entities the
* TextClassifier will look for.
- * Set to {@code null} for the default entity config and teh TextClassifier will
+ * Set to {@code null} for the default entity config and the TextClassifier will
* automatically determine what links to generate.
*
* @return this builder
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index b89dd31725b7..9f9a7815932c 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -52,6 +52,7 @@ import android.graphics.RectF;
import android.graphics.RenderNode;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.GradientDrawable;
import android.os.Build;
import android.os.Bundle;
import android.os.LocaleList;
@@ -3238,6 +3239,44 @@ public class Editor {
.setOnMenuItemClickListener(mOnContextMenuItemClickListener);
mPreserveSelection = true;
+
+ // No-op for the old context menu because it doesn't have icons.
+ adjustIconSpacing(menu);
+ }
+
+ /**
+ * Adjust icon spacing to align the texts.
+ * @hide
+ */
+ @VisibleForTesting
+ public void adjustIconSpacing(ContextMenu menu) {
+ int width = -1;
+ int height = -1;
+ for (int i = 0; i < menu.size(); ++i) {
+ final MenuItem item = menu.getItem(i);
+ final Drawable d = item.getIcon();
+ if (d == null) {
+ continue;
+ }
+
+ width = Math.max(width, d.getIntrinsicWidth());
+ height = Math.max(height, d.getIntrinsicHeight());
+ }
+
+ if (width < 0 || height < 0) {
+ return; // No menu has icon drawable.
+ }
+
+ GradientDrawable paddingDrawable = new GradientDrawable();
+ paddingDrawable.setSize(width, height);
+
+ for (int i = 0; i < menu.size(); ++i) {
+ final MenuItem item = menu.getItem(i);
+ final Drawable d = item.getIcon();
+ if (d == null) {
+ item.setIcon(paddingDrawable);
+ }
+ }
}
@Nullable
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index a33906267736..18874f768929 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -6717,6 +6717,10 @@ public class RemoteViews implements Parcelable, Filter {
Log.w(LOG_TAG, "getLaunchOptions: view.getDisplay() is null!",
new Exception());
}
+ // If the user interacts with a visible element it is safe to assume they consent that
+ // something is going to start.
+ opts.setPendingIntentBackgroundActivityStartMode(
+ ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
return Pair.create(intent, opts);
}
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index fd8f5495464c..1600a16566a5 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -13221,10 +13221,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
super.onPopulateAccessibilityEventInternal(event);
- if (this.isAccessibilityDataPrivate() && !event.isAccessibilityDataPrivate()) {
- // This view's accessibility data is private, but another view that generated this event
- // is not, so don't append this view's text to the event in order to prevent sharing
- // this view's contents with non-accessibility-tool services.
+ if (this.isAccessibilityDataSensitive() && !event.isAccessibilityDataSensitive()) {
+ // This view's accessibility data is sensitive, but another view that generated this
+ // event is not, so don't append this view's text to the event in order to prevent
+ // sharing this view's contents with non-accessibility-tool services.
return;
}
diff --git a/core/java/android/window/ITaskOrganizer.aidl b/core/java/android/window/ITaskOrganizer.aidl
index bf9d3c2eefaf..fd86769293a6 100644
--- a/core/java/android/window/ITaskOrganizer.aidl
+++ b/core/java/android/window/ITaskOrganizer.aidl
@@ -34,8 +34,9 @@ oneway interface ITaskOrganizer {
* has create a starting window for the Task.
*
* @param info The information about the Task that's available
+ * @param appToken Token of the application being started.
*/
- void addStartingWindow(in StartingWindowInfo info);
+ void addStartingWindow(in StartingWindowInfo info, IBinder appToken);
/**
* Called when the Task want to remove the starting window.
diff --git a/core/java/android/window/SnapshotDrawerUtils.java b/core/java/android/window/SnapshotDrawerUtils.java
index 071c20f25e5c..1a58fd556609 100644
--- a/core/java/android/window/SnapshotDrawerUtils.java
+++ b/core/java/android/window/SnapshotDrawerUtils.java
@@ -329,21 +329,6 @@ public class SnapshotDrawerUtils {
}
/**
- * Get or create a TaskDescription from a RunningTaskInfo.
- */
- public static ActivityManager.TaskDescription getOrCreateTaskDescription(
- ActivityManager.RunningTaskInfo runningTaskInfo) {
- final ActivityManager.TaskDescription taskDescription;
- if (runningTaskInfo.taskDescription != null) {
- taskDescription = runningTaskInfo.taskDescription;
- } else {
- taskDescription = new ActivityManager.TaskDescription();
- taskDescription.setBackgroundColor(WHITE);
- }
- return taskDescription;
- }
-
- /**
* Help method to draw the snapshot on a surface.
*/
public static void drawSnapshotOnSurface(StartingWindowInfo info, WindowManager.LayoutParams lp,
@@ -359,8 +344,13 @@ public class SnapshotDrawerUtils {
final WindowManager.LayoutParams attrs = info.topOpaqueWindowLayoutParams;
final ActivityManager.RunningTaskInfo runningTaskInfo = info.taskInfo;
- final ActivityManager.TaskDescription taskDescription =
- getOrCreateTaskDescription(runningTaskInfo);
+ final ActivityManager.TaskDescription taskDescription;
+ if (runningTaskInfo.taskDescription != null) {
+ taskDescription = runningTaskInfo.taskDescription;
+ } else {
+ taskDescription = new ActivityManager.TaskDescription();
+ taskDescription.setBackgroundColor(WHITE);
+ }
drawSurface.initiateSystemBarPainter(lp.flags, lp.privateFlags,
attrs.insetsFlags.appearance, taskDescription, info.requestedVisibleTypes);
final Rect systemBarInsets = getSystemBarInsets(windowBounds, topWindowInsetsState);
diff --git a/core/java/android/window/StartingWindowInfo.java b/core/java/android/window/StartingWindowInfo.java
index 451acbe84a60..1b64e613ed66 100644
--- a/core/java/android/window/StartingWindowInfo.java
+++ b/core/java/android/window/StartingWindowInfo.java
@@ -22,12 +22,9 @@ import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.TaskInfo;
import android.content.pm.ActivityInfo;
-import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
-import android.os.RemoteException;
import android.view.InsetsState;
-import android.view.SurfaceControl;
import android.view.WindowInsets;
import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowManager;
@@ -62,8 +59,6 @@ public final class StartingWindowInfo implements Parcelable {
/** @hide **/
public static final int STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN = 4;
- public static final int STARTING_WINDOW_TYPE_WINDOWLESS = 5;
-
/**
* @hide
*/
@@ -72,8 +67,7 @@ public final class StartingWindowInfo implements Parcelable {
STARTING_WINDOW_TYPE_SPLASH_SCREEN,
STARTING_WINDOW_TYPE_SNAPSHOT,
STARTING_WINDOW_TYPE_SOLID_COLOR_SPLASH_SCREEN,
- STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN,
- STARTING_WINDOW_TYPE_WINDOWLESS
+ STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN
})
public @interface StartingWindowType {}
@@ -124,7 +118,6 @@ public final class StartingWindowInfo implements Parcelable {
TYPE_PARAMETER_ACTIVITY_CREATED,
TYPE_PARAMETER_USE_SOLID_COLOR_SPLASH_SCREEN,
TYPE_PARAMETER_ALLOW_HANDLE_SOLID_COLOR_SCREEN,
- TYPE_PARAMETER_WINDOWLESS,
TYPE_PARAMETER_LEGACY_SPLASH_SCREEN
})
public @interface StartingTypeParams {}
@@ -158,12 +151,6 @@ public final class StartingWindowInfo implements Parcelable {
* @hide
*/
public static final int TYPE_PARAMETER_ALLOW_HANDLE_SOLID_COLOR_SCREEN = 0x00000080;
-
- /**
- * Windowless surface
- */
- public static final int TYPE_PARAMETER_WINDOWLESS = 0x00000100;
-
/**
* Application is allowed to use the legacy splash screen
* @hide
@@ -195,33 +182,7 @@ public final class StartingWindowInfo implements Parcelable {
*/
public TaskSnapshot taskSnapshot;
- @InsetsType public int requestedVisibleTypes = WindowInsets.Type.defaultVisible();
-
- /**
- * App token where the starting window should add to.
- */
- public IBinder appToken;
-
- public IWindowlessStartingSurfaceCallback windowlessStartingSurfaceCallback;
-
- /**
- * The root surface where windowless surface should attach on.
- */
- public SurfaceControl rootSurface;
-
- /**
- * Notify windowless surface is created.
- * @param addedSurface Created surface.
- */
- public void notifyAddComplete(SurfaceControl addedSurface) {
- if (windowlessStartingSurfaceCallback != null) {
- try {
- windowlessStartingSurfaceCallback.onSurfaceAdded(addedSurface);
- } catch (RemoteException e) {
- //
- }
- }
- }
+ public @InsetsType int requestedVisibleTypes = WindowInsets.Type.defaultVisible();
public StartingWindowInfo() {
@@ -255,9 +216,6 @@ public final class StartingWindowInfo implements Parcelable {
dest.writeBoolean(isKeyguardOccluded);
dest.writeTypedObject(taskSnapshot, flags);
dest.writeInt(requestedVisibleTypes);
- dest.writeStrongBinder(appToken);
- dest.writeStrongInterface(windowlessStartingSurfaceCallback);
- dest.writeTypedObject(rootSurface, flags);
}
void readFromParcel(@NonNull Parcel source) {
@@ -272,10 +230,6 @@ public final class StartingWindowInfo implements Parcelable {
isKeyguardOccluded = source.readBoolean();
taskSnapshot = source.readTypedObject(TaskSnapshot.CREATOR);
requestedVisibleTypes = source.readInt();
- appToken = source.readStrongBinder();
- windowlessStartingSurfaceCallback = IWindowlessStartingSurfaceCallback.Stub
- .asInterface(source.readStrongBinder());
- rootSurface = source.readTypedObject(SurfaceControl.CREATOR);
}
@Override
diff --git a/core/java/android/window/StartingWindowRemovalInfo.java b/core/java/android/window/StartingWindowRemovalInfo.java
index 518123600b9a..384dacfe89ed 100644
--- a/core/java/android/window/StartingWindowRemovalInfo.java
+++ b/core/java/android/window/StartingWindowRemovalInfo.java
@@ -67,16 +67,6 @@ public final class StartingWindowRemovalInfo implements Parcelable {
*/
public float roundedCornerRadius;
- /**
- * Remove windowless surface.
- */
- public boolean windowlessSurface;
-
- /**
- * Remove immediately.
- */
- public boolean removeImmediately;
-
public StartingWindowRemovalInfo() {
}
@@ -97,8 +87,6 @@ public final class StartingWindowRemovalInfo implements Parcelable {
playRevealAnimation = source.readBoolean();
deferRemoveForIme = source.readBoolean();
roundedCornerRadius = source.readFloat();
- windowlessSurface = source.readBoolean();
- removeImmediately = source.readBoolean();
}
@Override
@@ -109,8 +97,6 @@ public final class StartingWindowRemovalInfo implements Parcelable {
dest.writeBoolean(playRevealAnimation);
dest.writeBoolean(deferRemoveForIme);
dest.writeFloat(roundedCornerRadius);
- dest.writeBoolean(windowlessSurface);
- dest.writeBoolean(removeImmediately);
}
@Override
@@ -119,9 +105,7 @@ public final class StartingWindowRemovalInfo implements Parcelable {
+ " frame=" + mainFrame
+ " playRevealAnimation=" + playRevealAnimation
+ " roundedCornerRadius=" + roundedCornerRadius
- + " deferRemoveForIme=" + deferRemoveForIme
- + " windowlessSurface=" + windowlessSurface
- + " removeImmediately=" + removeImmediately + "}";
+ + " deferRemoveForIme=" + deferRemoveForIme + "}";
}
public static final @android.annotation.NonNull Creator<StartingWindowRemovalInfo> CREATOR =
diff --git a/core/java/android/window/TaskFragmentInfo.java b/core/java/android/window/TaskFragmentInfo.java
index a881a05a1054..fa5195727afe 100644
--- a/core/java/android/window/TaskFragmentInfo.java
+++ b/core/java/android/window/TaskFragmentInfo.java
@@ -66,6 +66,13 @@ public final class TaskFragmentInfo implements Parcelable {
@NonNull
private final List<IBinder> mActivities = new ArrayList<>();
+ /**
+ * List of Activity tokens that were explicitly requested to be launched in this TaskFragment.
+ * It only contains Activities that belong to the organizer process for security.
+ */
+ @NonNull
+ private final List<IBinder> mInRequestedTaskFragmentActivities = new ArrayList<>();
+
/** Relative position of the fragment's top left corner in the parent container. */
private final Point mPositionInParent = new Point();
@@ -99,15 +106,18 @@ public final class TaskFragmentInfo implements Parcelable {
public TaskFragmentInfo(
@NonNull IBinder fragmentToken, @NonNull WindowContainerToken token,
@NonNull Configuration configuration, int runningActivityCount,
- boolean isVisible, @NonNull List<IBinder> activities, @NonNull Point positionInParent,
- boolean isTaskClearedForReuse, boolean isTaskFragmentClearedForPip,
- boolean isClearedForReorderActivityToFront, @NonNull Point minimumDimensions) {
+ boolean isVisible, @NonNull List<IBinder> activities,
+ @NonNull List<IBinder> inRequestedTaskFragmentActivities,
+ @NonNull Point positionInParent, boolean isTaskClearedForReuse,
+ boolean isTaskFragmentClearedForPip, boolean isClearedForReorderActivityToFront,
+ @NonNull Point minimumDimensions) {
mFragmentToken = requireNonNull(fragmentToken);
mToken = requireNonNull(token);
mConfiguration.setTo(configuration);
mRunningActivityCount = runningActivityCount;
mIsVisible = isVisible;
mActivities.addAll(activities);
+ mInRequestedTaskFragmentActivities.addAll(inRequestedTaskFragmentActivities);
mPositionInParent.set(positionInParent);
mIsTaskClearedForReuse = isTaskClearedForReuse;
mIsTaskFragmentClearedForPip = isTaskFragmentClearedForPip;
@@ -151,6 +161,11 @@ public final class TaskFragmentInfo implements Parcelable {
return mActivities;
}
+ @NonNull
+ public List<IBinder> getActivitiesRequestedInTaskFragment() {
+ return mInRequestedTaskFragmentActivities;
+ }
+
/** Returns the relative position of the fragment's top left corner in the parent container. */
@NonNull
public Point getPositionInParent() {
@@ -215,6 +230,8 @@ public final class TaskFragmentInfo implements Parcelable {
&& mIsVisible == that.mIsVisible
&& getWindowingMode() == that.getWindowingMode()
&& mActivities.equals(that.mActivities)
+ && mInRequestedTaskFragmentActivities.equals(
+ that.mInRequestedTaskFragmentActivities)
&& mPositionInParent.equals(that.mPositionInParent)
&& mIsTaskClearedForReuse == that.mIsTaskClearedForReuse
&& mIsTaskFragmentClearedForPip == that.mIsTaskFragmentClearedForPip
@@ -229,6 +246,7 @@ public final class TaskFragmentInfo implements Parcelable {
mRunningActivityCount = in.readInt();
mIsVisible = in.readBoolean();
in.readBinderList(mActivities);
+ in.readBinderList(mInRequestedTaskFragmentActivities);
mPositionInParent.readFromParcel(in);
mIsTaskClearedForReuse = in.readBoolean();
mIsTaskFragmentClearedForPip = in.readBoolean();
@@ -245,6 +263,7 @@ public final class TaskFragmentInfo implements Parcelable {
dest.writeInt(mRunningActivityCount);
dest.writeBoolean(mIsVisible);
dest.writeBinderList(mActivities);
+ dest.writeBinderList(mInRequestedTaskFragmentActivities);
mPositionInParent.writeToParcel(dest, flags);
dest.writeBoolean(mIsTaskClearedForReuse);
dest.writeBoolean(mIsTaskFragmentClearedForPip);
@@ -274,6 +293,7 @@ public final class TaskFragmentInfo implements Parcelable {
+ " runningActivityCount=" + mRunningActivityCount
+ " isVisible=" + mIsVisible
+ " activities=" + mActivities
+ + " inRequestedTaskFragmentActivities" + mInRequestedTaskFragmentActivities
+ " positionInParent=" + mPositionInParent
+ " isTaskClearedForReuse=" + mIsTaskClearedForReuse
+ " isTaskFragmentClearedForPip=" + mIsTaskFragmentClearedForPip
diff --git a/core/java/android/window/TaskOrganizer.java b/core/java/android/window/TaskOrganizer.java
index d4728c1187d7..02878f8ae72b 100644
--- a/core/java/android/window/TaskOrganizer.java
+++ b/core/java/android/window/TaskOrganizer.java
@@ -92,10 +92,13 @@ public class TaskOrganizer extends WindowOrganizer {
* has create a starting window for the Task.
*
* @param info The information about the Task that's available
+ * @param appToken Token of the application being started.
+ * context to for resources
* @hide
*/
@BinderThread
- public void addStartingWindow(@NonNull StartingWindowInfo info) {}
+ public void addStartingWindow(@NonNull StartingWindowInfo info,
+ @NonNull IBinder appToken) {}
/**
* Called when the Task want to remove the starting window.
@@ -294,8 +297,9 @@ public class TaskOrganizer extends WindowOrganizer {
private final ITaskOrganizer mInterface = new ITaskOrganizer.Stub() {
@Override
- public void addStartingWindow(StartingWindowInfo windowInfo) {
- mExecutor.execute(() -> TaskOrganizer.this.addStartingWindow(windowInfo));
+ public void addStartingWindow(StartingWindowInfo windowInfo,
+ IBinder appToken) {
+ mExecutor.execute(() -> TaskOrganizer.this.addStartingWindow(windowInfo, appToken));
}
@Override
diff --git a/core/java/android/window/WindowOnBackInvokedDispatcher.java b/core/java/android/window/WindowOnBackInvokedDispatcher.java
index a8c2b2f28df4..8066f5085a01 100644
--- a/core/java/android/window/WindowOnBackInvokedDispatcher.java
+++ b/core/java/android/window/WindowOnBackInvokedDispatcher.java
@@ -357,6 +357,11 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
mImeDispatcher = imeDispatcher;
}
+ /** Returns true if a non-null {@link ImeOnBackInvokedDispatcher} has been set. **/
+ public boolean hasImeOnBackInvokedDispatcher() {
+ return mImeDispatcher != null;
+ }
+
/**
* Class used to check whether a callback can be registered or not. This is meant to be
* shared with {@link ProxyOnBackInvokedDispatcher} which needs to do the same checks.
diff --git a/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java b/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java
index ef255012b870..b83d1d83f036 100644
--- a/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java
+++ b/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java
@@ -650,6 +650,11 @@ public class AccessibilityShortcutController {
*
*/
private void setEmptyShortcutTargetIfNeeded() {
+ if (hasFeatureLeanback()) {
+ // Do not disable the default shortcut on TV.
+ return;
+ }
+
final ContentResolver contentResolver = mContext.getContentResolver();
final String shortcutTargets = Settings.Secure.getStringForUser(contentResolver,
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 7c237e69256f..ace8451722bb 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -21,6 +21,7 @@ import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT
import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT_SHARE_WITH_PERSONAL;
import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT_SHARE_WITH_WORK;
import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CROSS_PROFILE_BLOCKED_TITLE;
+import static android.content.ContentProvider.getUserIdFromUri;
import static android.stats.devicepolicy.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_PERSONAL;
import static android.stats.devicepolicy.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK;
@@ -161,6 +162,7 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Supplier;
+import java.util.stream.Collectors;
/**
* The Chooser Activity handles intent resolution specifically for sharing intents -
@@ -1397,7 +1399,7 @@ public class ChooserActivity extends ResolverActivity implements
ImageView previewThumbnailView = contentPreviewLayout.findViewById(
R.id.content_preview_thumbnail);
- if (previewThumbnail == null) {
+ if (!validForContentPreview(previewThumbnail)) {
previewThumbnailView.setVisibility(View.GONE);
} else {
mPreviewCoord = new ContentPreviewCoordinator(contentPreviewLayout, false);
@@ -1427,6 +1429,10 @@ public class ChooserActivity extends ResolverActivity implements
String action = targetIntent.getAction();
if (Intent.ACTION_SEND.equals(action)) {
Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM, android.net.Uri.class);
+ if (!validForContentPreview(uri)) {
+ imagePreview.setVisibility(View.GONE);
+ return contentPreviewLayout;
+ }
imagePreview.findViewById(R.id.content_preview_image_1_large)
.setTransitionName(ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME);
mPreviewCoord.loadUriIntoView(R.id.content_preview_image_1_large, uri, 0);
@@ -1436,7 +1442,7 @@ public class ChooserActivity extends ResolverActivity implements
List<Uri> uris = targetIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM, android.net.Uri.class);
List<Uri> imageUris = new ArrayList<>();
for (Uri uri : uris) {
- if (isImageType(resolver.getType(uri))) {
+ if (validForContentPreview(uri) && isImageType(resolver.getType(uri))) {
imageUris.add(uri);
}
}
@@ -1546,9 +1552,16 @@ public class ChooserActivity extends ResolverActivity implements
String action = targetIntent.getAction();
if (Intent.ACTION_SEND.equals(action)) {
Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM, android.net.Uri.class);
+ if (!validForContentPreview(uri)) {
+ contentPreviewLayout.setVisibility(View.GONE);
+ return contentPreviewLayout;
+ }
loadFileUriIntoView(uri, contentPreviewLayout);
} else {
List<Uri> uris = targetIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM, android.net.Uri.class);
+ uris = uris.stream()
+ .filter(ChooserActivity::validForContentPreview)
+ .collect(Collectors.toList());
int uriCount = uris.size();
if (uriCount == 0) {
@@ -1607,6 +1620,24 @@ public class ChooserActivity extends ResolverActivity implements
}
}
+ /**
+ * Indicate if the incoming content URI should be allowed.
+ *
+ * @param uri the uri to test
+ * @return true if the URI is allowed for content preview
+ */
+ private static boolean validForContentPreview(Uri uri) throws SecurityException {
+ if (uri == null) {
+ return false;
+ }
+ int userId = getUserIdFromUri(uri, UserHandle.USER_CURRENT);
+ if (userId != UserHandle.USER_CURRENT && userId != UserHandle.myUserId()) {
+ Log.e(TAG, "dropped invalid content URI belonging to user " + userId);
+ return false;
+ }
+ return true;
+ }
+
@VisibleForTesting
protected boolean isImageType(String mimeType) {
return mimeType != null && mimeType.startsWith("image/");
diff --git a/core/java/com/android/internal/config/sysui/SystemUiSystemPropertiesFlags.java b/core/java/com/android/internal/config/sysui/SystemUiSystemPropertiesFlags.java
index 586b309a781d..9fae2113f0f9 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiSystemPropertiesFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiSystemPropertiesFlags.java
@@ -64,7 +64,7 @@ public class SystemUiSystemPropertiesFlags {
/** Gating the feature which shows FSI-denied notifications as Sticky HUNs */
public static final Flag SHOW_STICKY_HUN_FOR_DENIED_FSI =
- devFlag("persist.sysui.notification.show_sticky_hun_for_denied_fsi");
+ releasedFlag("persist.sysui.notification.show_sticky_hun_for_denied_fsi");
/** Gating the ability for users to dismiss ongoing event notifications */
public static final Flag ALLOW_DISMISS_ONGOING =
diff --git a/core/java/com/android/internal/view/IImeTracker.aidl b/core/java/com/android/internal/inputmethod/IImeTracker.aidl
index b062ca7df921..c7418ee36fff 100644
--- a/core/java/com/android/internal/view/IImeTracker.aidl
+++ b/core/java/com/android/internal/inputmethod/IImeTracker.aidl
@@ -14,43 +14,45 @@
* limitations under the License.
*/
-package com.android.internal.view;
+package com.android.internal.inputmethod;
import android.view.inputmethod.ImeTracker;
/**
- * Interface to the global Ime tracker, used by all client applications.
+ * Interface to the global IME tracker service, used by all client applications.
* {@hide}
*/
interface IImeTracker {
/**
- * Called when an IME show request is created,
- * returns a new Binder to be associated with the IME tracking token.
+ * Called when an IME show request is created.
*
+ * @param tag the logging tag.
* @param uid the uid of the client that requested the IME.
* @param origin the origin of the IME show request.
* @param reason the reason why the IME show request was created.
+ * @return A new IME tracking token.
*/
- IBinder onRequestShow(int uid, int origin, int reason);
+ ImeTracker.Token onRequestShow(String tag, int uid, int origin, int reason);
/**
- * Called when an IME hide request is created,
- * returns a new Binder to be associated with the IME tracking token.
+ * Called when an IME hide request is created.
*
+ * @param tag the logging tag.
* @param uid the uid of the client that requested the IME.
* @param origin the origin of the IME hide request.
* @param reason the reason why the IME hide request was created.
+ * @return A new IME tracking token.
*/
- IBinder onRequestHide(int uid, int origin, int reason);
+ ImeTracker.Token onRequestHide(String tag, int uid, int origin, int reason);
/**
* Called when the IME request progresses to a further phase.
*
- * @param statsToken the token tracking the current IME request.
+ * @param binder the binder of token tracking the current IME request.
* @param phase the new phase the IME request reached.
*/
- oneway void onProgress(in IBinder statsToken, int phase);
+ oneway void onProgress(in IBinder binder, int phase);
/**
* Called when the IME request fails.
@@ -58,7 +60,7 @@ interface IImeTracker {
* @param statsToken the token tracking the current IME request.
* @param phase the phase the IME request failed at.
*/
- oneway void onFailed(in IBinder statsToken, int phase);
+ oneway void onFailed(in ImeTracker.Token statsToken, int phase);
/**
* Called when the IME request is cancelled.
@@ -66,21 +68,21 @@ interface IImeTracker {
* @param statsToken the token tracking the current IME request.
* @param phase the phase the IME request was cancelled at.
*/
- oneway void onCancelled(in IBinder statsToken, int phase);
+ oneway void onCancelled(in ImeTracker.Token statsToken, int phase);
/**
* Called when the IME show request is successful.
*
* @param statsToken the token tracking the current IME request.
*/
- oneway void onShown(in IBinder statsToken);
+ oneway void onShown(in ImeTracker.Token statsToken);
/**
* Called when the IME hide request is successful.
*
* @param statsToken the token tracking the current IME request.
*/
- oneway void onHidden(in IBinder statsToken);
+ oneway void onHidden(in ImeTracker.Token statsToken);
/**
* Checks whether there are any pending IME visibility requests.
diff --git a/core/java/com/android/internal/jank/EventLogTags.logtags b/core/java/com/android/internal/jank/EventLogTags.logtags
index 7af5d8fe49fc..ad47b810aa50 100644
--- a/core/java/com/android/internal/jank/EventLogTags.logtags
+++ b/core/java/com/android/internal/jank/EventLogTags.logtags
@@ -3,8 +3,8 @@
option java_package com.android.internal.jank;
# Marks a request to start tracing a CUJ. Doesn't mean the request was executed.
-37001 jank_cuj_events_begin_request (CUJ Type|1|5),(Elapsed Time Ns|2|3),(Uptime Ns|2|3)
+37001 jank_cuj_events_begin_request (CUJ Type|1|5),(Unix Time Ns|2|3),(Elapsed Time Ns|2|3),(Uptime Ns|2|3)
# Marks a request to end tracing a CUJ. Doesn't mean the request was executed.
-37002 jank_cuj_events_end_request (CUJ Type|1|5),(Elapsed Time Ns|2|3),(Uptime Time Ns|2|3)
+37002 jank_cuj_events_end_request (CUJ Type|1|5),(Unix Time Ns|2|3),(Elapsed Time Ns|2|3),(Uptime Time Ns|2|3)
# Marks a request to cancel tracing a CUJ. Doesn't mean the request was executed.
-37003 jank_cuj_events_cancel_request (CUJ Type|1|5),(Elapsed Time Ns|2|3),(Uptime Time Ns|2|3)
+37003 jank_cuj_events_cancel_request (CUJ Type|1|5),(Unix Time Ns|2|3),(Elapsed Time Ns|2|3),(Uptime Time Ns|2|3)
diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java
index 62f1599f0706..7ae63b1ac450 100644
--- a/core/java/com/android/internal/jank/InteractionJankMonitor.java
+++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java
@@ -37,6 +37,7 @@ import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_IN
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_OPEN_ALL_APPS;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_QUICK_SWITCH;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_UNLOCK_ENTRANCE_ANIMATION;
+import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_CLOCK_MOVE_ANIMATION;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_LAUNCH_CAMERA;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_OCCLUSION;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PASSWORD_APPEAR;
@@ -127,6 +128,7 @@ import com.android.internal.util.PerfettoTrigger;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.time.Instant;
import java.util.Locale;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
@@ -240,6 +242,7 @@ public class InteractionJankMonitor {
public static final int CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE = 67;
public static final int CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME = 68;
public static final int CUJ_IME_INSETS_ANIMATION = 69;
+ public static final int CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION = 70;
private static final int NO_STATSD_LOGGING = -1;
@@ -318,6 +321,7 @@ public class InteractionJankMonitor {
UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_CLOSE_ALL_APPS_SWIPE,
UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_CLOSE_ALL_APPS_TO_HOME,
UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__IME_INSETS_ANIMATION,
+ UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_CLOCK_MOVE_ANIMATION,
};
private static class InstanceHolder {
@@ -412,6 +416,7 @@ public class InteractionJankMonitor {
CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE,
CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME,
CUJ_IME_INSETS_ANIMATION,
+ CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION,
})
@Retention(RetentionPolicy.SOURCE)
public @interface CujType {
@@ -574,8 +579,10 @@ public class InteractionJankMonitor {
public boolean begin(@NonNull Configuration.Builder builder) {
try {
final Configuration config = builder.build();
- EventLogTags.writeJankCujEventsBeginRequest(
- config.mCujType, SystemClock.elapsedRealtimeNanos(), SystemClock.uptimeNanos());
+ postEventLogToWorkerThread((unixNanos, elapsedNanos, realtimeNanos) -> {
+ EventLogTags.writeJankCujEventsBeginRequest(
+ config.mCujType, unixNanos, elapsedNanos, realtimeNanos);
+ });
final TrackerResult result = new TrackerResult();
final boolean success = config.getHandler().runWithScissors(
() -> result.mResult = beginInternal(config), EXECUTOR_TASK_TIMEOUT);
@@ -649,8 +656,10 @@ public class InteractionJankMonitor {
* @return boolean true if the tracker is ended successfully, false otherwise.
*/
public boolean end(@CujType int cujType) {
- EventLogTags.writeJankCujEventsEndRequest(cujType, SystemClock.elapsedRealtimeNanos(),
- SystemClock.uptimeNanos());
+ postEventLogToWorkerThread((unixNanos, elapsedNanos, realtimeNanos) -> {
+ EventLogTags.writeJankCujEventsEndRequest(
+ cujType, unixNanos, elapsedNanos, realtimeNanos);
+ });
FrameTracker tracker = getTracker(cujType);
// Skip this call since we haven't started a trace yet.
if (tracker == null) return false;
@@ -688,8 +697,10 @@ public class InteractionJankMonitor {
* @return boolean true if the tracker is cancelled successfully, false otherwise.
*/
public boolean cancel(@CujType int cujType) {
- EventLogTags.writeJankCujEventsCancelRequest(cujType, SystemClock.elapsedRealtimeNanos(),
- SystemClock.uptimeNanos());
+ postEventLogToWorkerThread((unixNanos, elapsedNanos, realtimeNanos) -> {
+ EventLogTags.writeJankCujEventsCancelRequest(
+ cujType, unixNanos, elapsedNanos, realtimeNanos);
+ });
return cancel(cujType, REASON_CANCEL_NORMAL);
}
@@ -946,6 +957,8 @@ public class InteractionJankMonitor {
return "LAUNCHER_CLOSE_ALL_APPS_TO_HOME";
case CUJ_IME_INSETS_ANIMATION:
return "IME_INSETS_ANIMATION";
+ case CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION:
+ return "LOCKSCREEN_CLOCK_MOVE_ANIMATION";
}
return "UNKNOWN";
}
@@ -1278,4 +1291,21 @@ public class InteractionJankMonitor {
return mReason;
}
}
+
+ @FunctionalInterface
+ private interface TimeFunction {
+ void invoke(long unixNanos, long elapsedNanos, long realtimeNanos);
+ }
+
+ private void postEventLogToWorkerThread(TimeFunction logFunction) {
+ final Instant now = Instant.now();
+ final long unixNanos = TimeUnit.NANOSECONDS.convert(now.getEpochSecond(), TimeUnit.SECONDS)
+ + now.getNano();
+ final long elapsedNanos = SystemClock.elapsedRealtimeNanos();
+ final long realtimeNanos = SystemClock.uptimeNanos();
+
+ mWorker.getThreadHandler().post(() -> {
+ logFunction.invoke(unixNanos, elapsedNanos, realtimeNanos);
+ });
+ }
}
diff --git a/core/java/com/android/internal/midi/EventScheduler.java b/core/java/com/android/internal/midi/EventScheduler.java
index 506902f61fd6..426cd74074eb 100644
--- a/core/java/com/android/internal/midi/EventScheduler.java
+++ b/core/java/com/android/internal/midi/EventScheduler.java
@@ -16,7 +16,6 @@
package com.android.internal.midi;
-import java.util.Iterator;
import java.util.SortedMap;
import java.util.TreeMap;
@@ -26,11 +25,11 @@ import java.util.TreeMap;
* And only one Thread can read from the buffer.
*/
public class EventScheduler {
- private static final long NANOS_PER_MILLI = 1000000;
+ public static final long NANOS_PER_MILLI = 1000000;
private final Object mLock = new Object();
- volatile private SortedMap<Long, FastEventQueue> mEventBuffer;
- private FastEventQueue mEventPool = null;
+ protected volatile SortedMap<Long, FastEventQueue> mEventBuffer;
+ protected FastEventQueue mEventPool = null;
private int mMaxPoolSize = 200;
private boolean mClosed;
@@ -38,9 +37,13 @@ public class EventScheduler {
mEventBuffer = new TreeMap<Long, FastEventQueue>();
}
- // If we keep at least one node in the list then it can be atomic
- // and non-blocking.
- private class FastEventQueue {
+ /**
+ * Class for a fast event queue.
+ *
+ * If we keep at least one node in the list then it can be atomic
+ * and non-blocking.
+ */
+ public static class FastEventQueue {
// One thread takes from the beginning of the list.
volatile SchedulableEvent mFirst;
// A second thread returns events to the end of the list.
@@ -48,7 +51,7 @@ public class EventScheduler {
volatile long mEventsAdded;
volatile long mEventsRemoved;
- FastEventQueue(SchedulableEvent event) {
+ public FastEventQueue(SchedulableEvent event) {
mFirst = event;
mLast = mFirst;
mEventsAdded = 1;
@@ -149,7 +152,8 @@ public class EventScheduler {
* @param event
*/
public void add(SchedulableEvent event) {
- synchronized (mLock) {
+ Object lock = getLock();
+ synchronized (lock) {
FastEventQueue list = mEventBuffer.get(event.getTimestamp());
if (list == null) {
long lowestTime = mEventBuffer.isEmpty() ? Long.MAX_VALUE
@@ -159,7 +163,7 @@ public class EventScheduler {
// If the event we added is earlier than the previous earliest
// event then notify any threads waiting for the next event.
if (event.getTimestamp() < lowestTime) {
- mLock.notify();
+ lock.notify();
}
} else {
list.add(event);
@@ -167,7 +171,7 @@ public class EventScheduler {
}
}
- private SchedulableEvent removeNextEventLocked(long lowestTime) {
+ protected SchedulableEvent removeNextEventLocked(long lowestTime) {
SchedulableEvent event;
FastEventQueue list = mEventBuffer.get(lowestTime);
// Remove list from tree if this is the last node.
@@ -186,7 +190,8 @@ public class EventScheduler {
*/
public SchedulableEvent getNextEvent(long time) {
SchedulableEvent event = null;
- synchronized (mLock) {
+ Object lock = getLock();
+ synchronized (lock) {
if (!mEventBuffer.isEmpty()) {
long lowestTime = mEventBuffer.firstKey();
// Is it time for this list to be processed?
@@ -209,7 +214,8 @@ public class EventScheduler {
*/
public SchedulableEvent waitNextEvent() throws InterruptedException {
SchedulableEvent event = null;
- synchronized (mLock) {
+ Object lock = getLock();
+ synchronized (lock) {
while (!mClosed) {
long millisToWait = Integer.MAX_VALUE;
if (!mEventBuffer.isEmpty()) {
@@ -231,7 +237,7 @@ public class EventScheduler {
}
}
}
- mLock.wait((int) millisToWait);
+ lock.wait((int) millisToWait);
}
}
return event;
@@ -242,10 +248,25 @@ public class EventScheduler {
mEventBuffer = new TreeMap<Long, FastEventQueue>();
}
+ /**
+ * Stops the EventScheduler.
+ * The subscriber calling waitNextEvent() will get one final SchedulableEvent returning null.
+ */
public void close() {
- synchronized (mLock) {
+ Object lock = getLock();
+ synchronized (lock) {
mClosed = true;
- mLock.notify();
+ lock.notify();
}
}
+
+ /**
+ * Gets the lock. This doesn't lock it in anyway.
+ * Subclasses can override this.
+ *
+ * @return Object
+ */
+ protected Object getLock() {
+ return mLock;
+ }
}
diff --git a/core/java/com/android/internal/midi/MidiEventMultiScheduler.java b/core/java/com/android/internal/midi/MidiEventMultiScheduler.java
new file mode 100644
index 000000000000..16e4abecebdd
--- /dev/null
+++ b/core/java/com/android/internal/midi/MidiEventMultiScheduler.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2023 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.midi;
+
+/**
+ * Uses multiple MidiEventSchedulers for waiting for events.
+ *
+ */
+public class MidiEventMultiScheduler {
+ private MultiLockMidiEventScheduler[] mMidiEventSchedulers;
+ private int mNumEventSchedulers;
+ private int mNumClosedSchedulers = 0;
+ private final Object mMultiLock = new Object();
+
+ private class MultiLockMidiEventScheduler extends MidiEventScheduler {
+ @Override
+ public void close() {
+ synchronized (mMultiLock) {
+ mNumClosedSchedulers++;
+ }
+ super.close();
+ }
+
+ @Override
+ protected Object getLock() {
+ return mMultiLock;
+ }
+
+ public boolean isEventBufferEmptyLocked() {
+ return mEventBuffer.isEmpty();
+ }
+
+ public long getLowestTimeLocked() {
+ return mEventBuffer.firstKey();
+ }
+ }
+
+ /**
+ * MidiEventMultiScheduler constructor
+ *
+ * @param numSchedulers the number of schedulers to create
+ */
+ public MidiEventMultiScheduler(int numSchedulers) {
+ mNumEventSchedulers = numSchedulers;
+ mMidiEventSchedulers = new MultiLockMidiEventScheduler[numSchedulers];
+ for (int i = 0; i < numSchedulers; i++) {
+ mMidiEventSchedulers[i] = new MultiLockMidiEventScheduler();
+ }
+ }
+
+ /**
+ * Waits for the next MIDI event. This will return true when it receives it.
+ * If all MidiEventSchedulers have been closed, this will return false.
+ *
+ * @return true if a MIDI event is received and false if all schedulers are closed.
+ */
+ public boolean waitNextEvent() throws InterruptedException {
+ synchronized (mMultiLock) {
+ while (true) {
+ if (mNumClosedSchedulers >= mNumEventSchedulers) {
+ return false;
+ }
+ long lowestTime = Long.MAX_VALUE;
+ long now = System.nanoTime();
+ for (MultiLockMidiEventScheduler eventScheduler : mMidiEventSchedulers) {
+ if (!eventScheduler.isEventBufferEmptyLocked()) {
+ lowestTime = Math.min(lowestTime,
+ eventScheduler.getLowestTimeLocked());
+ }
+ }
+ if (lowestTime <= now) {
+ return true;
+ }
+ long nanosToWait = lowestTime - now;
+ // Add 1 millisecond so we don't wake up before it is
+ // ready.
+ long millisToWait = 1 + (nanosToWait / EventScheduler.NANOS_PER_MILLI);
+ // Clip 64-bit value to 32-bit max.
+ if (millisToWait > Integer.MAX_VALUE) {
+ millisToWait = Integer.MAX_VALUE;
+ }
+ mMultiLock.wait(millisToWait);
+ }
+ }
+ }
+
+ /**
+ * Gets the number of MidiEventSchedulers.
+ *
+ * @return the number of MidiEventSchedulers.
+ */
+ public int getNumEventSchedulers() {
+ return mNumEventSchedulers;
+ }
+
+ /**
+ * Gets a specific MidiEventScheduler based on the index.
+ *
+ * @param index the zero indexed index of a MIDI event scheduler
+ * @return a MidiEventScheduler
+ */
+ public MidiEventScheduler getEventScheduler(int index) {
+ return mMidiEventSchedulers[index];
+ }
+
+ /**
+ * Closes all event schedulers.
+ */
+ public void close() {
+ for (MidiEventScheduler eventScheduler : mMidiEventSchedulers) {
+ eventScheduler.close();
+ }
+ }
+}
diff --git a/core/java/com/android/internal/midi/MidiEventScheduler.java b/core/java/com/android/internal/midi/MidiEventScheduler.java
index 7b019044110f..1b2934d519fd 100644
--- a/core/java/com/android/internal/midi/MidiEventScheduler.java
+++ b/core/java/com/android/internal/midi/MidiEventScheduler.java
@@ -79,7 +79,7 @@ public class MidiEventScheduler extends EventScheduler {
/**
* Create an event that contains the message.
*/
- private MidiEvent createScheduledEvent(byte[] msg, int offset, int count,
+ public MidiEvent createScheduledEvent(byte[] msg, int offset, int count,
long timestamp) {
MidiEvent event;
if (count > POOL_EVENT_SIZE) {
diff --git a/core/java/com/android/internal/os/BatteryStatsHistory.java b/core/java/com/android/internal/os/BatteryStatsHistory.java
index f7e1d57c79fb..617519b1b540 100644
--- a/core/java/com/android/internal/os/BatteryStatsHistory.java
+++ b/core/java/com/android/internal/os/BatteryStatsHistory.java
@@ -330,7 +330,10 @@ public class BatteryStatsHistory {
}
}
- public BatteryStatsHistory(HistoryStepDetailsCalculator stepDetailsCalculator, Clock clock) {
+ public BatteryStatsHistory(int maxHistoryFiles, int maxHistoryBufferSize,
+ HistoryStepDetailsCalculator stepDetailsCalculator, Clock clock) {
+ mMaxHistoryFiles = maxHistoryFiles;
+ mMaxHistoryBufferSize = maxHistoryBufferSize;
mStepDetailsCalculator = stepDetailsCalculator;
mTracer = new TraceDelegate();
mClock = clock;
diff --git a/core/java/com/android/internal/os/ProcessCpuTracker.java b/core/java/com/android/internal/os/ProcessCpuTracker.java
index 65655b7b5a66..70514c30d90d 100644
--- a/core/java/com/android/internal/os/ProcessCpuTracker.java
+++ b/core/java/com/android/internal/os/ProcessCpuTracker.java
@@ -80,10 +80,6 @@ public class ProcessCpuTracker {
/** Stores user time and system time in jiffies. */
private final long[] mProcessStatsData = new long[4];
- /** Stores user time and system time in jiffies. Used for
- * public API to retrieve CPU use for a process. Must lock while in use. */
- private final long[] mSinglePidStatsData = new long[4];
-
private static final int[] PROCESS_FULL_STATS_FORMAT = new int[] {
PROC_SPACE_TERM,
PROC_SPACE_TERM|PROC_PARENS|PROC_OUT_STRING, // 2: name
@@ -629,17 +625,15 @@ public class ProcessCpuTracker {
* executing in both user and system code. Safe to call without lock held.
*/
public long getCpuTimeForPid(int pid) {
- synchronized (mSinglePidStatsData) {
- final String statFile = "/proc/" + pid + "/stat";
- final long[] statsData = mSinglePidStatsData;
- if (Process.readProcFile(statFile, PROCESS_STATS_FORMAT,
- null, statsData, null)) {
- long time = statsData[PROCESS_STAT_UTIME]
+ final String statFile = "/proc/" + pid + "/stat";
+ final long[] statsData = new long[4];
+ if (Process.readProcFile(statFile, PROCESS_STATS_FORMAT,
+ null, statsData, null)) {
+ long time = statsData[PROCESS_STAT_UTIME]
+ statsData[PROCESS_STAT_STIME];
- return time * mJiffyMillis;
- }
- return 0;
+ return time * mJiffyMillis;
}
+ return 0;
}
/**
@@ -647,15 +641,13 @@ public class ProcessCpuTracker {
* in the runqueue. Safe to call without lock held.
*/
public long getCpuDelayTimeForPid(int pid) {
- synchronized (mSinglePidStatsData) {
- final String statFile = "/proc/" + pid + "/schedstat";
- final long[] statsData = mSinglePidStatsData;
- if (Process.readProcFile(statFile, PROCESS_SCHEDSTATS_FORMAT,
- null, statsData, null)) {
- return statsData[PROCESS_SCHEDSTAT_CPU_DELAY_TIME] / 1_000_000;
- }
- return 0;
+ final String statFile = "/proc/" + pid + "/schedstat";
+ final long[] statsData = new long[4];
+ if (Process.readProcFile(statFile, PROCESS_SCHEDSTATS_FORMAT,
+ null, statsData, null)) {
+ return statsData[PROCESS_SCHEDSTAT_CPU_DELAY_TIME] / 1_000_000;
}
+ return 0;
}
/**
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index 8a9445d8554a..28b98d6fab06 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -16,14 +16,10 @@
package com.android.internal.os;
-import static com.android.internal.os.SafeZipPathValidatorCallback.VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL;
-
-import android.annotation.TestApi;
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.ApplicationErrorReport;
import android.app.IActivityManager;
-import android.app.compat.CompatChanges;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.type.DefaultMimeMapFactory;
import android.net.TrafficStats;
@@ -40,7 +36,6 @@ import com.android.internal.logging.AndroidConfig;
import dalvik.system.RuntimeHooks;
import dalvik.system.VMRuntime;
-import dalvik.system.ZipPathValidator;
import libcore.content.type.MimeMap;
@@ -265,31 +260,10 @@ public class RuntimeInit {
*/
TrafficStats.attachSocketTagger();
- /*
- * Initialize the zip path validator callback depending on the targetSdk.
- */
- initZipPathValidatorCallback();
-
initialized = true;
}
/**
- * If targetSDK >= U: set the safe zip path validator callback which disallows dangerous zip
- * entry names.
- * Otherwise: clear the callback to the default validation.
- *
- * @hide
- */
- @TestApi
- public static void initZipPathValidatorCallback() {
- if (CompatChanges.isChangeEnabled(VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL)) {
- ZipPathValidator.setCallback(new SafeZipPathValidatorCallback());
- } else {
- ZipPathValidator.clearCallback();
- }
- }
-
- /**
* Returns an HTTP user agent of the form
* "Dalvik/1.1.0 (Linux; U; Android Eclair Build/MAIN)".
*/
diff --git a/core/java/com/android/internal/protolog/BaseProtoLogImpl.java b/core/java/com/android/internal/protolog/BaseProtoLogImpl.java
index cd55d3292217..f2b0544bcfad 100644
--- a/core/java/com/android/internal/protolog/BaseProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/BaseProtoLogImpl.java
@@ -259,6 +259,7 @@ public class BaseProtoLogImpl {
if (writeToFile) {
writeProtoLogToFileLocked();
logAndPrintln(pw, "Log written to " + mLogFile + ".");
+ mBuffer.resetBuffer();
}
if (mProtoLogEnabled) {
logAndPrintln(pw, "ERROR: logging was re-enabled while waiting for flush.");
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index b529a1016464..f7c03cd42a99 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -56,6 +56,7 @@ oneway interface IStatusBar
void showRecentApps(boolean triggeredFromAltTab);
void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
void toggleRecentApps();
+ void toggleTaskbar();
void toggleSplitScreen();
void preloadRecentApps();
void cancelPreloadRecentApps();
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index 9116cb3ec9fa..9a4610e8c0a1 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -23,11 +23,11 @@ import android.view.inputmethod.InputMethodSubtype;
import android.view.inputmethod.EditorInfo;
import android.window.ImeOnBackInvokedDispatcher;
+import com.android.internal.inputmethod.IImeTracker;
import com.android.internal.inputmethod.IInputMethodClient;
import com.android.internal.inputmethod.IRemoteAccessibilityInputConnection;
import com.android.internal.inputmethod.IRemoteInputConnection;
import com.android.internal.inputmethod.InputBindResult;
-import com.android.internal.view.IImeTracker;
/**
* Public interface to the global input method manager, used by all client
@@ -148,6 +148,15 @@ interface IInputMethodManager {
/** Start Stylus handwriting session **/
void startStylusHandwriting(in IInputMethodClient client);
+ /** Prepares delegation of starting stylus handwriting session to a different editor **/
+ void prepareStylusHandwritingDelegation(in IInputMethodClient client,
+ in String delegatePackageName,
+ in String delegatorPackageName);
+
+ /** Accepts and starts a stylus handwriting session for the delegate view **/
+ boolean acceptStylusHandwritingDelegation(in IInputMethodClient client,
+ in String delegatePackageName, in String delegatorPackageName);
+
/** Returns {@code true} if currently selected IME supports Stylus handwriting. */
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = "
+ "android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional = true)")
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index f72c4c36b6c3..b86020eb90ea 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -133,6 +133,21 @@ public class LockPatternUtils {
})
public @interface CredentialType {}
+ public static String credentialTypeToString(int credentialType) {
+ switch (credentialType) {
+ case CREDENTIAL_TYPE_NONE:
+ return "NONE";
+ case CREDENTIAL_TYPE_PATTERN:
+ return "PATTERN";
+ case CREDENTIAL_TYPE_PIN:
+ return "PIN";
+ case CREDENTIAL_TYPE_PASSWORD:
+ return "PASSWORD";
+ default:
+ return "UNKNOWN_" + credentialType;
+ }
+ }
+
/**
* Flag provided to {@link #verifyCredential(LockscreenCredential, int, int)} . If set, the
* method will return a handle to the Gatekeeper Password in the
@@ -170,6 +185,8 @@ public class LockPatternUtils {
private static final String LOCK_SCREEN_OWNER_INFO_ENABLED =
Settings.Secure.LOCK_SCREEN_OWNER_INFO_ENABLED;
+ private static final String LOCK_PIN_ENHANCED_PRIVACY = "pin_enhanced_privacy";
+
private static final String LOCK_SCREEN_DEVICE_OWNER_INFO = "lockscreen.device_owner_info";
private static final String ENABLED_TRUST_AGENTS = "lockscreen.enabledtrustagents";
@@ -1037,6 +1054,27 @@ public class LockPatternUtils {
}
/**
+ * @return Whether enhanced pin privacy is enabled.
+ */
+ public boolean isPinEnhancedPrivacyEnabled(int userId) {
+ return getBoolean(LOCK_PIN_ENHANCED_PRIVACY, false, userId);
+ }
+
+ /**
+ * Set whether enhanced pin privacy is enabled.
+ */
+ public void setPinEnhancedPrivacyEnabled(boolean enabled, int userId) {
+ setBoolean(LOCK_PIN_ENHANCED_PRIVACY, enabled, userId);
+ }
+
+ /**
+ * @return Whether enhanced pin privacy was ever chosen.
+ */
+ public boolean isPinEnhancedPrivacyEverChosen(int userId) {
+ return getString(LOCK_PIN_ENHANCED_PRIVACY, userId) != null;
+ }
+
+ /**
* Set whether the visible password is enabled for cryptkeeper screen.
*/
public void setVisiblePasswordEnabled(boolean enabled, int userId) {
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index 939a0e411913..9c6a534c3bbb 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -266,7 +266,8 @@ static jboolean nativeIsDataInjectionEnabled(JNIEnv *_env, jclass _this, jlong s
}
static jint nativeCreateDirectChannel(JNIEnv *_env, jclass _this, jlong sensorManager,
- jlong size, jint channelType, jint fd, jobject hardwareBufferObj) {
+ jint deviceId, jlong size, jint channelType, jint fd,
+ jobject hardwareBufferObj) {
const native_handle_t *nativeHandle = nullptr;
NATIVE_HANDLE_DECLARE_STORAGE(ashmemHandle, 1, 0);
@@ -287,7 +288,7 @@ static jint nativeCreateDirectChannel(JNIEnv *_env, jclass _this, jlong sensorMa
}
SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
- return mgr->createDirectChannel(size, channelType, nativeHandle);
+ return mgr->createDirectChannel(deviceId, size, channelType, nativeHandle);
}
static void nativeDestroyDirectChannel(JNIEnv *_env, jclass _this, jlong sensorManager,
@@ -532,7 +533,7 @@ static const JNINativeMethod gSystemSensorManagerMethods[] = {
{"nativeIsDataInjectionEnabled", "(J)Z", (void *)nativeIsDataInjectionEnabled},
- {"nativeCreateDirectChannel", "(JJIILandroid/hardware/HardwareBuffer;)I",
+ {"nativeCreateDirectChannel", "(JIJIILandroid/hardware/HardwareBuffer;)I",
(void *)nativeCreateDirectChannel},
{"nativeDestroyDirectChannel", "(JI)V", (void *)nativeDestroyDirectChannel},
diff --git a/core/jni/android_media_MicrophoneInfo.cpp b/core/jni/android_media_MicrophoneInfo.cpp
index 65e30d8b1ea3..18f81254af7d 100644
--- a/core/jni/android_media_MicrophoneInfo.cpp
+++ b/core/jni/android_media_MicrophoneInfo.cpp
@@ -92,6 +92,7 @@ jint convertMicrophoneInfoFromNative(JNIEnv *env, jobject *jMicrophoneInfo,
env->DeleteLocalRef(jFrequencyResponse);
}
// Create a list of Pair for channel mapping.
+ jChannelMappings = env->NewObject(gArrayListClass, gArrayListCstor);
const auto &channelMapping = micInfo.channel_mapping;
for (size_t i = 0; i < std::size(channelMapping); i++) {
int channelMappingType = channelMapping[i];
diff --git a/core/jni/android_view_MotionPredictor.cpp b/core/jni/android_view_MotionPredictor.cpp
index 2c232fadbbc5..de3e81c7088b 100644
--- a/core/jni/android_view_MotionPredictor.cpp
+++ b/core/jni/android_view_MotionPredictor.cpp
@@ -20,7 +20,6 @@
#include <input/MotionPredictor.h>
#include "android_view_MotionEvent.h"
-#include "core_jni_converters.h"
#include "core_jni_helpers.h"
/**
@@ -30,14 +29,6 @@
namespace android {
-// ----------------------------------------------------------------------------
-
-static struct {
- jclass clazz;
-} gMotionEventClassInfo;
-
-// ----------------------------------------------------------------------------
-
static void release(void* ptr) {
delete reinterpret_cast<MotionPredictor*>(ptr);
}
@@ -57,14 +48,20 @@ static void android_view_MotionPredictor_nativeRecord(JNIEnv* env, jclass clazz,
jobject event) {
MotionPredictor* predictor = reinterpret_cast<MotionPredictor*>(ptr);
MotionEvent* motionEvent = android_view_MotionEvent_getNativePtr(env, event);
- predictor->record(*motionEvent);
+
+ android::base::Result<void> result = predictor->record(*motionEvent);
+ if (!result.ok()) {
+ jniThrowException(env, "java/lang/IllegalArgumentException",
+ result.error().message().c_str());
+ }
}
static jobject android_view_MotionPredictor_nativePredict(JNIEnv* env, jclass clazz, jlong ptr,
jlong predictionTimeNanos) {
MotionPredictor* predictor = reinterpret_cast<MotionPredictor*>(ptr);
- return toJavaArray(env, predictor->predict(static_cast<nsecs_t>(predictionTimeNanos)),
- gMotionEventClassInfo.clazz, &android_view_MotionEvent_obtainFromNative);
+ return android_view_MotionEvent_obtainFromNative(env,
+ predictor->predict(static_cast<nsecs_t>(
+ predictionTimeNanos)));
}
static jboolean android_view_MotionPredictor_nativeIsPredictionAvailable(JNIEnv* env, jclass clazz,
@@ -84,15 +81,13 @@ static const std::array<JNINativeMethod, 5> gMotionPredictorMethods{{
(void*)android_view_MotionPredictor_nativeGetNativeMotionPredictorFinalizer},
{"nativeRecord", "(JLandroid/view/MotionEvent;)V",
(void*)android_view_MotionPredictor_nativeRecord},
- {"nativePredict", "(JJ)[Landroid/view/MotionEvent;",
+ {"nativePredict", "(JJ)Landroid/view/MotionEvent;",
(void*)android_view_MotionPredictor_nativePredict},
{"nativeIsPredictionAvailable", "(JII)Z",
(void*)android_view_MotionPredictor_nativeIsPredictionAvailable},
}};
int register_android_view_MotionPredictor(JNIEnv* env) {
- jclass motionEventClazz = FindClassOrDie(env, "android/view/MotionEvent");
- gMotionEventClassInfo.clazz = MakeGlobalRefOrDie(env, motionEventClazz);
return RegisterMethodsOrDie(env, "android/view/MotionPredictor", gMotionPredictorMethods.data(),
gMotionPredictorMethods.size());
}
diff --git a/core/proto/android/nfc/Android.bp b/core/proto/android/nfc/Android.bp
new file mode 100644
index 000000000000..6a62c917f240
--- /dev/null
+++ b/core/proto/android/nfc/Android.bp
@@ -0,0 +1,43 @@
+//
+// Copyright (C) 2023 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+filegroup {
+ name: "srcs_nfc_proto",
+ srcs: [
+ "*.proto",
+ ],
+}
+
+// Will be statically linked by `framework-nfc`.
+java_library {
+ name: "nfc-proto-java-gen",
+ installable: false,
+ proto: {
+ type: "stream",
+ include_dirs: [
+ "external/protobuf/src",
+ ],
+ },
+ srcs: [
+ ":srcs_nfc_proto",
+ ],
+ sdk_version: "current",
+ min_sdk_version: "current",
+}
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index 8caf12773260..a5d287c3e4b2 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -95,6 +95,8 @@ message SecureSettingsProto {
optional SettingProto hearing_aid_media_routing = 48 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto hearing_aid_system_sounds_routing = 49 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto accessibility_magnification_joystick_enabled = 50 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Settings for font scaling
+ optional SettingProto accessibility_font_scaling_has_been_changed = 51 [ (android.privacy).dest = DEST_AUTOMATIC ];
}
optional Accessibility accessibility = 2;
diff --git a/core/proto/android/service/notification.proto b/core/proto/android/service/notification.proto
index e029af4f9819..f87d9109e7f8 100644
--- a/core/proto/android/service/notification.proto
+++ b/core/proto/android/service/notification.proto
@@ -285,22 +285,24 @@ message NotificationRemoteViewsProto {
repeated PackageRemoteViewInfoProto package_remote_view_info = 1;
}
+// Enum used in DNDModeProto to specify the zen mode setting.
+enum LoggedZenMode {
+ ROOT_CONFIG = -1; // Used to distinguish config (one per user) from the rules.
+ OFF = 0;
+ IMPORTANT_INTERRUPTIONS = 1;
+ NO_INTERRUPTIONS = 2;
+ ALARMS = 3;
+}
+
/**
* Atom that represents an item in the list of Do Not Disturb rules, pulled from
* NotificationManagerService.java.
*/
message DNDModeProto {
- enum Mode {
- ROOT_CONFIG = -1; // Used to distinguish the config (one per user) from the rules.
- ZEN_MODE_OFF = 0;
- ZEN_MODE_IMPORTANT_INTERRUPTIONS = 1;
- ZEN_MODE_NO_INTERRUPTIONS = 2;
- ZEN_MODE_ALARMS = 3;
- }
optional int32 user = 1; // Android user ID (0, 1, 10, ...)
optional bool enabled = 2; // true for ROOT_CONFIG if a manualRule is enabled
optional bool channels_bypassing = 3; // only valid for ROOT_CONFIG
- optional Mode zen_mode = 4;
+ optional LoggedZenMode zen_mode = 4;
// id is one of the system default rule IDs, or empty
// May also be "MANUAL_RULE" to indicate app-activation of the manual rule.
optional string id = 5;
@@ -308,15 +310,34 @@ message DNDModeProto {
optional DNDPolicyProto policy = 7;
}
+// Enum used in DNDPolicyProto for a particular policy parameter's state.
+enum State {
+ STATE_UNSET = 0;
+ STATE_ALLOW = 1;
+ STATE_DISALLOW = 2;
+}
+
+// Enum used in DNDPolicyProto for which people are allowed to break through.
+enum PeopleType {
+ PEOPLE_UNSET = 0;
+ PEOPLE_ANYONE = 1;
+ PEOPLE_CONTACTS = 2;
+ PEOPLE_STARRED = 3;
+ PEOPLE_NONE = 4;
+}
+
+// Enum used in DNDPolicyProto for conversation types allowed to break through.
+enum ConversationType {
+ CONV_UNSET = 0;
+ CONV_ANYONE = 1;
+ CONV_IMPORTANT = 2;
+ CONV_NONE = 3;
+}
+
/**
- * Atom that represents a Do Not Disturb policy, an optional detail proto for DNDModeProto.
+ * Message that represents a Do Not Disturb policy, an optional detail proto for DNDModeProto.
*/
message DNDPolicyProto {
- enum State {
- STATE_UNSET = 0;
- STATE_ALLOW = 1;
- STATE_DISALLOW = 2;
- }
optional State calls = 1;
optional State repeat_callers = 2;
optional State messages = 3;
@@ -334,23 +355,8 @@ message DNDPolicyProto {
optional State ambient = 15;
optional State notification_list = 16;
- enum PeopleType {
- PEOPLE_UNSET = 0;
- PEOPLE_ANYONE = 1;
- PEOPLE_CONTACTS = 2;
- PEOPLE_STARRED = 3;
- PEOPLE_NONE = 4;
- }
-
optional PeopleType allow_calls_from = 17;
optional PeopleType allow_messages_from = 18;
- enum ConversationType {
- CONV_UNSET = 0;
- CONV_ANYONE = 1;
- CONV_IMPORTANT = 2;
- CONV_NONE = 3;
- }
-
optional ConversationType allow_conversations_from = 19;
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 16db81825dd2..b73623031dc1 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3707,7 +3707,8 @@
<!-- @SystemApi @hide Allows an application to set a device owner on retail demo devices.-->
<permission android:name="android.permission.PROVISION_DEMO_DEVICE"
- android:protectionLevel="signature|setup" />
+ android:protectionLevel="signature|setup|knownSigner"
+ android:knownCerts="@array/demo_device_provisioning_known_signers" />
<!-- @TestApi @hide Allows an application to reset the record of previous system update freeze
periods. -->
@@ -7107,6 +7108,13 @@
@hide Not for use by third-party applications. -->
<permission android:name="android.permission.READ_CLIPBOARD_IN_BACKGROUND"
android:protectionLevel="signature|role" />
+
+ <!-- @SystemApi Permission that allows apps to disable the clipboard access notifications.
+ @hide
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.MANAGE_CLIPBOARD_ACCESS_NOTIFICATION"
+ android:protectionLevel="signature|installer" />
+
<!-- @hide Permission that suppresses the notification when the clipboard is accessed.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.SUPPRESS_CLIPBOARD_ACCESS_NOTIFICATION"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 53317e3a7beb..82591a5ae6c8 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Jou persoonlike programme word geblokkeer totdat jy jou werkprofiel aanskakel"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Persoonlike programme sal op <xliff:g id="DATE">%1$s</xliff:g> om <xliff:g id="TIME">%2$s</xliff:g> geblokkeer word. Jou IT-admin laat nie toe dat jou werkprofiel langer as <xliff:g id="NUMBER">%3$d</xliff:g> dae af bly nie."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Skakel aan"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Oproepe en boodskappe is af"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Jy het werkapps onderbreek. Jy sal nie foonoproepe of SMS’e ontvang nie."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Hervat werkapps"</string>
<string name="me" msgid="6207584824693813140">"Ek"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Tablet-opsies"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV-opsies"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Kan gebare vasvang wat op die toestel se vingerafdruksensor uitgevoer word."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Neem skermkiekie"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Kan \'n skermkiekie neem."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Voorskou, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"deaktiveer of verander statusbalk"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Laat die program toe om die statusbalk te deaktiveer en stelselikone by te voeg of te verwyder."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"wees die statusbalk"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"PTP via USB is aangeskakel"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"USB-verbinding is aangeskakel"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"MIDI via USB is aangeskakel"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Toestel is as webkamera gekoppel"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"USB-bykomstigheid is gekoppel"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Tik vir meer opsies."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Laai tans gekoppelde toestel. Tik vir meer opsies."</string>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Klaar"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Skakel kortpad af"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Gebruik kortpad"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Kleuromkering"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Kleurregstelling"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Eenhandmodus"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Ekstra donker"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 2ca63efbb117..ab5a9c7d72ba 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"የስራ መገለጫዎን እስኪያበሩት ድረስ የግል መተግበሪያዎችዎ ታግደዋል"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"የግል መተግበሪያዎች <xliff:g id="DATE">%1$s</xliff:g> <xliff:g id="TIME">%2$s</xliff:g> ላይ ይታገዳሉ። የእርስዎ የአይቲ አስተዳዳሪ የሥራ መገለጫዎ ከ<xliff:g id="NUMBER">%3$d</xliff:g> ቀኖች በላይ ጠፍቶ እንዲቆይ አይፈቅዱም።"</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"አብራ"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"ጥሪዎች እና መልዕክቶች ጠፍተዋል"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"የሥራ መተግበሪያዎችን ባሉበት አቁመዋል። የስልክ ጥሪዎች ወይም ኤስኤምኤሶች አይደርሱዎትም።"</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"የሥራ መተግበሪያዎችን ከቆሙበት አስቀጥል"</string>
<string name="me" msgid="6207584824693813140">"እኔ"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"የጡባዊ አማራጮች"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV አማራጮች"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"በመሣሪያው የጣት አሻራ ዳሳሽ ላይ የተከናወኑ የጣት ምልክቶችን መያዝ ይችላል።"</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ቅጽበታዊ ገጽ እይታን ያነሳል"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"የማሳያው ቅጽበታዊ ገጽ እይታን ማንሳት ይችላል።"</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"ቅድመ ዕይታ፣ <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"የሁኔቴ አሞሌ አቦዝን ወይም ቀይር"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"የስርዓት አዶዎችን ወደ ሁኔታ አሞሌ ላለማስቻል ወይም ለማከል እና ለማስወገድ ለመተግበሪያው ይፈቅዳሉ፡፡"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"የሁኔታ አሞሌ መሆን"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"PTP በዩኤስቢ በኩል በርቷል"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"ዩኤስቢን እንደ ሞደም መሰካት በርቷል"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"MIDI በዩኤስቢ በኩል በርቷል"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"መሣሪያ እንደ የድር ካሜራ ተገናኝቷል"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"የዩኤስቢ ተቀጥላ ተገናኝቷል"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"ለተጨማሪ አማራጮች መታ ያድርጉ።"</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"የተገናኘ መሣሪያን ኃይል በመሙላት ላይ። ለተጨማሪ አማራጮች መታ ያድርጉ።"</string>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"ተከናውኗል"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"አቋራጩን አጥፋ"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"አቋራጭ ይጠቀሙ"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"ተቃራኒ ቀለም"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"የቀለም ማስተካከያ"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"የአንድ እጅ ሁነታ"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ተጨማሪ ደብዛዛ"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index adfe70856850..b9fc2668ff87 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -211,6 +211,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"تم حظر تطبيقاتك الشخصية إلى أن تفعِّل ملفك الشخصي للعمل."</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"سيتم حظر التطبيقات الشخصية في <xliff:g id="DATE">%1$s</xliff:g> في <xliff:g id="TIME">%2$s</xliff:g>. لا يسمح مشرف تكنولوجيا المعلومات في مؤسستك بإيقاف الملف الشخصي للعمل أكثر من <xliff:g id="NUMBER">%3$d</xliff:g> يوم."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"تفعيل"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"المكالمات والرسائل غير مفعّلة"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"لقد أوقفت تطبيقات العمل مؤقتًا. لن تتلقّى مكالمات هاتفية أو رسائل نصية."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"إلغاء الإيقاف المؤقت لتطبيقات العمل"</string>
<string name="me" msgid="6207584824693813140">"أنا"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"خيارات الجهاز اللوحي"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"‏خيارات Android TV"</string>
@@ -342,6 +345,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"يمكن أن تلتقط الإيماءات من أداة استشعار بصمة الإصبع في الجهاز."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"أخذ لقطة شاشة"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"يمكن أخذ لقطة شاشة."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"نسخة حصرية، \"<xliff:g id="DREAM_NAME">%1$s</xliff:g>\""</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"إيقاف شريط الحالة أو تعديله"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"للسماح للتطبيق بإيقاف شريط الحالة أو إضافة رموز نظام وإزالتها."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"العمل كشريط للحالة"</string>
@@ -1362,8 +1366,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"‏تمّ تفعيل PTP عبر USB"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"‏تمّ تفعيل التوصيل عبر USB"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"‏تمّ تفعيل MIDI عبر USB"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"الجهاز متصل ككاميرا ويب"</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>
@@ -1712,8 +1715,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"تم"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"إيقاف الاختصار"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"استخدام الاختصار"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"قلب الألوان"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"تصحيح الألوان"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"وضع \"التصفح بيد واحدة\""</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"زيادة تعتيم الشاشة"</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index becc30369eb4..1354ad445148 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"আপুনি নিজৰ কৰ্মস্থানৰ প্ৰ’ফাইলটো অন নকৰালৈকে আপোনাৰ ব্যক্তিগত এপ্‌সমূহ অৱৰোধ কৰা থাকে"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"<xliff:g id="DATE">%1$s</xliff:g> তাৰিখে <xliff:g id="TIME">%2$s</xliff:g> বজাত ব্যক্তিগত এপ্‌সমূহ অৱৰোধ কৰা হ’ব। আপোনাৰ আইটি প্ৰশাসকে আপোনাৰ কৰ্মস্থানৰ প্ৰ’ফাইলটো <xliff:g id="NUMBER">%3$d</xliff:g> দিনতকৈ বেছি সময়ৰ বাবে অফ কৰি ৰাখিবলৈ অনুমতি নিদিয়ে।"</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"অন কৰক"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"কল আৰু বাৰ্তা অফ কৰা আছে"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"আপুনি কাম সম্পৰ্কীয় এপ্‌সমূহ পজ কৰিছে। আপুনি ফ’ন কল অথবা পাঠ বাৰ্তাসমূহ নাপাব"</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"কাম সম্পৰ্কীয় এপ্ আনপজ কৰক"</string>
<string name="me" msgid="6207584824693813140">"মই"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"টে\'বলেটৰ বিকল্পসমূহ"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TVৰ বিকল্পসমূহ"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ডিভাইচটোৰ ফিংগাৰপ্ৰিণ্ট ছেন্সৰত দিয়া নিৰ্দেশ বুজিব পাৰে।"</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"স্ক্ৰীনশ্বট লওক"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ডিছপ্লে’খনৰ এটা স্ক্ৰীনশ্বট ল\'ব পাৰে।"</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"পূৰ্বদৰ্শন কৰক, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"স্থিতি দণ্ড অক্ষম কৰক বা সলনি কৰক"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"স্থিতি দণ্ড অক্ষম কৰিবলৈ বা ছিষ্টেম আইকন আঁতৰাবলৈ এপ্‌টোক অনুমতি দিয়ে।"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"স্থিতি দণ্ড হ\'ব পাৰে"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"ইউএছবিৰ জৰিয়তে পিটিপি অন কৰা হ’ল"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"ইউএছবি টেডাৰিং অন কৰা হ’ল"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"ইউএছবিৰ জৰিয়তে এমআইডিআই অন কৰা হ’ল"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"ৱেবকেম হিচাপে সংযোগ কৰা ডিভাইচ"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"ইউএছবি সহায়ক সামগ্ৰী সংযোগ কৰা হ’ল"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"অধিক বিকল্পৰ বাবে টিপক।"</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"সংযুক্ত ডিভাইচ চ্চাৰ্জ কৰি থকা হৈছে। অধিক বিকল্পৰ বাবে টিপক।"</string>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"কৰা হ’ল"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"শ্বৰ্টকাট অফ কৰক"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"শ্বৰ্টকাট ব্যৱহাৰ কৰক"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"ৰং বিপৰীতকৰণ"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"ৰং শুধৰণী"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"এখন হাতেৰে ব্যৱহাৰ কৰাৰ ম’ড"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"এক্সট্ৰা ডিম"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index e554984cffef..3d3b7171aa20 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"İş profilinizi aktiv edənədək şəxsi tətbiqləriniz bloklanır"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Şəxsi tətbiqlər bu tarixdə bloklanacaq: <xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>. İT admini iş profilinizin <xliff:g id="NUMBER">%3$d</xliff:g> gündən çox deaktiv qalmasına icazə vermir."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Aktiv edin"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Zəng və mesajlar deaktivdir"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"İş tətbiqlərinə pauza vermisiniz. Telefon zəngləri, yaxud mətn mesajları qəbul etməyəcəksiniz."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Pauzanı bitirin"</string>
<string name="me" msgid="6207584824693813140">"Mən"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Planşet seçimləri"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV seçimləri"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Cihazların barmaq izi sensorunda olan işarələri əldə edə bilər."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ekran şəkli çəkin"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Ekran şəkli çəkilə bilər."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Önizləmə, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"status panelini deaktivləşdir və ya dəyişdir"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Tətbiqə status panelini deaktiv etməyə və ya sistem ikonalarını əlavə etmək və ya silmək imkanı verir."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"status paneli edin"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"USB vasitəsilə PTP aktiv edildi"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"USB-modem aktivdir"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"USB vasitəsilə MIDI aktiv edildi"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Cihaz Veb-kamera kimi qoşulub"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"USB aksesuarı qoşulub"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Əlavə seçimlər üçün tıklayın."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Qoşulmuş cihaza enerji doldurulur. Əlavə seçimlər üçün klikləyin."</string>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Hazırdır"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Qısayolu Deaktiv edin"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Qısayol İstifadə edin"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Rəng inversiyası"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Rəng korreksiyası"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Birəlli rejim"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Əlavə tündləşmə"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 63d2e6600456..719be37e5d3c 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -208,6 +208,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Lične aplikacije su blokirane dok ne uključite poslovni profil"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Lične aplikacije će biti blokirane: <xliff:g id="DATE">%1$s</xliff:g> u <xliff:g id="TIME">%2$s</xliff:g>. IT administrator ne dozvoljava da poslovni profil bude isključen duže od <xliff:g id="NUMBER">%3$d</xliff:g> dana."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Uključi"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Pozivi i poruke su isključeni"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Pauzirali ste poslovne aplikacije. Nećete dobijati telefonske pozive i SMS-ove."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Uključi poslovne"</string>
<string name="me" msgid="6207584824693813140">"Ja"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Opcije za tablet"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Opcije Android TV-a"</string>
@@ -339,6 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Može da registruje pokrete na senzoru za otisak prsta na uređaju."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Napravi snimak ekrana"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Može da napravi snimak ekrana."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Pregled, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"onemogućavanje ili izmena statusne trake"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Dozvoljava aplikaciji da onemogući statusnu traku ili da dodaje i uklanja sistemske ikone."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"funkcionisanje kao statusna traka"</string>
@@ -1359,8 +1363,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"Režim PTP preko USB-a je uključen"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"USB privezivanje je uključeno"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"Režim MIDI preko USB-a je uključen"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Uređaj povezan sa veb-kamerom"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"USB dodatak je povezan"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Dodirnite za još opcija."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Povezani uređaj se puni. Dodirnite za još opcija."</string>
@@ -1709,8 +1712,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Gotovo"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Isključi prečicu"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Koristi prečicu"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Inverzija boja"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Korekcija boja"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Režim jednom rukom"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Dodatno zatamnjeno"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 14626a076d7f..741c7ffb3100 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -209,6 +209,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Вашы асабістыя праграмы будуць заблакіраваны, пакуль вы не ўключыце працоўны профіль"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Асабістыя праграмы будуць заблакіраваны ў <xliff:g id="TIME">%2$s</xliff:g> <xliff:g id="DATE">%1$s</xliff:g>. Ваш ІТ-адміністратар не дазволіў выключаць працоўны профіль больш чым на <xliff:g id="NUMBER">%3$d</xliff:g> сут."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Уключыць"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Выклікі і паведамленні выключаны"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Працоўныя праграмы прыпынены. Вы не будзеце атрымліваць тэлефонныя выклікі і тэкставыя паведамленні."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Уключыць працоўныя праграмы"</string>
<string name="me" msgid="6207584824693813140">"Я"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Параметры планшэта"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Параметры Android TV"</string>
@@ -340,6 +343,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Можа распазнаваць жэсты на сканеры адбіткаў пальцаў прылады."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Зрабіць здымак экрана"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Можна зрабіць здымак экрана."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Перадпрагляд, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"адключаць ці змяняць радок стану"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Дазваляе прыкладанням адключаць радок стану або дадаваць і выдаляць сістэмныя значкі."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"быць панэллю стану"</string>
@@ -1360,8 +1364,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"Перадача фота (PTP) праз USB"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Рэжым USB-мадэма"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"MIDI праз USB"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Прылада падключана як вэб-камера"</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>
@@ -1710,8 +1713,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Гатова"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Дэактываваць камбінацыю хуткага доступу"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Выкарыстоўваць камбінацыю хуткага доступу"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Інверсія колераў"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Карэкцыя колераў"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Рэжым кіравання адной рукой"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Дадатковае памяншэнне яркасці"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 4e389d8fe664..421854969341 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Личните ви приложения са блокирани, докато не включите служебния си потребителски профил"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Личните приложения ще бъдат блокирани на <xliff:g id="DATE">%1$s</xliff:g> в <xliff:g id="TIME">%2$s</xliff:g>. Системният ви администратор не разрешава служебният ви потребителски профил да бъде изключен за повече от <xliff:g id="NUMBER">%3$d</xliff:g> дни."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Включване"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Обажданията и съобщенията са изключени"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Служебните приложения са поставени на пауза. Няма да получавате телефонни обаждания и текстови съобщения."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Вкл. на служ. прил."</string>
<string name="me" msgid="6207584824693813140">"Аз"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Опции за таблета"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Опции за Android TV"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Може да улавя жестовете, извършени върху сензора за отпечатъци на устройството."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Създаване на екранна снимка"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Може да създава екранни снимки."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Визуализация на „<xliff:g id="DREAM_NAME">%1$s</xliff:g>“"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"деактивиране или промяна на лентата на състоянието"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Разрешава на приложението да деактивира лентата на състоянието или да добавя и премахва системни икони."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"изпълняване на ролята на лента на състоянието"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"Режимът PTP през USB е включен"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Тетърингът през USB е включен"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"Режимът MIDI през USB е включен"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Устройството е свързано като уебкамера"</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>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Готово"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Изключване на прекия път"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Използване на пряк път"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Инвертиране на цветовете"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Корекция на цветове"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Работа с една ръка"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Доп. затъмн."</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 589946339eac..6df2dfb71c09 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"আপনার অফিসের প্রোফাইল চালু না করা পর্যন্ত আপনার ব্যক্তিগত অ্যাপ ব্লক থাকে"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"ব্যক্তিগত অ্যাপ <xliff:g id="DATE">%1$s</xliff:g>-এ <xliff:g id="TIME">%2$s</xliff:g>টার সময় ব্লক করা হবে। আপনার আইটি অ্যাডমিন আপনার অফিস প্রোফাইল <xliff:g id="NUMBER">%3$d</xliff:g> দিনের বেশি পজ করে রাখার অনুমতি দেয় না।"</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"চালু করুন"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"কল ও মেসেজ অফ করা আছে"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"আপনি অফিসের অ্যাপ পজ করেছেন। আপনি ফোন কল বা টেক্সট মেসেজ পাবেন না।"</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"অফিসের অ্যাপ আনপজ করুন"</string>
<string name="me" msgid="6207584824693813140">"আমাকে"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"ট্যাবলেট বিকল্পগুলি"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV-র বিকল্প"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ডিভাইসের আঙ্গুলের ছাপের সেন্সরের উপরে ইঙ্গিত করলে বুঝতে পারে।"</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"স্ক্রিনশট নিন"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ডিসপ্লের একটি স্ক্রিনশট নিতে পারেন।"</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"প্রিভিউ, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"স্ট্যাটাস বার নিষ্ক্রিয় অথবা সংশোধন করে"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"অ্যাপ্লিকেশনকে স্ট্যাটাস বার অক্ষম করতে এবং সিস্টেম আইকনগুলি সরাতে দেয়৷"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"স্থিতি দন্ডে থাকুন"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"USB এর মাধ্যমে PTP চালু করা হয়েছে"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"USB টিথারিং চালু করা হয়েছে"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"USB এর মাধ্যমে MIDI চালু করা হয়েছে"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"ওয়েবক্যাম হিসেবে কানেক্ট করা আছে"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"ইউএসবি অ্যাক্সেসরি কানেক্ট করা হয়েছে"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"আরও বিকল্পের জন্য আলতো চাপুন৷"</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"সংযুক্ত ডিভাইস চার্জ করা হচ্ছে। আরও বিকল্প দেখতে ট্যাপ করুন।"</string>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"হয়ে গেছে"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"শর্টকাট বন্ধ করুন"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"শর্টকাট ব্যবহার করুন"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"কালার ইনভার্সন"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"রঙ সংশোধন করা"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"এক হাতে ব্যবহার করার মোড"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"অতিরিক্ত কম আলো"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 6a1e062c9afb..2bb7912b947d 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -208,6 +208,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Vaše lične aplikacije će biti blokirane dok ne uključite radni profil"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Lične aplikacije će biti blokirane <xliff:g id="DATE">%1$s</xliff:g> u <xliff:g id="TIME">%2$s</xliff:g>. Vaš IT administrator ne dozvoljava da radni profil bude isključen duže od <xliff:g id="NUMBER">%3$d</xliff:g> dana."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Uključi"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Pozivi i poruke su isključeni"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Pauzirali ste poslovne aplikacije. Nećete primati telefonske pozive ni poruke."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Pr. pauz. pos. apl."</string>
<string name="me" msgid="6207584824693813140">"Ja"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Opcije tableta"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Opcije Android TV uređaja"</string>
@@ -339,6 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Može zabilježiti pokrete na senzoru za otisak prsta uređaja."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"praviti snimke ekrana"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Može napraviti snimak ekrana."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Pregled, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"onemogućavanje ili mijenjanje statusne trake"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Dozvoljava aplikaciji onemogućavanje statusne trake ili dodavanje i uklanjanje sistemskih ikona."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"funkcioniranje u vidu statusne trake"</string>
@@ -1359,8 +1363,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"Uključen je način rada PTP putem USB-a"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Dijeljenje internetske veze putem USB-a je uključeno"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"Uključen je način rada MIDI putem USB-a"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Uređaj je povezan kao web kamera"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"Povezan je USB periferni uređaj"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Dodirnite za više opcija."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Punjenje povezanog uređaja. Dodirnite za više opcija."</string>
@@ -1709,8 +1712,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Gotovo"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Isključi prečicu"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Koristi prečicu"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Inverzija boja"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Ispravka boja"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Način rada jednom rukom"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Dodatno zatamnjeno"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 82947e77fa56..e9a0d8c52411 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -208,6 +208,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Les teves aplicacions personals estan bloquejades fins que activis el perfil de treball"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Les aplicacions personals es bloquejaran el dia <xliff:g id="DATE">%1$s</xliff:g> a les <xliff:g id="TIME">%2$s</xliff:g>. L\'administrador de TI no permet desactivar el teu perfil de treball durant més de: <xliff:g id="NUMBER">%3$d</xliff:g> dies."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Activa"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Trucades i missatges desactivats"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Has posat en pausa les aplicacions de treball. No rebràs trucades ni missatges de text."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Reac. apps treball"</string>
<string name="me" msgid="6207584824693813140">"Mi"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Opcions de la tauleta"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Opcions d\'Android TV"</string>
@@ -339,6 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Pot capturar els gestos fets en el sensor d\'empremtes digitals del dispositiu."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Fer una captura de pantalla"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Pot fer una captura de la pantalla."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Previsualitza, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"desactivar o modificar la barra d\'estat"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Permet que l\'aplicació desactivi la barra d\'estat o afegeixi i elimini icones del sistema."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"aparèixer a la barra d\'estat"</string>
@@ -1359,8 +1363,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"S\'ha activat el mode PTP per USB"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"S\'ha activat la compartició de xarxa per USB"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"S\'ha activat el mode MIDI per USB"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Dispositiu connectat com a càmera web"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"S\'ha connectat un accessori USB"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Toca per veure més opcions."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"S\'està carregant el dispositiu connectat. Toca per veure més opcions."</string>
@@ -1709,8 +1712,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Fet"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Desactiva la drecera"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utilitza la drecera"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Inversió de colors"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Correcció de color"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Mode d\'una mà"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Atenuació extra"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 1ed9ac2286c6..a3d49aec319f 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -209,6 +209,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Vaše osobní aplikace jsou zablokovány, dokud nezapnete pracovní profil"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Osobní aplikace budou zablokovány <xliff:g id="DATE">%1$s</xliff:g> v <xliff:g id="TIME">%2$s</xliff:g>. Administrátor IT nepovoluje vypnutí pracovního profilu na déle než tento počet dní: <xliff:g id="NUMBER">%3$d</xliff:g>."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Zapnout"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Hovory a zprávy jsou vypnuté"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Máte pozastavené pracovní aplikace. Nebudete přijímat telefonní hovory ani textové zprávy."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Zrušit pozastavení pracovních aplikací"</string>
<string name="me" msgid="6207584824693813140">"Já"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Možnosti tabletu"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Možnosti zařízení Android TV"</string>
@@ -340,6 +343,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Dokáže rozpoznat gesta zadaná na snímači otisků prstů."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Pořídit snímek obrazovky"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Může pořídit snímek obrazovky."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Náhled, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"zakázání či změny stavového řádku"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Umožňuje aplikaci zakázat stavový řádek nebo přidat či odebrat systémové ikony."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"vydávání se za stavový řádek"</string>
@@ -1360,8 +1364,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"Byl zapnut režim PTP přes USB"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Byl zapnut tethering přes USB"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"Byl zapnut režim MIDI přes USB"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Zařízení připojeno jako webkamera"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"Je připojeno příslušenství USB"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Klepnutím zobrazíte další možnosti."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Nabíjení připojeného zařízení. Klepnutím zobrazíte další možnosti."</string>
@@ -1710,8 +1713,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Hotovo"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Vypnout zkratku"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Použít zkratku"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Převrácení barev"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Korekce barev"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Režim jedné ruky"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Velmi tmavé"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index c7806c7cbbc9..ab0b6c4c985a 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Dine personlige apps er blokeret, indtil du aktiverer din arbejdsprofil"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Personlige apps bliver blokeret <xliff:g id="DATE">%1$s</xliff:g> kl. <xliff:g id="TIME">%2$s</xliff:g>. Din it-administrator tillader ikke, at din arbejdsprofil deaktiveres i mere end <xliff:g id="NUMBER">%3$d</xliff:g> dage."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Aktivér"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Opkald og beskeder er slået fra"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Du har sat arbejdsapps på pause. Du kan ikke modtage telefonopkald eller sms-beskeder."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Genaktiver arbejdsapps"</string>
<string name="me" msgid="6207584824693813140">"Mig"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Valgmuligheder for tabletcomputeren"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Valgmuligheder for Android TV"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Kan registrere bevægelser, der foretages på enhedens fingeraftrykssensor."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Tag screenshot"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Kan tage et screenshot af skærmen."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Preview, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"deaktivere eller redigere statuslinje"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Tillader, at appen kan deaktivere statusbjælken eller tilføje og fjerne systemikoner."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"vær statusbjælken"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"PTP via USB er slået til"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Netdeling via USB er slået til"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"MIDI via USB er slået til"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Enheden er forbundet som webcam"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"USB-tilbehør er tilsluttet"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Tryk for at se flere muligheder."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Den tilsluttede enhed oplades. Tryk for at få flere valgmuligheder."</string>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Udfør"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Deaktiver genvej"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Brug genvej"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Ombytning af farver"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Farvekorrigering"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Enhåndstilstand"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Ekstra dæmpet belysning"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 11c1219e1d8c..96feac3d6a2d 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Deine privaten Apps werden blockiert, bis du dein Arbeitsprofil aktivierst"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Private Apps werden am <xliff:g id="DATE">%1$s</xliff:g> um <xliff:g id="TIME">%2$s</xliff:g> blockiert. Dein IT-Administrator hat festgelegt, dass dein Arbeitsprofil nicht länger als <xliff:g id="NUMBER">%3$d</xliff:g> Tage pausiert werden darf."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Aktivieren"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Anrufe und Nachrichten sind deaktiviert"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Du hast geschäftliche Apps pausiert. Deshalb kannst du keine Anrufe oder Nachrichten empfangen."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Geschäftl. Apps nicht pausieren"</string>
<string name="me" msgid="6207584824693813140">"Eigene"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Tablet-Optionen"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV-Optionen"</string>
@@ -292,7 +295,7 @@
<string name="foreground_service_multiple_separator" msgid="5002287361849863168">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string>
<string name="safeMode" msgid="8974401416068943888">"Abgesicherter Modus"</string>
<string name="android_system_label" msgid="5974767339591067210">"Android-System"</string>
- <string name="user_owner_label" msgid="8628726904184471211">"Zum persönlichen Profil wechseln"</string>
+ <string name="user_owner_label" msgid="8628726904184471211">"Zum privaten Profil wechseln"</string>
<string name="managed_profile_label" msgid="7316778766973512382">"Zum Arbeitsprofil wechseln"</string>
<string name="permgrouplab_contacts" msgid="4254143639307316920">"Kontakte"</string>
<string name="permgroupdesc_contacts" msgid="9163927941244182567">"auf deine Kontakte zugreifen"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Erfasst Touch-Gesten auf dem Fingerabdrucksensor des Geräts."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Screenshot erstellen"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Es kann ein Screenshot des Displays erstellt werden."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Vorschau – <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"Statusleiste deaktivieren oder ändern"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Ermöglicht der App, die Statusleiste zu deaktivieren oder Systemsymbole hinzuzufügen oder zu entfernen"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"Statusleiste darstellen"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"PTP über USB aktiviert"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"USB-Tethering aktiviert"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"MIDI über USB aktiviert"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Gerät als Webcam verbunden"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"Mit USB-Zubehör verbunden"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Für weitere Optionen tippen."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Verbundenes Gerät wird aufgeladen. Für weitere Optionen tippen."</string>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Fertig"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Verknüpfung deaktivieren"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Verknüpfung verwenden"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Farbumkehr"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Farbkorrektur"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Einhandmodus"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Extradunkel"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index c7f851e6bcf8..de19837a660b 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Οι προσωπικές σας εφαρμογές αποκλείονται μέχρι να ενεργοποιήσετε το προφίλ εργασίας σας."</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Οι προσωπικές εφαρμογές θα αποκλειστούν στις <xliff:g id="DATE">%1$s</xliff:g> και ώρα <xliff:g id="TIME">%2$s</xliff:g>. Ο διαχειριστής IT δεν επιτρέπει το προφίλ εργασίας να παραμένει απενεργοποιημένο για περισσότερες από <xliff:g id="NUMBER">%3$d</xliff:g> ημέρες."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Ενεργοποίηση"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Οι κλήσεις και τα μηνύμ. είναι ανενεργά"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Θέσατε σε παύση τις εφαρμογές εργασιών. Δεν θα λαμβάνετε τηλεφωνικές κλήσεις ή μηνύματα κειμένου."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Κατ. παύσης εφ."</string>
<string name="me" msgid="6207584824693813140">"Για εμένα"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Επιλογές tablet"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Επιλογές Android TV"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Μπορεί να αναγνωρίσει κινήσεις που εκτελούνται στον αισθητήρα δακτυλικού αποτυπώματος της συσκευής."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Λήψη στιγμιότυπου οθόνης"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Μπορεί να τραβήξει στιγμιότυπο της οθόνης."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Προεπισκόπηση, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"απενεργοποιεί ή να τροποποιεί την γραμμή κατάστασης"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Επιτρέπει στην εφαρμογή να απενεργοποιεί τη γραμμή κατάστασης ή να προσθέτει και να αφαιρεί εικονίδια συστήματος."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"ορίζεται ως γραμμή κατάστασης"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"Η λειτουργία PTP μέσω USB ενεργοποιήθηκε"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Η σύνδεση μέσω USB ενεργοποιήθηκε"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"Η λειτουργία MIDI μέσω USB ενεργοποιήθηκε"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Η συσκευή συνδέθηκε ως webcam"</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>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Τέλος"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Απενεργοποίηση συντόμευσης"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Χρήση συντόμευσης"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Αντιστροφή χρωμάτων"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Διόρθωση χρωμάτων"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Λειτουργία ενός χεριού"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Επιπλέον μείωση φωτεινότητας"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 8ecd973b0bc0..73d6bfd5febd 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Your personal apps are blocked until you turn on your work profile"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Personal apps will be blocked on <xliff:g id="DATE">%1$s</xliff:g> at <xliff:g id="TIME">%2$s</xliff:g>. Your IT admin doesn’t allow your work profile to stay off for more than <xliff:g id="NUMBER">%3$d</xliff:g> days."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Turn on"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Calls and messages are off"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"You have paused work apps. You won\'t receive phone calls or text messages."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Unpause work apps"</string>
<string name="me" msgid="6207584824693813140">"Me"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Tablet options"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV options"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Can capture gestures performed on the device\'s fingerprint sensor."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Take screenshot"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Can take a screenshot of the display."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Preview, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"disable or modify status bar"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Allows the app to disable the status bar or add and remove system icons."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"be the status bar"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index c73c0f1cf918..02f76c2409f5 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Your personal apps are blocked until you turn on your work profile"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Personal apps will be blocked on <xliff:g id="DATE">%1$s</xliff:g> at <xliff:g id="TIME">%2$s</xliff:g>. Your IT admin doesn’t allow your work profile to stay off for more than <xliff:g id="NUMBER">%3$d</xliff:g> days."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Turn on"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Calls and messages are off"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"You have paused work apps. You won\'t receive phone calls or text messages."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Unpause work apps"</string>
<string name="me" msgid="6207584824693813140">"Me"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Tablet options"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV options"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Can capture gestures performed on the device\'s fingerprint sensor."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Take screenshot"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Can take a screenshot of the display."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Preview, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"disable or modify status bar"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Allows the app to disable the status bar or add and remove system icons."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"be the status bar"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 01169923be78..19570b1dbb29 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Your personal apps are blocked until you turn on your work profile"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Personal apps will be blocked on <xliff:g id="DATE">%1$s</xliff:g> at <xliff:g id="TIME">%2$s</xliff:g>. Your IT admin doesn’t allow your work profile to stay off for more than <xliff:g id="NUMBER">%3$d</xliff:g> days."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Turn on"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Calls and messages are off"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"You have paused work apps. You won\'t receive phone calls or text messages."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Unpause work apps"</string>
<string name="me" msgid="6207584824693813140">"Me"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Tablet options"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV options"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Can capture gestures performed on the device\'s fingerprint sensor."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Take screenshot"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Can take a screenshot of the display."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Preview, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"disable or modify status bar"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Allows the app to disable the status bar or add and remove system icons."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"be the status bar"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 5fa28a0686e0..dfa965cca5fa 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Your personal apps are blocked until you turn on your work profile"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Personal apps will be blocked on <xliff:g id="DATE">%1$s</xliff:g> at <xliff:g id="TIME">%2$s</xliff:g>. Your IT admin doesn’t allow your work profile to stay off for more than <xliff:g id="NUMBER">%3$d</xliff:g> days."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Turn on"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Calls and messages are off"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"You have paused work apps. You won\'t receive phone calls or text messages."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Unpause work apps"</string>
<string name="me" msgid="6207584824693813140">"Me"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Tablet options"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV options"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Can capture gestures performed on the device\'s fingerprint sensor."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Take screenshot"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Can take a screenshot of the display."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Preview, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"disable or modify status bar"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Allows the app to disable the status bar or add and remove system icons."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"be the status bar"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 9bdc49be86d2..7e74c19d9ded 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‎‏‏‏‏‎‎‏‏‏‎‏‏‎‏‎‎‎‏‏‎‎‎‏‎‎‏‎‏‎‎‏‏‏‏‏‎‏‎‏‎‎‎‏‏‏‏‎‏‎‏‏‎‏‎Your personal apps are blocked until you turn on your work profile‎‏‎‎‏‎"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‎‏‎‏‏‏‏‎‎‏‏‎‏‏‏‎‎‏‎‏‎‎‏‎‎‏‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‏‏‎‏‏‎‎‏‎‏‎‎‏‏‎‎Personal apps will be blocked on ‎‏‎‎‏‏‎<xliff:g id="DATE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ at ‎‏‎‎‏‏‎<xliff:g id="TIME">%2$s</xliff:g>‎‏‎‎‏‏‏‎. Your IT admin doesn’t allow your work profile to stay off for more than ‎‏‎‎‏‏‎<xliff:g id="NUMBER">%3$d</xliff:g>‎‏‎‎‏‏‏‎ days.‎‏‎‎‏‎"</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‎‎‎‏‏‎‎‏‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‎‏‎‎‏‎‎‎‎‎‏‏‎‏‎‏‎‎‎‏‎‏‏‎‏‎‏‏‎‎‏‎Turn on‎‏‎‎‏‎"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‏‎‏‏‎‎‏‏‏‎‎‏‏‏‏‎‏‏‎‏‎‎‏‎‎‎‎‏‎‎‏‎‏‏‎‎‎‏‎‏‎‏‎‎‎‎‎‏‏‏‏‏‎Calls and messages are off‎‏‎‎‏‎"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‏‎‎‎‎‎‎‏‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‏‏‎‎‎‏‏‏‎‎‎‎‎‎‏‎‏‏‎‏‎You have paused work apps. You won\'t receive phone calls or text messages.‎‏‎‎‏‎"</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‏‎‏‏‎‎‏‏‎‏‎‎‎‎‎‎‏‎‎‎‎‏‏‎‎‎‎‏‎‏‏‏‎‏‏‏‎‎‏‎‏‎‏‏‏‏‎‎‎‏‎‏‎‏‎Unpause work apps‎‏‎‎‏‎"</string>
<string name="me" msgid="6207584824693813140">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‎‎‏‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‎‏‏‏‏‏‎‏‎‏‏‏‎‏‏‏‏‏‎‎‏‎‏‎‎‎Me‎‏‎‎‏‎"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‎‏‎‏‏‎‎‎‎‎‎‎‎‏‎‎‏‏‏‏‏‏‎‎‏‎‎‎‎‏‎‏‏‏‏‏‎‎‎‏‎‏‎‏‏‎‏‎‏‏‎‏‎Tablet options‎‏‎‎‏‎"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‎‎‏‎‏‏‎‏‏‏‎‎‏‏‏‎‎‏‎‎‏‏‏‎‎‏‏‏‎‏‎‏‎‎‏‎‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‏‎Android TV options‎‏‎‎‏‎"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‏‏‎‏‎‎‏‎‎‎‎‎‏‏‏‎‎‏‏‏‎‏‎‎‎‎‎‏‎‎‏‎‎‏‏‎‎‎‎‎‎‏‎‎‎‎‎‎‏‏‎‏‎‎Can capture gestures performed on the device\'s fingerprint sensor.‎‏‎‎‏‎"</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‎‎‎‏‎‎‎‎‏‎‏‏‎‏‎‏‎‎‏‎‏‏‏‏‎‏‏‏‎‏‏‎‎‏‏‎‎‏‏‏‏‎‎‏‏‏‏‏‎‏‏‏‏‎‏‎‎Take screenshot‎‏‎‎‏‎"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‏‏‏‎‎‏‎‎‏‏‏‎‎‎‎‏‎‏‎‏‎‏‏‏‏‎‎‏‎‏‎‎‏‎‏‎‏‎‏‏‏‏‎‏‎‏‏‏‏‎‎‏‎‎‎Can take a screenshot of the display.‎‏‎‎‏‎"</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‏‎‎‏‏‏‏‎‏‎‎‏‎‎‎‏‏‏‏‎‏‏‏‏‎‎‎‎‏‎‎‎‏‏‎‎‏‏‏‏‎‏‎‏‎‎‎‏‏‎‎‎‏‎‎‎Preview, ‎‏‎‎‏‏‎<xliff:g id="DREAM_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‏‎‎‏‏‎‏‏‏‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‎disable or modify status bar‎‏‎‎‏‎"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‎‎‏‏‏‏‎‎‏‎‎‏‎‏‎‏‏‎‎‎‎‏‎‏‎‎‎‎‎‏‏‏‏‎‏‏‏‏‎‎‏‏‎‎‏‎‏‎‏‏‏‏‎‏‎‎Allows the app to disable the status bar or add and remove system icons.‎‏‎‎‏‎"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‏‎‎‎‎‎‏‎‎‏‏‏‏‏‏‏‎‎‎‎‎‏‎‏‏‏‏‎‏‏‎‎‏‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‎‏‏‏‎‏‎be the status bar‎‏‎‎‏‎"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 03df43cba15c..4cf1fbbe0a58 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -208,6 +208,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Las apps personales estarán bloqueadas hasta que actives tu perfil de trabajo"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Se bloquearán las apps personales el <xliff:g id="DATE">%1$s</xliff:g> a la(s) <xliff:g id="TIME">%2$s</xliff:g>. Tu administrador de TI no permite que mantengas tu perfil de trabajo desactivado durante más de <xliff:g id="NUMBER">%3$d</xliff:g> días."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Activar"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Llamadas y mensajes desactivados"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Tienes apps de trabajo detenidas. No recibirás llamadas de teléfono ni mensajes de texto."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Reanudar apps"</string>
<string name="me" msgid="6207584824693813140">"Yo"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Opciones de tablet"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Opciones de Android TV"</string>
@@ -339,6 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Capturará los gestos que se hacen en el sensor de huellas dactilares del dispositivo."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Tomar captura de pantalla"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Puede tomar capturas de pantalla."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Vista previa, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"desactivar o modificar la barra de estado"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Permite que la aplicación inhabilite la barra de estado o que agregue y elimine íconos del sistema."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"aparecer en la barra de estado"</string>
@@ -1359,8 +1363,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"Se activó el modo PTP mediante USB"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Se activó la conexión mediante dispositivo móvil por USB"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"Se activó el modo MIDI mediante USB"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Se conectó el dispositivo como cámara web"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"Accesorio USB conectado"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Presiona para ver más opciones."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Cargando el dispositivo conectado. Presiona para ver más opciones."</string>
@@ -1709,8 +1712,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Listo"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Desactivar acceso directo"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Usar acceso directo"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Inversión de colores"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Corrección de colores"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modo de una mano"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Atenuación extra"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index cd1e2705623a..a03449d7076f 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -208,6 +208,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Tus aplicaciones personales estarán bloqueadas hasta que actives tu perfil de trabajo"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Las aplicaciones personales se bloquearán el <xliff:g id="DATE">%1$s</xliff:g> a las <xliff:g id="TIME">%2$s</xliff:g>. Tu administrador de TI no permite que tu perfil de trabajo esté más de <xliff:g id="NUMBER">%3$d</xliff:g> días desactivado."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Activar"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Llamadas y mensajes desactivados"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Has pausado las aplicaciones de trabajo. No recibirás llamadas ni mensajes de texto."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Reactivar apps de trabajo"</string>
<string name="me" msgid="6207584824693813140">"Yo"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Opciones del tablet"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Opciones de Android TV"</string>
@@ -339,6 +342,7 @@
<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"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Puede hacer capturas de la pantalla."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Vista previa, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"inhabilitar o modificar la barra de estado"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Permite que la aplicación inhabilite la barra de estado o añada y elimine iconos del sistema."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"aparecer en la barra de estado"</string>
@@ -1359,8 +1363,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"Modo PTP por USB activado"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Modo de conexión compartida por USB activado"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"Modo MIDI por USB activado"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Dispositivo conectado como cámara web"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"Accesorio USB conectado"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Toca para ver más opciones."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Cargando el dispositivo conectado. Toca para ver más opciones."</string>
@@ -1709,8 +1712,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Hecho"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Desactivar acceso directo"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utilizar acceso directo"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Invertir colores"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Corrección de color"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modo Una mano"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Atenuación extra"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 48216362d22c..6d26022ca30b 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Teie isiklikud rakendused on blokeeritud, kuni lülitate oma tööprofiili sisse"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Isiklikud rakendused blokeeritakse <xliff:g id="DATE">%1$s</xliff:g> kell <xliff:g id="TIME">%2$s</xliff:g>. IT-administraator ei luba teie tööprofiili üle <xliff:g id="NUMBER">%3$d</xliff:g> päeva väljalülitatuna hoida."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Lülita sisse"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Kõned ja sõnumid on välja lülitatud"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Olete töörakendused peatanud. Te ei saa telefonikõnesid ega tekstsõnumeid."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Jätka töörakendusi"</string>
<string name="me" msgid="6207584824693813140">"Mina"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Tahvelarvuti valikud"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV valikud"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Teil on võimalik jäädvustada seadme sõrmejäljeanduril tehtud liigutused."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Jäädvusta ekraanipilt"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Saab jäädvustada ekraanipildi."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Eelvaade, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"keela või muuda olekuriba"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Võimaldab rakendusel keelata olekuriba või lisada ja eemaldada süsteemiikoone."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"olekuribana kuvamine"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"PTP USB kaudu on sisse lülitatud"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"USB kaudu jagamine on sisse lülitatud"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"MIDI USB kaudu on sisse lülitatud"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Seade on ühendatud veebikaamerana"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"USB lisatarvik on ühendatud"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Puudutage lisavalikute nägemiseks."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Ühendatud seadet laetakse. Puudutage lisavalikute nägemiseks."</string>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Valmis"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Lülita otsetee välja"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Kasuta otseteed"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Värvide ümberpööramine"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Värvide korrigeerimine"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Ühekäerežiim"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Eriti tume"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index d45baa546b02..70464d830c0b 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Aplikazio pertsonalak blokeatuta egongo dira laneko profila aktibatzen duzun arte"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Aplikazio pertsonalak egun eta ordu honetan blokeatuko dira: <xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>. IKT saileko administratzaileak ez dizu ematen baimenik laneko profila <xliff:g id="NUMBER">%3$d</xliff:g> egunez baino gehiagoz desaktibatuta edukitzeko."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Aktibatu"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Deiak eta mezuak desaktibatuta daude"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Laneko aplikazioak pausatu dituzu. Ez duzu jasoko telefono-deirik edo testu-mezurik."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Berraktibatu laneko aplikazioak"</string>
<string name="me" msgid="6207584824693813140">"Ni"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Tabletaren aukerak"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV gailuaren aukerak"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Gailuaren hatz-marken sentsorean egindako keinuak atzeman ditzake."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Pantaila-argazkiak atera."</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Pantaila-argazkiak atera ditzake."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Aurrebista, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"desgaitu edo aldatu egoera-barra"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Egoera-barra desgaitzea edo sistema-ikonoak gehitzea edo kentzea baimentzen die aplikazioei."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"bihurtu egoera-barra"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"Aktibatuta dago USB bidezko PTP modua"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Aktibatuta dago USB bidez konexioa partekatzeko aukera"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"Aktibatuta dago USB bidezko MIDI modua"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Web-kamera gisa konektatu da gailua"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"USB osagarri bat konektatu da"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Sakatu aukera gehiago ikusteko."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Konektatutako gailua kargatzen ari da. Sakatu aukera gehiago ikusteko."</string>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Eginda"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Desaktibatu lasterbidea"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Erabili lasterbidea"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Kolore-alderantzikatzea"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Koloreen zuzenketa"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Esku bakarreko modua"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Are ilunago"</string>
@@ -2320,5 +2322,5 @@
<string name="concurrent_display_notification_active_content" msgid="5889355473710601270">"<xliff:g id="APP_NAME">%1$s</xliff:g> bi pantailak erabiltzen ari da edukia erakusteko"</string>
<string name="concurrent_display_notification_thermal_title" msgid="5921609404644739229">"Gailua beroegi dago"</string>
<string name="concurrent_display_notification_thermal_content" msgid="2075484836527609319">"Bi pantailako modua ez dago erabilgarri telefonoa berotzen ari delako"</string>
- <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Itzali"</string>
+ <string name="device_state_notification_turn_off_button" msgid="6327161707661689232">"Desaktibatu"</string>
</resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index f4eb123814a8..562560e00b11 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"تا زمانی‌که نمایه کاری‌تان را روشن نکنید، برنامه‌های شخصی‌تان مسدودند"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"برنامه‌های شخصی در تاریخ <xliff:g id="DATE">%1$s</xliff:g> ساعت <xliff:g id="TIME">%2$s</xliff:g> مسدود خواهند شد. سرپرست فناوری اطلاعات اجازه نمی‌دهد نمایه کاری شما بیشتر از <xliff:g id="NUMBER">%3$d</xliff:g> روز خاموش بماند."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"روشن کردن"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"تماس‌ها و پیام‌ها خاموش هستند"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"برنامه‌های کاری را موقتاً متوقف کرده‌اید. تماس‌ها یا پیامک‌ها را دریافت نخواهید کرد."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"ازسرگیری برنامه‌های کاری"</string>
<string name="me" msgid="6207584824693813140">"من"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"گزینه‌های رایانهٔ لوحی"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"‏گزینه‌های Android TV"</string>
@@ -293,7 +296,7 @@
<string name="safeMode" msgid="8974401416068943888">"حالت ایمن"</string>
<string name="android_system_label" msgid="5974767339591067210">"‏سیستم Android"</string>
<string name="user_owner_label" msgid="8628726904184471211">"جابه‌جا شدن به نمایه شخصی"</string>
- <string name="managed_profile_label" msgid="7316778766973512382">"جابه‌جا شدن به نمایه کاری"</string>
+ <string name="managed_profile_label" msgid="7316778766973512382">"رفتن به نمایه کاری"</string>
<string name="permgrouplab_contacts" msgid="4254143639307316920">"مخاطبین"</string>
<string name="permgroupdesc_contacts" msgid="9163927941244182567">"دسترسی به مخاطبین شما"</string>
<string name="permgrouplab_location" msgid="1858277002233964394">"مکان"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"می‌تواند اشاره‌های اجرا‌شده روی حسگر اثرانگشت دستگاه را ثبت کند."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"گرفتن نماگرفت"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"می‌تواند از نمایشگر نماگرفت بگیرد."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"پیش‌نما، <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"غیرفعال کردن یا تغییر نوار وضعیت"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"‏به برنامه اجازه می‎دهد تا نوار وضعیت را غیرفعال کند یا نمادهای سیستم را اضافه یا حذف کند."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"نوار وضعیت باشد"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"‏PTP ازطریق USB روشن شد"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"‏اشتراک‌گذاری اینترنت با USB روشن شد"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"‏MIDI ازطریق USB روشن شد"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"دستگاه به‌عنوان «وب‌بین» متصل شده است"</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>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"تمام"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"خاموش کردن میان‌بر"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"استفاده از میان‌بر"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"وارونگی رنگ"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"تصحیح رنگ"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"حالت یک‌دستی"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"بسیار کم‌نور"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index f50560b42794..4803bc0e359b 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Henkilökohtaiset sovelluksesi estetään, kunnes laitat työprofiilisi päälle"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Henkilökohtaiset sovellukset estetään <xliff:g id="DATE">%1$s</xliff:g> klo <xliff:g id="TIME">%2$s</xliff:g>. IT-järjestelmänvalvoja ei salli työprofiilisi pysyä pois päältä yli <xliff:g id="NUMBER">%3$d</xliff:g> päivää."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Laita päälle"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Puhelut ja viestit ovat pois päältä"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Olet keskeyttänyt työsovellukset. Et saa puheluja tai tekstiviestejä."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Laita päälle"</string>
<string name="me" msgid="6207584824693813140">"Minä"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Tablet-laitteen asetukset"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV ‑vaihtoehdot"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Voi tallentaa laitteen sormenjälkitunnistimelle tehtyjä eleitä."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ota kuvakaappaus"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Voi ottaa kuvakaappauksen näytöstä."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Esikatselu, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"poista tilapalkki käytöstä tai muokkaa tilapalkkia"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Antaa sovelluksen poistaa tilapalkin käytöstä ja lisätä tai poistaa järjestelmäkuvakkeita."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"sijaita tilapalkissa"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"PTP USB:n kautta on käytössä"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Internetin jakaminen USB:n kautta on käytössä"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"MIDI USB:n kautta on käytössä"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Laite yhdistetty webkamerana"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"USB-lisälaite yhdistetty"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Näet lisää vaihtoehtoja napauttamalla."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Ladataan yhdistettyä laitetta. Napauta nähdäksesi lisää vaihtoehtoja."</string>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Valmis"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Poista pikanäppäin käytöstä"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Käytä pikanäppäintä"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Käänteiset värit"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Värinkorjaus"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Yhden käden moodi"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Erittäin himmeä"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index eadb4efe3f2c..b8a364b1fbd4 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -208,6 +208,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Vos applications personnelles sont bloquées jusqu\'à ce que vous activiez votre profil professionnel"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Les applications personnelles seront bloquées le <xliff:g id="DATE">%1$s</xliff:g> à <xliff:g id="TIME">%2$s</xliff:g>. Votre administrateur informatique ne vous autorise pas à laisser votre profil professionnel désactivé pendant plus de <xliff:g id="NUMBER">%3$d</xliff:g> jours."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Activer"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Les appels et messages sont désactivés"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Vous avez mis en pause les applications professionnelles. Vous ne recevrez aucun appel téléphonique ni message texte."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Réact. applis prof."</string>
<string name="me" msgid="6207584824693813140">"Moi"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Options de la tablette"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Options d\'Android TV"</string>
@@ -339,6 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Peut capturer des gestes effectués sur le capteur d\'empreintes digitales 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 une capture de l\'écran."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Aperçu, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"désactiver ou modifier la barre d\'état"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Permet à l\'application de désactiver la barre d\'état, ou d\'ajouter et de supprimer des icônes système."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"servir de barre d\'état"</string>
@@ -1359,8 +1363,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"Mode PTP par USB activé"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Partage de connexion USB activé"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"Mode MIDI par USB activé"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Appareil connecté en tant que caméra Web"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"Accessoire USB connecté"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Touchez pour afficher plus d\'options."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Chargement de l\'appareil connecté. Touchez l\'écran pour afficher plus d\'options."</string>
@@ -1709,8 +1712,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"OK"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Désactiver le raccourci"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utiliser le raccourci"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Inversion des couleurs"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Correction des couleurs"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Mode Une main"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Très sombre"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index f488f92eabd1..29b86bcb0b66 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -208,6 +208,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Vos applis perso sont bloquées tant que vous n\'avez pas activé votre profil pro"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Vos applis perso seront bloquées le <xliff:g id="DATE">%1$s</xliff:g> à <xliff:g id="TIME">%2$s</xliff:g>. Votre administrateur ne permet pas que votre profil pro reste désactivé pendant plus de <xliff:g id="NUMBER">%3$d</xliff:g> jours."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Activer"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Les appels et messages sont désactivés"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Vous avez suspendu les applis professionnelles. Vous ne recevrez pas d\'appels ni de messages."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Activer apps pro"</string>
<string name="me" msgid="6207584824693813140">"Moi"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Options de la tablette"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Options Android TV"</string>
@@ -339,6 +342,7 @@
<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>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Aperçu, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"Désactivation ou modification de la barre d\'état"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Permet à l\'application de désactiver la barre d\'état, ou d\'ajouter et de supprimer des icônes système."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"remplacer la barre d\'état"</string>
@@ -1359,8 +1363,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"PTP via USB activé"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Partage de connexion via USB activé"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"MIDI via USB activé"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Appareil connecté en tant que webcam"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"Accessoire USB connecté"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Appuyez ici pour plus d\'options."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Recharge de l\'appareil connecté. Appuyez ici pour plus d\'options."</string>
@@ -1709,8 +1712,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"OK"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Désactiver le raccourci"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utiliser le raccourci"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Inversion des couleurs"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Correction des couleurs"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Mode une main"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Encore moins lumineux"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 53a01eb1cabd..355acf41266c 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"As túas aplicacións persoais están bloqueadas ata que actives o teu perfil de traballo"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"As aplicacións persoais bloquearanse o <xliff:g id="DATE">%1$s</xliff:g> á seguinte hora: <xliff:g id="TIME">%2$s</xliff:g>. O administrador de TI non permite que o teu perfil de traballo estea desactivado máis de <xliff:g id="NUMBER">%3$d</xliff:g> días."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Activar"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Desactiváronse as chamadas e as mensaxes"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Puxeches en pausa as aplicacións do traballo. Non recibirás chamadas nin mensaxes de texto."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Volver activar"</string>
<string name="me" msgid="6207584824693813140">"Eu"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Opcións da tableta"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Opcións de Android TV"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Pode rexistrar os xestos realizados no sensor de impresión dixital do dispositivo."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Facer captura de pantalla"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Pode facer capturas de pantalla."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Vista previa, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"desactivar ou modificar a barra de estado"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Permite á aplicación desactivar a barra de estado ou engadir e quitar as iconas do sistema."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"actuar como a barra de estado"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"Activouse o modo PTP por USB"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Activouse a conexión compartida por USB"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"Activouse o modo MIDI por USB"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"O dispositivo está conectado como unha cámara web"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"Conectouse un accesorio USB"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Toca para ver máis opcións."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Cargando o dispositivo conectado. Toca para ver máis opcións."</string>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Feito"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Desactivar atallo"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utilizar atallo"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Inversión da cor"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Corrección da cor"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modo dunha soa man"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Atenuación extra"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 51eaf8722d3f..64ca8348f888 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"જ્યાં સુધી તમે કાર્યાલયની પ્રોફાઇલ ચાલુ ન કરો ત્યાં સુધી તમારી વ્યક્તિગત ઍપ બ્લૉક કરેલી રહે છે"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"વ્યક્તિગત ઍપને <xliff:g id="DATE">%1$s</xliff:g>ના રોજ <xliff:g id="TIME">%2$s</xliff:g> વાગ્યે બ્લૉક કરવામાં આવશે. તમારા IT વ્યવસ્થાપક તમારી ઑફિસની પ્રોફાઇલને <xliff:g id="NUMBER">%3$d</xliff:g> દિવસ કરતાં વધુ સમય માટે બંધ રાખવાની મંજૂરી આપતા નથી."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"ચાલુ કરો"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"કૉલ અને મેસેજ બંધ છે"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"તમે ઑફિસ માટેની ઍપ થોભાવી છે. તમે ફોન કૉલ કે ટેક્સ્ટ મેસેજ મેળવશો નહીં."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"ઑફિસ માટેની ઍપ ફરી ચાલુ કરો"</string>
<string name="me" msgid="6207584824693813140">"હું"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"ટેબ્લેટ વિકલ્પો"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TVના વિકલ્પો"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ડિવાઇસના ફિંગરપ્રિન્ટ સેન્સર પર કરવામાં આવેલા સંકેતો કૅપ્ચર કરી શકે છે."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"સ્ક્રીનશૉટ લો"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ડિસ્પ્લેનો સ્ક્રીનશૉટ લઈ શકે છે."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"પ્રીવ્યૂ, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"સ્ટેટસ બારને અક્ષમ કરો અથવા તેમાં ફેરફાર કરો"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"ઍપ્લિકેશનને સ્ટેટસ બાર અક્ષમ કરવાની અથવા સિસ્ટમ આયકન્સ ઉમેરવા અને દૂર કરવાની મંજૂરી આપે છે."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"સ્ટેટસ બારમાં બતાવો"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"USB મારફતે PTP ચાલુ કર્યું"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"USBથી ઇન્ટરનેટ શેર કરવાની સુવિધા ચાલુ કરી"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"USB મારફતે MIDI ચાલુ કર્યું"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"ડિવાઇસને વેબકૅમ તરીકે કનેક્ટ કર્યું"</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>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"થઈ ગયું"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"શૉર્ટકટ બંધ કરો"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"શૉર્ટકટનો ઉપયોગ કરો"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"વિપરીત રંગમાં બદલવું"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"રંગ સુધારણા"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"એક-હાથે વાપરો મોડ"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"એક્સ્ટ્રા ડિમ"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 58fb413422a6..277b7a026812 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"निजी ऐप्लिकेशन अनब्लॉक करने के लिए, अपनी वर्क प्रोफ़ाइल चालू करें"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"निजी ऐप्लिकेशन <xliff:g id="DATE">%1$s</xliff:g> को <xliff:g id="TIME">%2$s</xliff:g> पर ब्लॉक कर दिए जाएंगे. आपका आईटी एडमिन आपकी वर्क प्रोफ़ाइल को <xliff:g id="NUMBER">%3$d</xliff:g> दिन से ज़्यादा बंद रखने की अनुमति नहीं देता."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"चालू करें"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"कॉल और मैसेज की सुविधा बंद है"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"आपने वर्क ऐप्लिकेशन रोक दिए हैं. आपको फ़ोन कॉल या मैसेज नहीं मिलेंगे."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"वर्क ऐप्लिकेशन फिर से चालू करें"</string>
<string name="me" msgid="6207584824693813140">"मैं"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"टैबलेट विकल्‍प"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV डिवाइस में फ़ोन से जुड़े विकल्प"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"डिवाइस के फ़िंगरप्रिंट सेंसर पर किए गए हाथ के जेस्चर कैप्चर किए जा सकते हैं."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"स्क्रीनशॉट लें"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"डिसप्ले का स्क्रीनशॉट लिया जा सकता है."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"<xliff:g id="DREAM_NAME">%1$s</xliff:g> की झलक"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"स्टेटस बार को अक्षम करें या बदलें"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"ऐप को, स्टेटस बार को बंद करने या सिस्‍टम आइकॉन को जोड़ने और निकालने की अनुमति देता है."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"स्टेटस बार को रहने दें"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"यूएसबी के ज़रिए पीटीपी की सुविधा चालू की गई"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"यूएसबी टेदरिंग की सुविधा चालू की गई"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"यूएसबी के ज़रिए एमआईडीआई (मिडी) की सुविधा चालू की गई"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"डिवाइस को वेबकैम के तौर पर कनेक्ट किया गया"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"यूएसबी ऐक्सेसरी कनेक्ट हो गई है"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"ज़्यादा विकल्पों के लिए टैप करें."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"जोड़ा गया डिवाइस चार्ज हो रहा है. ज़्यादा विकल्पों के लिए टैप करें."</string>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"हो गया"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"शॉर्टकट बंद करें"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"शॉर्टकट का उपयोग करें"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"रंग बदलने की सुविधा"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"रंग में सुधार करने की सुविधा"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"वन-हैंडेड मोड"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"स्क्रीन की रोशनी को सामान्य लेवल से और कम करने की सुविधा"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 44dbcf9a9513..e752c8e7be57 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -208,6 +208,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Vaše su osobne aplikacije blokirane dok ne uključite poslovni profil"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Osobne aplikacije blokirat će se <xliff:g id="DATE">%1$s</xliff:g> u <xliff:g id="TIME">%2$s</xliff:g>. Vaš IT administrator ne dopušta da vaš poslovni profil ostane isključen dulje od <xliff:g id="NUMBER">%3$d</xliff:g> dana."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Uključi"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Pozivi i poruke su isključeni"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Pauzirali ste poslovne aplikacije. Nećete primati telefonske pozive ili tekstne poruke."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Ponovno pokreni poslovne aplikacije"</string>
<string name="me" msgid="6207584824693813140">"Ja"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Opcije tabletnog uređaja"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Opcije Android TV-a"</string>
@@ -339,6 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Može snimati pokrete izvršene na senzoru otiska prsta na uređaju."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Snimi zaslon"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Možete napraviti snimku zaslona."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Pregled, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"onemogućavanje ili izmjena trake statusa"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Aplikaciji omogućuje onemogućavanje trake statusa ili dodavanje i uklanjanje sistemskih ikona."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"biti traka statusa"</string>
@@ -1359,8 +1363,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"Uključen je PTP putem USB-a"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Uključeno je modemsko povezivanje putem USB-a"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"Uključen je MIDI putem USB-a"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Uređaj je povezan kao web-kamera"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"Priključen je USB dodatak"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Dodirnite za više opcija."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Povezani se uređaj puni. Dodirnite za više opcija."</string>
@@ -1709,8 +1712,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Gotovo"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Isključi prečac"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Upotrijebi prečac"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Inverzija boja"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Korekcija boja"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Način rada jednom rukom"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Još tamnije"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 842932f6aa1f..b0333bfd51be 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"A személyes alkalmazások le lesznek tiltva, amíg be nem kapcsolja a munkaprofilt"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"A rendszer a következő időpontban letiltja a személyes alkalmazásokat: <xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>. Rendszergazdája nem engedélyezi, hogy a munkaprofil <xliff:g id="NUMBER">%3$d</xliff:g> napnál tovább kikapcsolva legyen."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Bekapcsolás"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"A hívások és az SMS-ek le vannak tiltva"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Szünetelteti a munkahelyi alkalmazásokat. Nem fogadhat majd telefonhívásokat és SMS-eket."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Appok feloldása"</string>
<string name="me" msgid="6207584824693813140">"Saját"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Táblagép beállításai"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV beállításai"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Érzékeli az eszköz ujjlenyomat-érzékelőjén végzett kézmozdulatokat."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Képernyőkép készítése"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Készíthet képernyőképet a kijelzőről."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Előnézet, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"állapotsor kikapcsolása vagy módosítása"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Lehetővé teszi az alkalmazás számára az állapotsor kikapcsolását, illetve rendszerikonok hozzáadását és eltávolítását."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"az állapotsor szerepének átvétele"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"Az USB-n keresztüli PTP be van kapcsolva"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Az USB-internetmegosztás be van kapcsolva"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"Az USB-n keresztüli MIDI be van kapcsolva"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Webkameraként csatlakoztatott eszköz"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"USB-kiegészítő csatlakoztatva"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Koppintson a további beállítások megjelenítéséhez."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Folyamatban van a csatlakoztatott eszköz töltése. Koppintson a további lehetőségekhez."</string>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Kész"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Billentyűparancs kikapcsolása"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Billentyűparancs használata"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Színek invertálása"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Színjavítás"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Egykezes mód"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Extrasötét"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 8b9ae43211de..7169464a9eac 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Անձնական հավելվածներն արգելափակված կլինեն, մինչև չմիացնեք ձեր աշխատանքային պրոֆիլը"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Անձնական հավելվածները <xliff:g id="DATE">%1$s</xliff:g>-ին ժամը <xliff:g id="TIME">%2$s</xliff:g> կարգելափակվեն։ Ձեր ՏՏ ադմինիստրատորը չի թույլատրում, որ ձեր աշխատանքային պրոֆիլը <xliff:g id="NUMBER">%3$d</xliff:g> օրից ավել անջատված մնա։"</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Միացնել"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Զանգերն ու SMS-ներն անջատված են"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Դուք դադարեցրել եք աշխատանքային հավելվածները։ Այդ պատճառով չեք ստանա հեռախոսազանգեր և տեքստային հաղորդագրություններ։"</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Վերականգնել"</string>
<string name="me" msgid="6207584824693813140">"Իմ"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Պլանշետի ընտրանքները"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV-ի կարգավորումներ"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Կարող է արձանագրել մատնահետքերի սկաների վրա կատարվող ժեստերը"</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Սքրինշոթի ստեղծում"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Կարող է ստեղծել էկրանի սքրինշոթ։"</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Նախադիտում, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"անջատել կամ փոփոխել կարգավիճակի գոտին"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Թույլ է տալիս հավելվածին անջատել կարգավիճակի գոտին կամ ավելացնել ու հեռացնել համակարգի պատկերակները:"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"լինել կարգավիճակի գոտի"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"PTP ռեժիմը USB-ի միջոցով միացավ"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"USB մոդեմի ռեժիմը միացավ"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"MIDI ռեժիմը USB-ի միջոցով միացավ"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Սարքը միացած է որպես վեբ տեսախցիկ"</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>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Պատրաստ է"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Անջատել դյուրանցումը"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Օգտագործել դյուրանցումը"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Գունաշրջում"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Գունաշտկում"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Մեկ ձեռքի ռեժիմ"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Հավելյալ խամրեցում"</string>
@@ -1958,7 +1960,7 @@
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g>՝ անհասանելի է"</string>
<string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Անհրաժեշտ է թույլտվություն"</string>
<string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Տեսախցիկն անհասանելի է"</string>
- <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Շարունակեք հեռախոսով"</string>
+ <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Շարու­նակեք հեռախոսով"</string>
<string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Խոսափողն անհասանելի է"</string>
<string name="app_streaming_blocked_title_for_playstore_dialog" msgid="8149823099822897538">"Play Խանութը հասանելի չէ"</string>
<string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV-ի կարգավորումներն անհասանելի են"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 08031d402959..5836b5a84377 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Aplikasi pribadi Anda diblokir hingga Anda mengaktifkan profil kerja Anda"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Aplikasi pribadi akan diblokir pada tanggal <xliff:g id="DATE">%1$s</xliff:g> pukul <xliff:g id="TIME">%2$s</xliff:g>. Admin IT tidak mengizinkan profil kerja Anda nonaktif selama lebih dari <xliff:g id="NUMBER">%3$d</xliff:g> hari."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Aktifkan"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Panggilan dan pesan dinonaktifkan"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Anda menjeda aplikasi kerja. Anda tidak akan menerima panggilan telepon atau pesan teks."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Lanjutkan aplikasi kerja"</string>
<string name="me" msgid="6207584824693813140">"Saya"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Opsi tablet"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Opsi Android TV"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Dapat merekam gestur yang dilakukan di sensor sidik jari perangkat."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ambil screenshot"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Dapat mengambil screenshot tampilan."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Pratinjau, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"nonaktifkan atau ubah bilah status"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Mengizinkan apl menonaktifkan bilah status atau menambah dan menghapus ikon sistem."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"jadikan bilah status"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"PTP via USB diaktifkan"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Tethering USB diaktifkan"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"MIDI via USB diaktifkan"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Perangkat terhubung sebagai Webcam"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"Aksesori USB terhubung"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Ketuk untuk opsi lainnya."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Mengisi daya perangkat yang terhubung. Ketuk untuk opsi lainnya."</string>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Selesai"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Nonaktifkan Pintasan"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Gunakan Pintasan"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Inversi warna"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Koreksi warna"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Mode satu tangan"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Ekstra redup"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index c14c43ef7e31..5edf2e60c152 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Lokað er á forrit til einkanota þar til þú kveikir á vinnusniði"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Lokað verður á forrit til einkanota <xliff:g id="DATE">%1$s</xliff:g> kl. <xliff:g id="TIME">%2$s</xliff:g>. Kerfisstjórinn þinn leyfir ekki að slökkt sé á vinnusniðinu í meira en <xliff:g id="NUMBER">%3$d</xliff:g> daga."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Kveikja"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Slökkt er á símtölum og skilaboðum"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Þú gerðir hlé á vinnuforritum. Þú munt hvorki taka á móti símtölum né textaskilaboðum."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Ljúka hléi vinnuforrita"</string>
<string name="me" msgid="6207584824693813140">"Ég"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Valkostir spjaldtölvu"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Valkostir Android TV"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Getur fangað bendingar sem eru gerðar á fingrafaralesara tækisins."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Taka skjámynd"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Getur tekið skjámynd af skjánum."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Forskoðun, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"slökkva á eða breyta stöðustiku"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Leyfir forriti að slökkva á stöðustikunni eða bæta við og fjarlægja kerfistákn."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"vera stöðustikan"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"Kveikt er á PTP yfir USB"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Kveikt er á USB-tjóðrun"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"Kveikt er á MIDI yfir USB"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Tæki tengt sem vefmyndavél"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"USB-aukabúnaður tengdur"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Ýttu til að sjá fleiri valkosti."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Hleður tengt tæki. Ýttu til að sjá fleiri valkosti."</string>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Lokið"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Slökkva á flýtileið"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Nota flýtileið"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Umsnúningur lita"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Litaleiðrétting"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Einhent stilling"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Mjög dökkt"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 3d376a92ddce..a5878646264d 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -208,6 +208,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Le tue app personali saranno bloccate finché non attivi il tuo profilo di lavoro."</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Le app personali verranno bloccate il giorno <xliff:g id="DATE">%1$s</xliff:g> alle ore <xliff:g id="TIME">%2$s</xliff:g>. L\'amministratore IT non consente di mantenere disattivato il profilo di lavoro per più di <xliff:g id="NUMBER">%3$d</xliff:g> giorni."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Attiva"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Chiamate e messaggi sono disattivati"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Hai messo in pausa le app di lavoro. Non riceverai telefonate o messaggi."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"App lavoro on"</string>
<string name="me" msgid="6207584824693813140">"Io"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Opzioni tablet"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Opzioni Android TV"</string>
@@ -339,6 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"È in grado di rilevare i gesti compiuti con il sensore di impronte dei dispositivi."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Acquisire screenshot"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Può acquisire uno screenshot del display."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"<xliff:g id="DREAM_NAME">%1$s</xliff:g> in anteprima"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"disattivazione o modifica della barra di stato"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Consente all\'applicazione di disattivare la barra di stato o di aggiungere e rimuovere icone di sistema."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"ruolo di barra di stato"</string>
@@ -1359,8 +1363,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"Modalità PTP tramite USB attivata"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Tethering USB attivato"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"Modalità MIDI tramite USB attivata"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Dispositivo connesso come webcam"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"Accessorio USB collegato"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Tocca per altre opzioni."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Dispositivo collegato in carica. Tocca per altre opzioni."</string>
@@ -1709,8 +1712,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Fine"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Disattiva scorciatoia"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Usa scorciatoia"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Inversione dei colori"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Correzione del colore"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modalità a una mano"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Attenuazione extra"</string>
@@ -1983,7 +1985,7 @@
<string name="profile_encrypted_message" msgid="1128512616293157802">"Tocca per sbloc. prof. di lav."</string>
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Connesso a <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Tocca per visualizzare i file"</string>
- <string name="pin_target" msgid="8036028973110156895">"Blocca"</string>
+ <string name="pin_target" msgid="8036028973110156895">"Fissa"</string>
<string name="pin_specific_target" msgid="7824671240625957415">"Blocca <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Sgancia"</string>
<string name="unpin_specific_target" msgid="3859828252160908146">"Sblocca <xliff:g id="LABEL">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index a88e3738ec42..85984f03fb5d 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -208,6 +208,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"האפליקציות שלך לשימוש אישי יהיו חסומות עד להפעלת פרופיל העבודה"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"‏אפליקציות לשימוש אישי ייחסמו ב-<xliff:g id="DATE">%1$s</xliff:g> בשעה <xliff:g id="TIME">%2$s</xliff:g>. מנהל ה-IT לא מתיר השבתה של פרופיל העבודה ליותר מ-<xliff:g id="NUMBER">%3$d</xliff:g> ימים."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"הפעלה"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"השיחות וההודעות מושבתות"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"השהית את האפליקציות לעבודה. לא יתקבלו שיחות טלפון או הודעות טקסט."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"הפעלת האפליקציות לעבודה"</string>
<string name="me" msgid="6207584824693813140">"אני"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"אפשרויות טאבלט"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"‏אפשרויות Android TV"</string>
@@ -339,6 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"אפשרות לזהות תנועות בזמן נגיעה בחיישן טביעות האצבע של המכשיר."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"צילום המסך"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ניתן לצלם צילום מסך של התצוגה."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"תצוגה מקדימה, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"השבתה או שינוי של שורת הסטטוס"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"מאפשרת לאפליקציה להשבית את שורת הסטטוס או להוסיף ולהסיר סמלי מערכת."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"להיות שורת הסטטוס"</string>
@@ -1359,8 +1363,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"‏PTP באמצעות USB מופעל"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"‏שיתוף אינטרנט בין מכשירים באמצעות USB מופעל"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"‏MIDI באמצעות USB מופעל"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"המכשיר מחובר כמצלמת אינטרנט"</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>
@@ -1709,8 +1712,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"סיום"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"השבתת קיצור הדרך"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"שימוש בקיצור הדרך"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"היפוך צבעים"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"תיקון צבע"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"מצב שימוש ביד אחת"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"מעומעם במיוחד"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 9e6e6673e40d..70d84cac29bb 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"個人用アプリは、仕事用プロファイルを ON にしない限りブロックされます"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"個人用アプリは、<xliff:g id="DATE">%1$s</xliff:g> <xliff:g id="TIME">%2$s</xliff:g> にブロックされます。仕事用プロファイルを <xliff:g id="NUMBER">%3$d</xliff:g> 日を超えて OFF にすることは、IT 管理者から許可されていません。"</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"ON にする"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"通話とメッセージ: OFF"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"仕事用アプリを一時停止しました。電話やテキスト メッセージを受信できなくなります。"</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"仕事用アプリを停止解除"</string>
<string name="me" msgid="6207584824693813140">"自分"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"タブレットオプション"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV のオプション"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"デバイスの指紋認証センサーで行われた操作をキャプチャできます。"</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"スクリーンショットの撮影"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ディスプレイのスクリーンショットを撮影できます。"</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"プレビュー - <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"ステータスバーの無効化や変更"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"ステータスバーの無効化、システムアイコンの追加や削除をアプリに許可します。"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"ステータスバーへの表示"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"USB PTP モード ON"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"USB テザリング ON"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"USB MIDI モード ON"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"ウェブカメラとしてデバイスを接続しました"</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>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"完了"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"ショートカットを OFF にする"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ショートカットを使用"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"色反転"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"色補正"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"片手モード"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"さらに輝度を下げる"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 831707ca4dec..c8162c440112 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"თქვენი პირადი აპები დაბლოკილი იქნება, სანამ სამსახურის პროფილს არ ჩართავთ"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"პირადი აპები დაიბლოკება: <xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>. თქვენი IT ადმინისტრატორი თქვენს სამსახურის პროფილს არ აძლევს უფლებას, გამორთული იყოს <xliff:g id="NUMBER">%3$d</xliff:g> დღეზე მეტ ხანს."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"ჩართვა"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"ზარები და შეტყობინებები გამორთულია"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"თქვენ დააპაუზეთ სამსახურის აპები. თქვენ არ მიიღებთ სატელეფონო ზარებს ან ტექსტურ შეტყობინებებს."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"სამსახურის აპების დაპაუზების გაუქმება"</string>
<string name="me" msgid="6207584824693813140">"მე"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"ტაბლეტის პარამეტრები"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV ვარიანტები"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"შეუძლია აღბეჭდოს მოწყობილობის თითის ანაბეჭდის სენსორზე განხორციელებული ჟესტები."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ეკრანის ანაბეჭდის გადაღება"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"შეუძლია ეკრანის ანაბეჭდის გადაღება."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"გადახედვა, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"სტატუსის ზოლის გათიშვა ან ცვლილება"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"აპს შეეძლება სტატუსების ზოლის გათიშვა და სისტემის ხატულების დამატება/წაშლა."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"სტატუსის ზოლის ჩანაცვლება"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"ჩართულია PTP, USB-ს მეშვეობით"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"USB ტეტერინგი ჩართულია"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"ჩართულია MIDI, USB-ს მეშვეობით"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"მოწყობილობა შეერთებულია, როგორც ვებკამერა"</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>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"მზადაა"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"მალსახმობის გამორთვა"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"მალსახმობის გამოყენება"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"ფერთა ინვერსია"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"ფერთა კორექცია"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"ცალი ხელის რეჟიმი"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"დამატებითი დაბინდვა"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 2923f2286faa..73adb514bfc6 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Жұмыс профиліңізді қоспайынша, жеке қолданбалар бөгеледі."</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Жеке қолданбалардың бөгелетін уақыты: <xliff:g id="DATE">%1$s</xliff:g>, сағат <xliff:g id="TIME">%2$s</xliff:g>. Әкімші жұмыс профилін <xliff:g id="NUMBER">%3$d</xliff:g> күннен аса мерзімге өшіруге рұқсат бермейді."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Қосу"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Қоңыраулар мен хабарлар өшірулі"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Жұмыс қолданбаларының жұмысын тоқтатып қойдыңыз. Телефон қоңырауларын қабылдай не мәтіндік хабарлар ала алмайсыз."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Жұмыс қолданбаларының жұмысын қайта жалғастыру"</string>
<string name="me" msgid="6207584824693813140">"Мен"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Планшет опциялары"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV опциялары"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Құрылғының саусақ ізі сенсорында орындалған қимылдарды сақтайды."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Скриншот жасау"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Дисплейдің скриншотын жасай аласыз."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Алғы көрініс, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"күйін көрсету тақтасын өшіру немесе өзгерту"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Қолданбаға күй жолағын өшіруге немесе жүйелік белгішелерді қосуға және жоюға рұқсат береді."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"күй жолағы болу"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"PTP режимі USB арқылы қосылды"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"USB тетеринг режимі қосылды"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"MIDI режимі USB арқылы қосылды"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Құрылғы веб-камера ретінде жалғанды"</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>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Дайын"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Төте жолды өшіру"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Төте жолды пайдалану"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Түс инверсиясы"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Түсті түзету"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Бір қолмен басқару режимі"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Экранды қарайту"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 7c3f03864125..ede615b6ce84 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"កម្មវិធីផ្ទាល់ខ្លួន​របស់អ្នកត្រូវ​បានទប់ស្កាត់ រហូតទាល់តែ​អ្នកបើក​កម្រងព័ត៌មាន​ការងាររបស់អ្នក"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"កម្មវិធីផ្ទាល់ខ្លួន​នឹងត្រូវបាន​ទប់ស្កាត់​នៅថ្ងៃទី <xliff:g id="DATE">%1$s</xliff:g> នៅម៉ោង <xliff:g id="TIME">%2$s</xliff:g>។ អ្នកគ្រប់គ្រង​ផ្នែកព័ត៌មានវិទ្យា​របស់អ្នក​មិនអនុញ្ញាតឱ្យ​បន្តបិទ​កម្រងព័ត៌មាន​ការងារ​របស់អ្នក​លើសពី <xliff:g id="NUMBER">%3$d</xliff:g> ថ្ងៃ​ទេ។"</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"បើក"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"ការហៅទូរសព្ទ និងសារត្រូវបានបិទ"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"អ្នកបានផ្អាកកម្មវិធី​ការងារ។ អ្នកនឹងមិនទទួលការហៅទូរសព្ទ ឬសារជាអក្សរទេ។"</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"ឈប់ផ្អាកកម្មវិធី​ការងារ"</string>
<string name="me" msgid="6207584824693813140">"ខ្ញុំ"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"ជម្រើស​កុំព្យូទ័រ​បន្ទះ"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"ជម្រើស Android TV"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"អាចចាប់យក​ចលនា​ដែលធ្វើនៅលើ​នៅលើ​ឧបករណ៍​ចាប់​ស្នាម​ម្រាមដៃ​របស់ឧបករណ៍បាន។"</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ថត​អេក្រង់"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"អាច​ថត​អេក្រង់​នៃ​ផ្ទាំង​អេក្រង់​បាន។"</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"មើល​សាកល្បង <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"បិទ ឬ​កែ​របារ​ស្ថានភាព"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"ឲ្យ​កម្មវិធី​បិទ​របារ​ស្ថានភាព ឬ​បន្ថែម និង​លុប​រូប​តំណាង​ប្រព័ន្ធ។"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"ធ្វើជារបារស្ថានភាព"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"មុខងារ PTP តាម​ USB ត្រូវបានបើក"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"ការភ្ជាប់តាម USB ត្រូវបានបើក"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"មុខងារ​ MIDI តាម USB ត្រូវបានបើក"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"បានភ្ជាប់ឧបករណ៍ជា​កាមេរ៉ាបណ្ដាញ"</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>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"រួចរាល់"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"បិទ​ផ្លូវកាត់"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ប្រើប្រាស់​ផ្លូវកាត់"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"ការបញ្ច្រាស​ពណ៌"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"ការកែតម្រូវ​ពណ៌"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"មុខងារប្រើដៃម្ខាង"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ពន្លឺតិចខ្លាំង"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index fab5b3aab8ca..a67341704859 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"ನಿಮ್ಮ ಉದ್ಯೋಗದ ಪ್ರೊಫೈಲ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸುವವರೆಗೆ ನಿಮ್ಮ ವೈಯಕ್ತಿಕ ಆ್ಯಪ್‌ಗಳನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗುತ್ತದೆ"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"ವೈಯಕ್ತಿಕ ಆ್ಯಪ್‌ಗಳನ್ನು <xliff:g id="DATE">%1$s</xliff:g> ರಂದು <xliff:g id="TIME">%2$s</xliff:g> ಸಮಯಕ್ಕೆ ನಿರ್ಬಂಧಿಸಲಾಗುತ್ತದೆ. ನಿಮ್ಮ ಐಟಿ ನಿರ್ವಾಹಕರು ನಿಮ್ಮ ಕೆಲಸದ ಪ್ರೊಫೈಲ್ ಅನ್ನು <xliff:g id="NUMBER">%3$d</xliff:g> ದಿನಗಳಿಗಿಂತ ಹೆಚ್ಚು ಕಾಲ ಉಳಿಯಲು ಅನುಮತಿಸುವುದಿಲ್ಲ."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"ಆನ್"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"ಕರೆಗಳು ಮತ್ತು ಸಂದೇಶಗಳು ಆಫ್ ಆಗಿವೆ"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್‌ಗಳನ್ನು ನೀವು ವಿರಾಮಗೊಳಿಸಿದ್ದೀರಿ ನೀವು ಫೋನ್ ಕರೆಗಳು ಅಥವಾ ಪಠ್ಯ ಸಂದೇಶಗಳನ್ನು ಸ್ವೀಕರಿಸುವುದಿಲ್ಲ."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್ ವಿರಾಮ ರದ್ದುಮಾಡಿ"</string>
<string name="me" msgid="6207584824693813140">"ನಾನು"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"ಟ್ಯಾಬ್ಲೆಟ್ ಆಯ್ಕೆಗಳು"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV ಆಯ್ಕೆಗಳು"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ಸಾಧನದ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್‌ನಲ್ಲಿ ನಡೆಸಿದ ಗೆಶ್ಚರ್‌ಗಳನ್ನು ಕ್ಯಾಪ್ಚರ್ ಮಾಡಿ."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ತೆಗೆದುಕೊಳ್ಳಿ"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ಪ್ರದರ್ಶನದ ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಅನ್ನು ತೆಗೆದುಕೊಳ್ಳಬಲ್ಲದು."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"ಪೂರ್ವವೀಕ್ಷಣೆ, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ ಇಲ್ಲವೇ ಮಾರ್ಪಡಿಸಿ"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ಅಥವಾ ಸೇರಿಸಲು ಮತ್ತು ಸಿಸ್ಟಂ ಐಕಾನ್‌ಗಳನ್ನು ತೆಗೆದುಹಾಕಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯಾಗಿರಲು"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"USB ಮೂಲಕ PTP ಆನ್‌ ಆಗಿದೆ"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"USB ಟೆಥರಿಂಗ್ ಆನ್ ಆಗಿದೆ"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"USB ಮೂಲಕ MIDI ಆನ್‌ ಆಗಿದೆ"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"ಸಾಧನವನ್ನು ವೆಬ್‌ಕ್ಯಾಮ್‌ನಂತೆ ಕನೆಕ್ಟ್ ಮಾಡಲಾಗಿದೆ"</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>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"ಪೂರ್ಣಗೊಂಡಿದೆ"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"ಶಾರ್ಟ್‌ಕಟ್‌ ಆಫ್ ಮಾಡಿ"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ಶಾರ್ಟ್‌ಕಟ್ ಬಳಸಿ"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"ಬಣ್ಣದ ವಿಲೋಮ"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"ಬಣ್ಣದ ತಿದ್ದುಪಡಿ"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"ಒಂದು ಕೈ ಮೋಡ್‌"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ಇನ್ನಷ್ಟು ಮಬ್ಬು"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 6b800a8dae79..348dcd502a97 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"직장 프로필을 사용 설정할 때까지 개인 앱이 차단됩니다."</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"개인 앱이 <xliff:g id="DATE">%1$s</xliff:g> <xliff:g id="TIME">%2$s</xliff:g>에 차단됩니다. IT 관리자가 <xliff:g id="NUMBER">%3$d</xliff:g>일 넘게 직장 프로필을 중지하도록 허용하지 않습니다."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"사용 설정"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"전화 및 메시지 사용 중지됨"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"직장 앱을 일시중지했습니다. 전화나 문자 메시지를 수신하지 않습니다."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"직장 앱 일시중지 해제"</string>
<string name="me" msgid="6207584824693813140">"나"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"태블릿 옵션"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV 옵션"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"기기 지문 센서에서 동작을 캡처합니다."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"스크린샷 촬영"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"디스플레이 스크린샷을 촬영할 수 있습니다."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"미리보기, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"상태 표시줄 사용 중지 또는 수정"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"앱이 상태 표시줄을 사용중지하거나 시스템 아이콘을 추가 및 제거할 수 있도록 허용합니다."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"상태 표시줄에 위치"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"USB를 통해 PTP 사용 설정됨"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"USB 테더링 사용 설정됨"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"USB를 통해 MIDI 사용 설정됨"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"기기가 웹캠으로 연결됨"</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>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"완료"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"단축키 사용 중지"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"단축키 사용"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"색상 반전"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"색상 보정"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"한 손 모드"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"더 어둡게"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index b4a0ccd289f3..90d60e66b629 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Жумуш профилиңизди күйгүзмөйүнчө жеке колдонмолоруңуз бөгөттөлгөн боюнча калат"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Жеке колдонмолор <xliff:g id="DATE">%1$s</xliff:g> саат <xliff:g id="TIME">%2$s</xliff:g> бөгөттөлөт. IT администраторуңуз жумуш профилиңизди <xliff:g id="NUMBER">%3$d</xliff:g> күндөн ашык убакытка өчүрүүгө уруксат бербейт."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Күйгүзүү"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Чалуулар жана билдирүүлөр өчүк"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Жумуш колдонмолорун тындырып койдуңуз. Эми сизге эч ким телефон чала албайт жана SMS билдирүүлөрүн жөнөтө албайт."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Жумуш колдонмолорун иштетүү"</string>
<string name="me" msgid="6207584824693813140">"Мен"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Планшет мүмкүнчүлүктөрү"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV параметрлери"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Түзмөктөгү манжа изинин сенсорунда жасалган жаңсоолорду жаздырып алат."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Скриншот тартып алуу"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Дисплейдин скриншотун тартып алсаңыз болот."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Алдын ала көрүү, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"абал тилкесин өчүрүү же өзгөртүү"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Колдонмого абал тилкесин өчүрүү же тутум сүрөтчөлөрүн кошуу же алып салуу мүмкүнчүлүгүн берет."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"абал тилкесинин милдетин аткаруу"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"USB аркылуу PTP режими күйгүзүлдү"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"USB модем күйгүзүлдү"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"USB аркылуу MIDI режими күйгүзүлдү"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Түзмөк веб-камера катары туташты"</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>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Бүттү"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Кыска жолду өчүрүү"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Кыска жолду колдонуу"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Түстөрдү инверсиялоо"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Түстөрдү тууралоо"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Бир кол режими"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Кошумча караңгылатуу"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index ad7c77f0df4a..63854c32eb07 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"ແອັບສ່ວນຕົວຂອງທ່ານຈະຖືກບລັອກໄວ້ຈົນກວ່າທ່ານຈະເປີດໃຊ້​ໂປຣ​ໄຟລ໌​ບ່ອນ​ເຮັດ​ວຽກຂອງທ່ານ"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"ແອັບສ່ວນຕົວຈະຖືກບລັອກໃນວັນທີ <xliff:g id="DATE">%1$s</xliff:g> ເວລາ <xliff:g id="TIME">%2$s</xliff:g>. ຜູ້ເບິ່ງແຍງລະບົບໄອທີຂອງທ່ານບໍ່ອະນຸຍາດໃຫ້ປິດໂປຣໄຟລ໌ບ່ອນເຮັດວຽກຂອງທ່ານເກີນ <xliff:g id="NUMBER">%3$d</xliff:g> ມື້."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"ເປີດໃຊ້"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"ໂທ ແລະ ຂໍ້ຄວາມປິດຢູ່"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"ທ່ານໄດ້ຢຸດແອັບບ່ອນເຮັດວຽກໄວ້ຊົ່ວຄາວແລ້ວ. ທ່ານຈະບໍ່ໄດ້ຮັບການໂທທາງໂທລະສັບ ຫຼື ຂໍ້ຄວາມ."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"ແອັບບ່ອນເຮັດວຽກເຊົາຢຸດໄວ້ຊົ່ວຄາວ"</string>
<string name="me" msgid="6207584824693813140">"ຂ້າພະເຈົ້າ"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"ໂຕເລືອກແທັບເລັດ"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"ຕົວເລືອກ Android TV"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ສາມາດບັນທຶກທ່າທາງທີ່ເກີດຂຶ້ນໃນອຸປະກອນເຊັນເຊີລາຍນິ້ວມືໄດ້."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ຖ່າຍຮູບໜ້າຈໍ"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ສາມາດຖ່າຍຮູບໜ້າຈໍໄດ້."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"ຕົວຢ່າງ, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"ປິດການນນຳໃຊ້ ຫຼື ແກ້ໄຂແຖບສະຖານະ"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"ອະນຸຍາດໃຫ້ແອັບຯປິດການເຮັດວຽກຂອງແຖບສະຖານະ ຫຼືເພີ່ມ ແລະລຶບໄອຄອນລະບົບອອກໄດ້."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"ເປັນ​ແຖບ​ສະ​ຖາ​ນະ"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"ເປີດໂໝດ PTP ຜ່ານ USB ແລ້ວ"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"ເປີດໂໝດ USB tethering ແລ້ວ"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"ເປີດໃຊ້ MIDI ຜ່ານ USB ແລ້ວ"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"ເຊື່ອມຕໍ່ອຸປະກອນເປັນເວັບແຄມ"</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>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"ແລ້ວໆ"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"ປິດປຸ່ມລັດ"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ໃຊ້ປຸ່ມລັດ"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"ການປີ້ນສີ"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"ການແກ້ໄຂສີ"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"ໂໝດມືດຽວ"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ຫຼຸດແສງເປັນພິເສດ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 8e28dff79f2d..84603252f464 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -209,6 +209,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Asmeninės programos bus užblokuotos, kol įjungsite darbo profilį"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Asmeninės programos bus užblokuotos <xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>. IT administratorius neleidžia palikti darbo profilio išjungto ilgiau nei <xliff:g id="NUMBER">%3$d</xliff:g> d."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Įjungti"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Skambučiai ir pranešimai išjungti"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Pristabdėte darbo programas. Negausite skambučių ir teksto pranešimų."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Atš. darbo progr. pristabd."</string>
<string name="me" msgid="6207584824693813140">"Aš"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Planšetinio kompiuterio parinktys"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"„Android TV“ parinktys"</string>
@@ -340,6 +343,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Gali užfiksuoti gestus, atliktus naudojant įrenginio piršto antspaudo jutiklį."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ekrano kopijos kūrimas"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Galima sukurti vaizdo ekrano kopiją."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Peržiūra, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"išjungti ar keisti būsenos juostą"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Leidžiama programai neleisti būsenos juostos arba pridėti ir pašalinti sistemos piktogramas."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"būti būsenos juosta"</string>
@@ -1360,8 +1364,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"PTP režimas naudojant USB įjungtas"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"USB įrenginio kaip modemo naudojimas įjungtas"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"MIDI režimas naudojant USB įjungtas"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Įrenginys prijungtas kaip žiniatinklio kamera"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"Prijungtas USB priedas"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Palieskite, kad būtų rodoma daugiau parinkčių."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Įkraunamas prijungtas įrenginys. Palieskite, jei reikia daugiau parinkčių."</string>
@@ -1710,8 +1713,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Atlikta"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Išjungti spartųjį klavišą"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Naudoti spartųjį klavišą"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Spalvų inversija"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Spalvų taisymas"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Vienos rankos režimas"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Itin blanku"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index b69954999558..5d3d46f34cf3 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -208,6 +208,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Jūsu personīgās lietotnes būs bloķētas, līdz ieslēgsiet savu darba profilu."</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Personīgās lietotnes tiks bloķētas šādā datumā: <xliff:g id="DATE">%1$s</xliff:g>, plkst. <xliff:g id="TIME">%2$s</xliff:g>. Jūsu IT administrators neatļauj atspējot darba profilu ilgāk par <xliff:g id="NUMBER">%3$d</xliff:g> dienām."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Ieslēgt"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Zvani un īsziņas ir izslēgtas"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Jūs pārtraucāt darba lietotņu darbību. Nesaņemsiet tālruņa zvanus un īsziņas."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Atsākt darbību"</string>
<string name="me" msgid="6207584824693813140">"Man"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Planšetdatora opcijas"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV opcijas"</string>
@@ -339,6 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Var uztvert žestus ierīces pirksta nospieduma sensorā."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ekrānuzņēmuma izveide"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Var izveidot displeja ekrānuzņēmumu."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"<xliff:g id="DREAM_NAME">%1$s</xliff:g> (priekšskatījums)"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"atspējot vai pārveidot statusa joslu"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Ļauj lietotnei atspējot statusa joslu vai pievienot un noņemt sistēmas ikonas."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"Būt par statusa joslu"</string>
@@ -1359,8 +1363,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"Ieslēgts PTP režīms, izmantojot USB savienojumu"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Ieslēgta USB piesaiste"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"Ieslēgts MIDI režīms, izmantojot USB savienojumu"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Ierīce pievienota kā tīmekļa kamera"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"USB piederums ir pievienots"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Pieskarieties, lai skatītu citas opcijas."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Pievienotā ierīce tiek uzlādēta. Pieskarieties, lai skatītu citas opcijas."</string>
@@ -1709,8 +1712,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Gatavs"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Izslēgt saīsni"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Izmantot saīsni"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Krāsu inversija"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Krāsu korekcija"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Vienas rokas režīms"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Papildu aptumšošana"</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 4524b3952f17..ff1db65efb75 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Вашите лични апликации се блокирани додека да го вклучите работниот профил"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Личните апликации ќе се блокираат на <xliff:g id="DATE">%1$s</xliff:g> во <xliff:g id="TIME">%2$s</xliff:g>. Вашиот IT администратор не дозволува вашиот работен профил да биде исклучен повеќе од <xliff:g id="NUMBER">%3$d</xliff:g> денови."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Вклучи"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Повиците и пораките се исклучени"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Ги паузиравте работните апликации. Нема да добивате телефонски повици или текстуални пораки."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Актив. раб. апл."</string>
<string name="me" msgid="6207584824693813140">"Јас"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Опции на таблет"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Опции на Android TV"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Може да сними движења што се направени на сензорот за отпечатоци на уредот."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Зачувување слика од екранот"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Може да зачува слика од екранот."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Преглед, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"оневозможи или измени статусна лента"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Дозволува апликацијата да ја оневозможи статусната лента или да додава или отстранува системски икони."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"да стане статусна лента"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"Вклучен е PTP преку USB"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Вклучен е интернет преку USB"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"Вклучен е MIDI преку USB"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Уредот е поврзан како веб-камера"</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>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Готово"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Исклучи ја кратенката"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Користи кратенка"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Инверзија на боите"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Корекција на боите"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Режим со една рака"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Дополнително затемнување"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 51c176350eaa..51e8c59ac109 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"നിങ്ങളുടെ ഔദ്യോഗിക പ്രൊഫൈൽ ഓണാക്കുന്നത് വരെ നിങ്ങളുടെ വ്യക്തിപരമായ ആപ്പുകൾ ബ്ലോക്കായിരിക്കും"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"വ്യക്തിപര ആപ്പുകൾ <xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>-ന് ബ്ലോക്ക് ചെയ്യപ്പെടും. നിങ്ങളുടെ ഔദ്യോഗിക പ്രൊഫൈൽ <xliff:g id="NUMBER">%3$d</xliff:g> ദിവസത്തിൽ കൂടുതൽ ഓഫായ നിലയിൽ തുടരാൻ നിങ്ങളുടെ ഐടി അഡ്‌മിൻ അനുവദിക്കുന്നില്ല."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"ഓണാക്കുക"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"കോളുകളും സന്ദേശങ്ങളും ഓഫാണ്"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"നിങ്ങൾ ഔദ്യോഗിക ആപ്പുകൾ താൽകാലികമായി നിർത്തി. നിങ്ങൾക്ക് ഫോൺ കോളുകളോ ടെക്സ്റ്റ് സന്ദേശങ്ങളോ ലഭിക്കില്ല."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"വർക്ക് ആപ്പ് ഓണാക്കൂ"</string>
<string name="me" msgid="6207584824693813140">"ഞാന്‍"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"ടാബ്‌ലെറ്റ് ഓപ്‌ഷനുകൾ"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV ഓപ്‌ഷനുകൾ"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ഉപകരണത്തിന്റെ ഫിംഗർപ്രിന്റ് സെൻസറിൽ ചെയ്‌ത ജെസ്‌റ്ററുകൾ ക്യാപ്‌ചർ ചെയ്യാനാകും."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"സ്ക്രീന്‍ഷോട്ട് എടുക്കുക"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ഡിസ്‌പ്ലേയുടെ സ്‌ക്രീൻഷോട്ട് എടുക്കാൻ കഴിയും."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"പ്രിവ്യൂ, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"സ്റ്റാറ്റസ് ബാർ പ്രവർത്തനരഹിതമാക്കുക അല്ലെങ്കിൽ പരിഷ്‌ക്കരിക്കുക"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"നില ബാർ പ്രവർത്തരഹിതമാക്കുന്നതിന് അല്ലെങ്കിൽ സിസ്‌റ്റം ഐക്കണുകൾ ചേർക്കുന്നതിനും നീക്കംചെയ്യുന്നതിനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"സ്റ്റാറ്റസ് ബാർ ആയിരിക്കുക"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"USB വഴിയുള്ള PTP ഓണാക്കി"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"USB ടെതറിംഗ് ഓണാക്കി"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"USB വഴിയുള്ള MIDI ഓണാക്കി"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"ഉപകരണം വെബ്‌ക്യാം ആയി കണക്റ്റ് ചെയ്തു"</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>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"പൂർത്തിയാക്കി"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"കുറുക്കുവഴി ‌ഓഫാക്കുക"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"കുറുക്കുവഴി ഉപയോഗിക്കുക"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"നിറം വിപരീതമാക്കൽ"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"നിറം ശരിയാക്കൽ"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"ഒറ്റക്കൈ മോഡ്"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"കൂടുതൽ ഡിം ചെയ്യൽ"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 181fa723e632..760cb14f23a4 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Та ажлын профайлыг асаах хүртэл таны хувийн аппуудыг хориглосон"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Хувийн аппуудыг <xliff:g id="DATE">%1$s</xliff:g>-н <xliff:g id="TIME">%2$s</xliff:g>-д блоклоно. Таны IT админ таны ажлын профайлыг <xliff:g id="NUMBER">%3$d</xliff:g>-с олон хоног унтраалттай байхыг зөвшөөрдөггүй."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Асаах"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Дуудлага болон мессеж унтраалттай байна"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Та ажлын аппуудыг түр зогсоосон. Та утасны дуудлага эсвэл мессеж хүлээн авахгүй."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Ажлын аппыг үргэлжлүүл"</string>
<string name="me" msgid="6207584824693813140">"Би"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Таблетын сонголтууд"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV-н сонголт"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Төхөөрөмжийн хурууны хээ мэдрэгчид зангасан зангааг танина."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Дэлгэцийн зургийг дарах"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Дэлгэцийн зургийг дарах боломжтой."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Урьдчилан үзэх, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"статус самбарыг идэвхгүй болгох болон өөрчлөх"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Апп нь статус самбарыг идэвхгүй болгох эсвэл систем дүрсийг нэмэх, хасах боломжтой."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"статусын хэсэг болох"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"USB-р PTP горимд асаасан"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"USB модем болгохыг асаасан"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"USB-р MIDI горимд асаасан"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Төхөөрөмж вебкамер байдлаар холбогдсон"</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>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Болсон"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Товчлолыг унтраах"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Товчлол ашиглах"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Өнгө урвуулах"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Өнгөний засвар"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Нэг гарын горим"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Хэт бүүдгэр"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 923dcde7287f..73b19aa72c5f 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"तुम्ही तुमची कार्य प्रोफाइल सुरू करेपर्यंत तुमची वैयक्तिक ॲप्स ब्लॉक केली आहेत"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"वैयक्तिक ॲप्स <xliff:g id="DATE">%1$s</xliff:g> रोजी <xliff:g id="TIME">%2$s</xliff:g> वाजता ब्लॉक केली जातील. तुमचा आयटी अ‍ॅडमिन तुमची कार्य प्रोफाइल <xliff:g id="NUMBER">%3$d</xliff:g> पेक्षा जास्त दिवसांसाठी बंद ठेवण्याची अनुमती देत नाही."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"सुरू करा"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"कॉल आणि मेसेज बंद आहेत"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"तुम्ही कामासंबंधित ॲप्स थांबवली आहेत. तुम्हाला फोन कॉल किंवा एसएमएस मिळणार नाहीत."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"वर्क ॲप्स अनपॉझ करा"</string>
<string name="me" msgid="6207584824693813140">"मी"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"टॅबलेट पर्याय"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV पर्याय"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"डिव्‍हाइसच्‍या फिंगरप्रिंट सेंन्सरवरील जेश्चर कॅप्‍चर करू शकते."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"स्क्रीनशॉट घ्या"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"डिस्प्लेचा स्क्रीनशॉट घेऊ शकतो."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"पूर्वावलोकन, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"स्टेटस बार अक्षम करा किंवा सुधारित करा"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"स्टेटस बार अक्षम करण्यासाठी किंवा सिस्टम चिन्हे जोडण्यासाठी आणि काढण्यासाठी अ‍ॅप ला अनुमती देते."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"स्टेटस बार होऊ द्या"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"USB मार्फत PTP सुरू केले"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"USB टेदरिंग सुरू केले"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"USB मार्फत MIDI सुरू केले"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"डिव्हाइसला वेबकॅम म्हणून कनेक्ट केले"</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>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"पूर्ण झाले"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"शॉर्टकट बंद करा"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"शॉर्टकट वापरा"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"कलर इन्व्हर्जन"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"रंग सुधारणा"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"एकहाती मोड"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"आणखी डिम"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index cc0e947940b8..231d6ad859dc 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Apl peribadi anda disekat sehingga anda menghidupkan profil kerja"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Apl peribadi akan disekat pada <xliff:g id="DATE">%1$s</xliff:g> pukul <xliff:g id="TIME">%2$s</xliff:g>. Pentadbir IT anda tidak membenarkan profil kerja anda dimatikan melebihi <xliff:g id="NUMBER">%3$d</xliff:g> hari."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Hidupkan"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Panggilan dan mesej dimatikan"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Anda telah menjeda apl kerja. Anda tidak akan menerima panggilan telefon atau mesej teks."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Nyahjeda apl kj"</string>
<string name="me" msgid="6207584824693813140">"Saya"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Pilihan tablet"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Pilihan Android TV"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Boleh menangkap gerak isyarat yang dilakukan pada penderia cap jari peranti."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ambil tangkapan skrin"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Boleh mengambil tangkapan skrin paparan."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Pratonton, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"lumpuhkan atau ubah suai bar status"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Membenarkan apl melumpuhkan bar status atau menambah dan mengalih keluar ikon sistem."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"jadi bar status"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"PTP melalui USB dihidupkan"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Penambatan USB dihidupkan"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"MIDI melalui USB dihidupkan"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Peranti disambungkan sebagai Kamera Web"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"Aksesori USB disambungkan"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Ketik untuk mendapatkan lagi pilihan."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Mengecas peranti tersambung. Ketik untuk mendapatkan lagi pilihan."</string>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Selesai"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Matikan pintasan"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Gunakan Pintasan"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Penyongsangan warna"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Pembetulan warna"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Mod sebelah tangan"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Amat malap"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 1018e1e93736..f7cb067f2d76 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"သင့်အလုပ်ပရိုဖိုင် ဖွင့်သည်အထိ ကိုယ်ပိုင်အက်ပ်များကို ပိတ်ထားသည်"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"ကိုယ်ပိုင်အက်ပ်များကို <xliff:g id="DATE">%1$s</xliff:g> <xliff:g id="TIME">%2$s</xliff:g> တွင် ပိတ်ပါမည်။ သင့်အလုပ်ပရိုဖိုင် <xliff:g id="NUMBER">%3$d</xliff:g> ရက်ထက်ပိုပြီး ပိတ်ထားခြင်းကို သင်၏ IT စီမံခန့်ခွဲသူက ခွင့်မပြုပါ။"</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"ဖွင့်ရန်"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"ခေါ်ဆိုမှုနှင့် မက်ဆေ့ဂျ်များ ပိတ်ထားသည်"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"အလုပ်သုံးအက်ပ်များကို သင်ခဏရပ်လိုက်ပါပြီ။ ဖုန်းခေါ်ဆိုမှု (သို့) မိုဘိုင်းမက်ဆေ့ဂျ်များ ရရှိမည်မဟုတ်ပါ။"</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"အလုပ်သုံးအက်ပ် ဆက်သုံးရန်"</string>
<string name="me" msgid="6207584824693813140">"ကျွန်ုပ်"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Tabletဆိုင်ရာရွေးချယ်မှုများ"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV ရွေးချယ်စရာများ"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"စက်ပစ္စည်း၏ လက်ဗွေအာရုံခံကိရိယာတွင် လုပ်ဆောင်ထားသည့် လက်ဟန်များကို မှတ်သားထားနိုင်သည်။"</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ဖန်သားပြင်ဓာတ်ပုံ ရိုက်ရန်"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ဖန်သားပြင်ပြသမှုကို ဓာတ်ပုံရိုက်နိုင်ပါသည်။"</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"<xliff:g id="DREAM_NAME">%1$s</xliff:g> အစမ်းကြည့်ခြင်း"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"အခြေအနေပြဘားအား အလုပ်မလုပ်ခိုင်းရန်သို့မဟုတ် မွမ်းမံရန်"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"အက်ပ်အား အခြေအနေပြ ဘားကို ပိတ်ခွင့် သို့မဟတ် စနစ် အိုင်ကွန်များကို ထည့်ခြင်း ဖယ်ရှားခြင်း ပြုလုပ်ခွင့် ပြုသည်။"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"အခြေအနေပြ ဘားဖြစ်ပါစေ"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"USB မှတစ်ဆင့် PTP ကို အသုံးပြုရန် ဖွင့်ထားသည်"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"USB မှတစ်ဆင့် မိုဘိုင်းဖုန်းကို မိုဒမ်အဖြစ်သုံးရန် ဖွင့်ထားသည်"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"USB မှတစ်ဆင့် MIDI ကို အသုံးပြုရန် ဖွင့်ထားသည်"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"စက်ပစ္စည်းကို ‘ဝဘ်ကမ်’ အဖြစ် ချိတ်ဆက်လိုက်သည်"</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>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"ပြီးပြီ"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"ဖြတ်လမ်းလင့်ခ်ကို ပိတ်ရန်"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ဖြတ်လမ်းလင့်ခ်ကို သုံးရန်"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"အရောင်ပြောင်းပြန်ပြုလုပ်ခြင်း"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"အရောင် အမှန်ပြင်ခြင်း"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"လက်တစ်ဖက်သုံးမုဒ်"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ပိုမှိန်ခြင်း"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 35296a9030d6..e5e862943efe 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"De personlige appene dine er blokkert til du slår på jobbprofilen din"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Personlige apper blir blokkert <xliff:g id="DATE">%1$s</xliff:g> klokken <xliff:g id="TIME">%2$s</xliff:g>. IT-administratoren din tillater ikke at jobbprofilen din er slått av i mer enn <xliff:g id="NUMBER">%3$d</xliff:g> dager."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Slå på"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Anrop og meldinger er slått av"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Du har satt jobbapper på pause. Du mottar ikke telefonanrop eller tekstmeldinger."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Skru dem på"</string>
<string name="me" msgid="6207584824693813140">"Meg"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Innstillinger for nettbrettet"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV-alternativer"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Kan fange inn bevegelser som utføres på enhetens fingeravtrykkssensor."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ta skjermdump"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Kan ikke ta en skjermdump av skjermen."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Forhåndsvisning, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"deaktivere eller endre statusfeltet"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Lar appen deaktivere statusfeltet eller legge til og fjerne systemikoner."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"vise appen i statusfeltet"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"PTP via USB er slått på"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"USB-internettdeling er slått på"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"MIDI via USB er slått på"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Enheten er koblet til som nettkamera"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"USB-tilbehør er tilkoblet"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Trykk for å få flere alternativ."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Den tilkoblede enheten lades. Trykk for å se flere alternativer."</string>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Ferdig"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Slå av snarveien"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Bruk snarveien"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Fargeinvertering"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Fargekorrigering"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Enhåndsmodus"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Ekstra dimmet"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index e1de195cf125..d91ad0837075 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"तपाईंले आफ्नो कार्य प्रोफाइल सक्रिय नगरुन्जेल तपाईंका व्यक्तिगत एपहरूलाई रोक लगाइन्छ"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"मिति <xliff:g id="DATE">%1$s</xliff:g> <xliff:g id="TIME">%2$s</xliff:g> बजे व्यक्तिगत एपहरूलाई रोक लगाइने छ। तपाईंका IT एडमिन तपाईंलाई आफ्नो कार्य प्रोफाइल <xliff:g id="NUMBER">%3$d</xliff:g> भन्दा धेरै दिन निष्क्रिय राख्ने अनुमति दिनुहुन्न।"</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"अन गर्नुहोस्"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"कल वा म्यासेज अफ गरिएको छ"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"तपाईंले कामसम्बन्धी एपहरू पज गर्नुभएको छ। तपाईं फोन कल वा टेक्स्ट म्यासेजहरू प्राप्त गर्नु हुने छैन।"</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"कामसम्बन्धी एपहरू सुचारु गर्नुहोस्"</string>
<string name="me" msgid="6207584824693813140">"मलाई"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"ट्याब्लेट विकल्पहरू"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android टिभी सम्बन्धी विकल्पहरू"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"यसले यन्त्रक‍ो फिंगरप्रिन्टसम्बन्धी सेन्सरमा गरिएका इसाराहरूलाई खिच्‍न सक्छ।"</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"स्क्रिनसट लिनुहोस्"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"डिस्प्लेको स्क्रिनसट लिन सकिन्छ।"</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"प्रिभ्यू, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"स्थिति पट्टिलाई अक्षम वा संशोधित गर्नुहोस्"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"स्थिति पट्टि असक्षम पार्न वा प्रणाली आइकनहरू थप्न र हटाउन एपलाई अनुमति दिन्छ।"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"स्टाटस बार हुन दिनुहोस्"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"USB मार्फत PTP सेवा सक्रिय गरियो"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"USB टेदरिङ सेवा सक्रिय गरियो"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"USB मार्फत MIDI सेवा सक्रिय गरियो"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"यो डिभाइस वेबक्यामका रूपमा कनेक्ट गरिएको छ"</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>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"सम्पन्न भयो"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"सर्टकटलाई निष्क्रिय पार्नुहोस्"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"सर्टकट प्रयोग गर्नुहोस्"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"कलर इन्भर्सन"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"रङ सच्याउने सुविधा"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"एक हाते मोड"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"अझै मधुरो"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 6c6c0b40fdeb..2955a35796b8 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Je persoonlijke apps zijn geblokkeerd totdat je je werkprofiel aanzet"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Apps die worden gebruikt voor persoonlijke doeleinden, worden geblokkeerd op <xliff:g id="DATE">%1$s</xliff:g> om <xliff:g id="TIME">%2$s</xliff:g>. Je IT-beheerder staat niet toe dat je werkprofiel langer dan <xliff:g id="NUMBER">%3$d</xliff:g> dagen uitstaat."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Aanzetten"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Gesprekken en berichten zijn uitgezet"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Je hebt werk-apps gepauzeerd. Je krijgt geen telefoongesprekken of tekstberichten."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Werk-apps hervatten"</string>
<string name="me" msgid="6207584824693813140">"Ik"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Tabletopties"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Opties voor Android TV"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Kan gebaren registreren die op de vingerafdruksensor van het apparaat worden getekend."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Screenshot maken"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Kan een screenshot van het scherm maken."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Voorbeeld, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"statusbalk uitzetten of wijzigen"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Hiermee kan de app de statusbalk uitzetten of systeemiconen toevoegen en verwijderen."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"de statusbalk zijn"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"PTP via USB staat aan"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"USB-tethering staat aan"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"MIDI via USB staat aan"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Apparaat verbonden als webcam"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"USB-accessoire verbonden"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Tik voor meer opties."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Verbonden apparaat wordt opgeladen. Tik voor meer opties."</string>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Klaar"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Sneltoets uitzetten"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Sneltoets gebruiken"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Kleurinversie"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Kleurcorrectie"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Bediening met 1 hand"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Extra dimmen"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 0cbe22ec3dec..8b0df2ef2aca 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"ଆପଣ ଆପଣଙ୍କ ୱାର୍କ ପ୍ରୋଫାଇଲ୍ ଚାଲୁ ନକରିବା ପର୍ଯ୍ୟନ୍ତ ଆପଣଙ୍କର ବ୍ୟକ୍ତିଗତ ଆପ୍ସ ବ୍ଲକ୍ କରାଯାଇଛି"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"<xliff:g id="DATE">%1$s</xliff:g> <xliff:g id="TIME">%2$s</xliff:g>ରେ ଆପଣଙ୍କ ବ୍ୟକ୍ତିଗତ ଆପ୍ସକୁ ବ୍ଲକ୍ କରାଯିବ। ଆପଣଙ୍କ IT ଆଡମିନ୍ ଆପଣଙ୍କ ୱାର୍କ ପ୍ରୋଫାଇଲକୁ <xliff:g id="NUMBER">%3$d</xliff:g>ରୁ ଅଧିକ ଦିନ ପାଇଁ ବନ୍ଦ କରିବାକୁ ଅନୁମତି ଦିଅନ୍ତି ନାହିଁ।"</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"ଚାଲୁ କରନ୍ତୁ"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"କଲ ଏବଂ ମେସେଜଗୁଡ଼ିକ ବନ୍ଦ ଅଛି"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"ଆପଣ ୱାର୍କ ଆପ୍ସକୁ ବିରତ କରିଦେଇଛନ୍ତି। ଆପଣ ଫୋନ କଲ କିମ୍ବା ଟେକ୍ସଟ ମେସେଜ ପାଇବେ ନାହିଁ।"</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"ୱାର୍କ ଆପ୍ସ ପୁଣି ଚାଲୁ କର"</string>
<string name="me" msgid="6207584824693813140">"ମୁଁ"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"ଟାବଲେଟ୍‌ର ବିକଳ୍ପ"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TVର ବିକଳ୍ପଗୁଡ଼ିକ"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ଡିଭାଇସ୍‌ର ଟିପଚିହ୍ନ ସେନସର୍ ଉପରେ ଜେଶ୍ଚର୍‍ କ୍ୟାପଚର୍‍ କାର୍ଯ୍ୟ କରାଯାଇପାରିବ।"</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ସ୍କ୍ରିନସଟ୍ ନିଅନ୍ତୁ"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ଡିସପ୍ଲେର ଏକ ସ୍କ୍ରିନସଟ୍ ନିଆଯାଇପାରେ।"</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"ପ୍ରିଭ୍ୟୁ, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"ଷ୍ଟାଟସ୍‌ ବାର୍‌କୁ ଅକ୍ଷମ କିମ୍ୱା ସଂଶୋଧନ କରନ୍ତୁ"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"ଆପ୍‍କୁ, ସ୍ଥିତି ବାର୍‍ ଅକ୍ଷମ କରିବାକୁ କିମ୍ବା ସିଷ୍ଟମ୍‍ ଆଇକନ୍‍ ଯୋଡ଼ିବା କିମ୍ବା ବାହାର କରିବାକୁ ଦେଇଥାଏ।"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"ଷ୍ଟାଟସ୍‍ ବାର୍‍ ରହିବାକୁ ଦିଅନ୍ତୁ"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"USB ମାଧ୍ୟମରେ PTPକୁ ଚାଲୁ କରାଗଲା"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"USB ଟିଥରିଙ୍ଗ ଚାଲୁ କରାଗଲା"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"USB ମାଧ୍ୟମରେ MIDIକୁ ଚାଲୁ କରାଗଲା"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"ୱେବକେମ ଭାବେ ଡିଭାଇସ କନେକ୍ଟ କରାଯାଇଛି"</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>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"ହୋଇଗଲା"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"ଶର୍ଟକଟ୍‍ ବନ୍ଦ କରନ୍ତୁ"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ଶର୍ଟକଟ୍‍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"କଲର ଇନଭର୍ସନ"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"ରଙ୍ଗ ସଂଶୋଧନ"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"ଏକ-ହାତ ମୋଡ୍"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ଅତ୍ୟଧିକ ଡିମ"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index a41cde195ac3..d5414e38a41d 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਆਪਣਾ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਚਾਲੂ ਨਹੀਂ ਕਰਦੇ ਤੁਹਾਡੀਆਂ ਨਿੱਜੀ ਐਪਾਂ ਬਲਾਕ ਰਹਿੰਦੀਆਂ ਹਨ"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"<xliff:g id="DATE">%1$s</xliff:g> ਨੂੰ <xliff:g id="TIME">%2$s</xliff:g> ਵਜੇ ਨਿੱਜੀ ਐਪਾਂ ਨੂੰ ਬਲਾਕ ਕਰ ਦਿੱਤਾ ਜਾਵੇਗਾ। ਤੁਹਾਡਾ ਆਈ.ਟੀ. ਪ੍ਰਸ਼ਾਸਕ ਤੁਹਾਡੇ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਨੂੰ <xliff:g id="NUMBER">%3$d</xliff:g> ਦਿਨਾਂ ਤੋਂ ਵੱਧ ਸਮੇਂ ਤੱਕ ਬੰਦ ਰਹਿਣ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਦਿੰਦਾ।"</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"ਚਾਲੂ ਕਰੋ"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"ਕਾਲਾਂ ਅਤੇ ਸੁਨੇਹੇ ਸੁਵਿਧਾ ਬੰਦ ਹੈ"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"ਤੁਸੀਂ ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ ਨੂੰ ਰੋਕ ਦਿੱਤਾ ਹੈ। ਤੁਹਾਨੂੰ ਫ਼ੋਨ ਕਾਲਾਂ ਅਤੇ ਲਿਖਤ ਸੁਨੇਹੇ ਪ੍ਰਾਪਤ ਨਹੀਂ ਹੋਣਗੇ।"</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ ਤੋਂ ਰੋਕ ਹਟਾਓ"</string>
<string name="me" msgid="6207584824693813140">"ਮੈਂ"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"ਟੈਬਲੈੱਟ ਵਿਕਲਪ"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV ਦੇ ਵਿਕਲਪ"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"ਡੀਵਾਈਸਾਂ ਦੇ ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ \'ਤੇ ਕੀਤੇ ਗਏ ਸੰਕੇਤਾਂ ਨੂੰ ਕੈਪਚਰ ਕਰ ਸਕਦੇ ਹਨ।"</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਲਓ"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ਡਿਸਪਲੇ ਦਾ ਸਕ੍ਰੀਨਸ਼ਾਟ ਲੈ ਸਕਦੀ ਹੈ।"</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"ਪੂਰਵ-ਝਲਕ ਦੇਖੋ, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"ਸਥਿਤੀ ਪੱਟੀ ਬੰਦ ਕਰੋ ਜਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰੋ"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"ਐਪ ਨੂੰ ਸਥਿਤੀ ਪੱਟੀ ਨੂੰ ਚਾਲੂ ਕਰਨ ਜਾਂ ਸਿਸਟਮ ਪ੍ਰਤੀਕਾਂ ਨੂੰ ਜੋੜਨ ਅਤੇ ਹਟਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"ਸਥਿਤੀ ਪੱਟੀ ਬਣਨ ਦਿਓ"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"USB ਰਾਹੀਂ PTP ਚਾਲੂ ਹੈ"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"USB ਟੈਦਰਿੰਗ ਚਾਲੂ ਹੈ"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"USB ਰਾਹੀਂ MIDI ਚਾਲੂ ਹੈ"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"ਡੀਵਾਈਸ ਨੂੰ ਵੈੱਬਕੈਮ ਵਜੋਂ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</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>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"ਹੋ ਗਿਆ"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"ਸ਼ਾਰਟਕੱਟ ਬੰਦ ਕਰੋ"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ਸ਼ਾਰਟਕੱਟ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"ਰੰਗ ਪਲਟਨਾ"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"ਰੰਗ ਸੁਧਾਈ"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"ਇੱਕ ਹੱਥ ਮੋਡ"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ਜ਼ਿਆਦਾ ਘੱਟ ਚਮਕ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 927d84b52380..8c13803f4950 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -209,6 +209,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Zablokowano aplikacje osobiste do czasu włączenia profilu służbowego"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Aplikacje osobiste zostaną zablokowane <xliff:g id="DATE">%1$s</xliff:g> o <xliff:g id="TIME">%2$s</xliff:g>. Administrator IT nie pozwala na wyłączenie profilu służbowego na dłużej niż <xliff:g id="NUMBER">%3$d</xliff:g> dni."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Włącz"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Połączenia i wiadomości są wyłączone"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Aplikacje służbowe zostały wstrzymane. Nie będziesz otrzymywać połączeń telefonicznych ani SMS-ów."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Cofnij wstrzymanie aplikacji służbowych"</string>
<string name="me" msgid="6207584824693813140">"Ja"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Opcje tabletu"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Opcje Androida TV"</string>
@@ -340,6 +343,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Może przechwytywać gesty wykonywane na czytniku linii papilarnych w urządzeniu."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Robienie zrzutu ekranu"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Może robić zrzuty ekranu wyświetlacza."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Podgląd, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"wyłączanie lub zmienianie paska stanu"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Pozwala aplikacji na wyłączanie paska stanu oraz dodawanie i usuwanie ikon systemowych."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"działanie jako pasek stanu"</string>
@@ -1360,8 +1364,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"Tryb PTP przez USB włączony"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Tethering USB włączony"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"Tryb MIDI przez USB włączony"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Urządzenie połączone jako kamera internetowa"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"Podłączono akcesorium USB"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Kliknij, by wyświetlić więcej opcji."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Ładowanie połączonego urządzenia. Kliknij, by wyświetlić więcej opcji."</string>
@@ -1710,8 +1713,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"OK"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Wyłącz skrót"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Użyj skrótu"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Odwrócenie kolorów"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Korekcja kolorów"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Tryb jednej ręki"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Dodatkowe przyciemnienie"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 3a391f6bc8fe..896362ad7ae0 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -208,6 +208,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Seus apps pessoais ficarão bloqueados até você ativar o perfil de trabalho"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Os apps pessoais serão bloqueados em <xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>. Seu administrador de TI não permite que o perfil de trabalho fique desativado por mais de <xliff:g id="NUMBER">%3$d</xliff:g> dias."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Ativar"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Ligações e mensagens desativadas"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Você pausou os apps de trabalho. Ligações e mensagens de texto não vão ser recebidas."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Reativar apps de trabalho"</string>
<string name="me" msgid="6207584824693813140">"Eu"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Opções do tablet"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Opções do Android TV"</string>
@@ -339,6 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Pode captar gestos realizados no sensor de impressão digital do dispositivo."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Fazer uma captura de tela"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Pode fazer uma captura de tela."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Visualização, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"desativar ou modificar a barra de status"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Permite que o app desative a barra de status ou adicione e remova ícones do sistema."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"ser a barra de status"</string>
@@ -1359,8 +1363,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"PTP via USB ativado"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Tethering USB ativado"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"MIDI via USB ativado"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Dispositivo conectado como Webcam"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"Acessório USB conectado"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Toque para ver mais opções."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Carregando dispositivo conectado. Toque para ver mais opções."</string>
@@ -1709,8 +1712,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Concluído"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Desativar atalho"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Usar atalho"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Inversão de cores"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Correção de cor"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modo para uma mão"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Escurecer a tela"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 01374342cc31..78eff1363c2d 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -208,6 +208,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"As suas apps pessoais estão bloqueadas até ativar o seu perfil de trabalho."</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"As apps pessoais serão bloqueadas a <xliff:g id="DATE">%1$s</xliff:g> à(s) <xliff:g id="TIME">%2$s</xliff:g>. O seu administrador de TI não permite que o seu perfil de trabalho fique desativado mais de <xliff:g id="NUMBER">%3$d</xliff:g> dias."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Ativar"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Chamadas e mensagens desativadas"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Pausou as apps de trabalho. Não vai receber chamadas nem mensagens de texto."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Retom. apps tr."</string>
<string name="me" msgid="6207584824693813140">"Eu"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Opções do tablet"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Opções do Android TV"</string>
@@ -339,6 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Pode capturar gestos realizados no sensor de impressões digitais do dispositivo."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Fazer captura de ecrã"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"É possível tirar uma captura de ecrã."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Pré-visualização, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"desativar ou modificar barra de estado"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Permite à app desativar a barra de estado ou adicionar e remover ícones do sistema."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"ser apresentada na barra de estado"</string>
@@ -1236,7 +1240,7 @@
<string name="unsupported_display_size_show" msgid="980129850974919375">"Mostrar sempre"</string>
<string name="unsupported_compile_sdk_message" msgid="7326293500707890537">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> foi concebida para uma versão incompatível do SO Android e pode ter um comportamento inesperado. Pode estar disponível uma versão atualizada da app."</string>
<string name="unsupported_compile_sdk_show" msgid="1601210057960312248">"Mostrar sempre"</string>
- <string name="unsupported_compile_sdk_check_update" msgid="1103639989147664456">"Verificar atualizações"</string>
+ <string name="unsupported_compile_sdk_check_update" msgid="1103639989147664456">"Rever atualizações"</string>
<string name="smv_application" msgid="3775183542777792638">"A app <xliff:g id="APPLICATION">%1$s</xliff:g> (processo <xliff:g id="PROCESS">%2$s</xliff:g>) violou a política StrictMode auto-imposta."</string>
<string name="smv_process" msgid="1398801497130695446">"O processo <xliff:g id="PROCESS">%1$s</xliff:g> violou a política StrictMode auto-imposta."</string>
<string name="android_upgrading_title" product="default" msgid="7279077384220829683">"O telemóvel está a atualizar…"</string>
@@ -1359,8 +1363,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"O PTP por USB está ativado"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"A ligação USB via telemóvel está ativada"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"O MIDI através de USB está ativado"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Dispositivo ligado como câmara Web"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"Acessório USB ligado"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Toque para obter mais opções."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"A carregar o dispositivo ligado. Toque para obter mais opções."</string>
@@ -1709,8 +1712,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Concluído"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Desativar atalho"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utilizar atalho"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Inversão de cores"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Correção da cor"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modo para uma mão"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Mais escuro"</string>
@@ -1975,7 +1977,7 @@
<string name="app_streaming_blocked_message_for_settings_dialog" product="tablet" msgid="3286849551133045896">"Não é possível aceder a esta app no seu dispositivo <xliff:g id="DEVICE">%1$s</xliff:g>. Em alternativa, experimente no tablet."</string>
<string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Não é possível aceder a esta app no seu dispositivo <xliff:g id="DEVICE">%1$s</xliff:g>. Em alternativa, experimente no telemóvel."</string>
<string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Esta app foi criada para uma versão mais antiga do Android. Pode não funcionar corretamente e não inclui as proteções de privacidade e segurança mais recentes. Verifique se existem atualizações ou contacte o programador da app."</string>
- <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Verificar atualizações"</string>
+ <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Rever atualizações"</string>
<string name="new_sms_notification_title" msgid="6528758221319927107">"Tem mensagens novas"</string>
<string name="new_sms_notification_content" msgid="3197949934153460639">"Abra a app de SMS para ver"</string>
<string name="profile_encrypted_title" msgid="9001208667521266472">"Algumas funcionalidades limitadas"</string>
@@ -2299,7 +2301,7 @@
<string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Uma app ainda está ativa"</string>
<string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"A app <xliff:g id="APP">%1$s</xliff:g> está a ser executada em segundo plano Toque para gerir a utilização da bateria."</string>
<string name="notification_content_long_running_fgs" msgid="8258193410039977101">"A app <xliff:g id="APP">%1$s</xliff:g> pode afetar a autonomia da bateria. Toque para rever as apps ativas."</string>
- <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Verificar apps ativas"</string>
+ <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Rever apps ativas"</string>
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Não é possível aceder à câmara do telemóvel a partir do dispositivo <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"Não é possível aceder à câmara do tablet a partir do dispositivo <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
<string name="vdm_secure_window" msgid="161700398158812314">"Não é possível aceder a isto durante o streaming. Em alternativa, experimente no telemóvel."</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 3a391f6bc8fe..896362ad7ae0 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -208,6 +208,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Seus apps pessoais ficarão bloqueados até você ativar o perfil de trabalho"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Os apps pessoais serão bloqueados em <xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>. Seu administrador de TI não permite que o perfil de trabalho fique desativado por mais de <xliff:g id="NUMBER">%3$d</xliff:g> dias."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Ativar"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Ligações e mensagens desativadas"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Você pausou os apps de trabalho. Ligações e mensagens de texto não vão ser recebidas."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Reativar apps de trabalho"</string>
<string name="me" msgid="6207584824693813140">"Eu"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Opções do tablet"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Opções do Android TV"</string>
@@ -339,6 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Pode captar gestos realizados no sensor de impressão digital do dispositivo."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Fazer uma captura de tela"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Pode fazer uma captura de tela."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Visualização, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"desativar ou modificar a barra de status"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Permite que o app desative a barra de status ou adicione e remova ícones do sistema."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"ser a barra de status"</string>
@@ -1359,8 +1363,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"PTP via USB ativado"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Tethering USB ativado"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"MIDI via USB ativado"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Dispositivo conectado como Webcam"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"Acessório USB conectado"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Toque para ver mais opções."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Carregando dispositivo conectado. Toque para ver mais opções."</string>
@@ -1709,8 +1712,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Concluído"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Desativar atalho"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Usar atalho"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Inversão de cores"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Correção de cor"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modo para uma mão"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Escurecer a tela"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 5053850808a6..6c6fc32947c2 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -208,6 +208,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Aplicațiile personale sunt blocate până când activezi profilul de serviciu"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Aplicațiile personale vor fi blocate pe <xliff:g id="DATE">%1$s</xliff:g>, la <xliff:g id="TIME">%2$s</xliff:g>. Administratorul IT nu permite ca profilul de serviciu să fie dezactivat mai mult de <xliff:g id="NUMBER">%3$d</xliff:g> zile."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Activează"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Apelurile și mesajele sunt dezactivate"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Ai întrerupt aplicațiile pentru lucru. Nu vei primi apeluri telefonice sau mesaje text."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Reactivează aplicațiile pentru lucru"</string>
<string name="me" msgid="6207584824693813140">"Eu"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Opțiuni tablet PC"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Opțiuni pentru Android TV"</string>
@@ -339,6 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Poate reda gesturile făcute pe senzorul de amprentă al dispozitivului."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Fă o captură de ecran"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Poate face o captură de ecran."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Previzualizare, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"dezactivare sau modificare bare de stare"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Permite aplicației să dezactiveze bara de stare sau să adauge și să elimine pictograme de sistem."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"să fie bara de stare"</string>
@@ -1359,8 +1363,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"PTP prin USB este activat"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Tetheringul prin USB este activat"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"MIDI prin USB este activat"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Dispozitiv conectat drept cameră web"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"Accesoriu USB conectat"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Atinge pentru mai multe opțiuni."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Se încarcă dispozitivul conectat. Atinge pentru mai multe opțiuni."</string>
@@ -1709,8 +1712,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Gata"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Dezactivează comanda rapidă"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Folosește comanda rapidă"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Inversarea culorilor"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Corecția culorilor"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modul cu o mână"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Luminozitate redusă suplimentar"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 9f5451242434..047d126aaaf7 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -209,6 +209,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Личные приложения будут заблокированы, пока вы не включите рабочий профиль."</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Личные приложения будут заблокированы <xliff:g id="DATE">%1$s</xliff:g> в <xliff:g id="TIME">%2$s</xliff:g>. Системный администратор запретил отключать рабочий профиль более чем на <xliff:g id="NUMBER">%3$d</xliff:g> дн."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Включить"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Звонки и сообщения отключены"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Рабочие приложения приостановлены. Вы не сможете получать вызовы и текстовые сообщения."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Возобновить"</string>
<string name="me" msgid="6207584824693813140">"Я"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Настройки планшетного ПК"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Настройки Android TV"</string>
@@ -340,6 +343,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Использовать сканер отпечатков пальцев для дополнительных жестов."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Создавать скриншоты"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Создавать снимки экрана."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"<xliff:g id="DREAM_NAME">%1$s</xliff:g>: предпросмотр"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"Отключение/изменение строки состояния"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Приложение сможет отключать строку состояния, а также добавлять и удалять системные значки."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"Замена строки состояния"</string>
@@ -1168,8 +1172,8 @@
<string name="no" msgid="5122037903299899715">"Отмена"</string>
<string name="dialog_alert_title" msgid="651856561974090712">"Внимание!"</string>
<string name="loading" msgid="3138021523725055037">"Загрузка…"</string>
- <string name="capital_on" msgid="2770685323900821829">"I"</string>
- <string name="capital_off" msgid="7443704171014626777">"O"</string>
+ <string name="capital_on" msgid="2770685323900821829">"Включено"</string>
+ <string name="capital_off" msgid="7443704171014626777">"Выключено"</string>
<string name="checked" msgid="9179896827054513119">"отмечено"</string>
<string name="not_checked" msgid="7972320087569023342">"не отмечено"</string>
<string name="selected" msgid="6614607926197755875">"выбрано"</string>
@@ -1360,8 +1364,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"Режим PTP включен"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Режим USB-модема включен"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"Режим MIDI включен"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Устройство подключено как веб-камера"</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>
@@ -1710,8 +1713,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Готово"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Деактивировать быстрое включение"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Использовать быстрое включение"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Инверсия цветов"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Коррекция цвета"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Режим управления одной рукой"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Дополнительное уменьшение яркости"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index fe40fef4e634..e58ca7354c87 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"ඔබ ඔබගේ කාර්යාල පැතිකඩ ක්‍රියාත්මක කරන තෙක් ඔබගේ පෞද්ගලික යෙදුම් අවහිර කර ඇත"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"පෞද්ගලික යෙදුම් <xliff:g id="DATE">%1$s</xliff:g> දින <xliff:g id="TIME">%2$s</xliff:g>ට අවහිර වනු ඇත. ඔබේ IT පරිපාලක ඔබේ කාර්යාල පැතිකඩ දින <xliff:g id="NUMBER">%3$d</xliff:g>කට වඩා ඉවත් කර තැබීමට ඉඩ නොදේ."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"ක්‍රියාත්මක කරන්න"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"ඇමතුම් සහ පණිවිඩ ක්‍රියා විරහිතයි"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"ඔබ කාර්යාල යෙදුම් විරාම කර ඇත. ඔබට දුරකථන ඇමතුම් හෝ පෙළ පණිවිඩ නොලැබෙනු ඇත."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"කාර්යාල යෙදුම් විරාමය නොකරන්න"</string>
<string name="me" msgid="6207584824693813140">"මම"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"ටැබ්ලට විකල්ප"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV විකල්ප"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"උපාංගයෙහි ඇඟිලි සලකුණු සංවේදකය මත සිදු කරන ඉංගිත ග්‍රහණය කළ හැකිය."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"තිර රුව ගන්න"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"සංදර්ශකයේ තිර රුවක් ගැනීමට හැකිය."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"පෙරදසුන, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"තත්ව තීරුව අබල කරන්න හෝ වෙනස් කරන්න"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"තත්ව තීරුව අක්‍රිය කිරීමට හෝ පද්ධති නිරූපක එකතු හෝ ඉවත් කිරීමට යෙදුමට අවසර දේ."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"තත්ත්ව තීරුව බවට පත්වීම"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"USB හරහා PTP ක්‍රියාත්මකයි"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"USB ටෙදරින් ක්‍රියාත්මකයි"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"USB හරහා MIDI ක්‍රියාත්මකයි"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"උපාංගය වෙබ් කැමරාව ලෙස සම්බන්ධ කර ඇත"</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>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"නිමයි"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"කෙටිමඟ ක්‍රියාවිරහිත කරන්න"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"කෙටිමඟ භාවිතා කරන්න"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"වර්ණ අපවර්තනය"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"වර්ණ නිවැරදි කිරීම"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"තනි අත් ප්‍රකාරය"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"තවත් අඳුරු"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index e2081119316b..d56b390eada2 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -209,6 +209,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Vaše osobné aplikácie sú zablokované, dokým nezapnete svoj pracovný profil"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Osobné aplikácie budú <xliff:g id="DATE">%1$s</xliff:g> o <xliff:g id="TIME">%2$s</xliff:g> zablokované. Váš správca IT nepovoľuje, aby váš pracovný profil bol vypnutý viac ako <xliff:g id="NUMBER">%3$d</xliff:g> d."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Zapnúť"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Hovory a správy sú vypnuté"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Pozastavili ste pracovné aplikácie. Nebudete môcť prijímať telefonické hovory ani textové správy."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Zrušiť pozastavenie pracovných aplikácií"</string>
<string name="me" msgid="6207584824693813140">"Ja"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Možnosti tabletu"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Možnosti zariadenia Android TV"</string>
@@ -340,6 +343,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Dokáže zaznamenať gestá na senzore odtlačkov prstov zariadenia."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Vytvoriť snímku obrazovky"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Je možné vytvoriť snímku obrazovky."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Ukážka, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"zakázanie alebo zmeny stavového riadka"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Umožňuje aplikácii vypnúť stavový riadok alebo pridať a odstrániť systémové ikony."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"vydávanie sa za stavový riadok"</string>
@@ -1360,8 +1364,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"Bol zapnutý režim PTP cez USB"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Bol zapnutý tethering cez USB"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"Bol zapnutý režim MIDI cez USB"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Zariadenie pripojené ako webkamera"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"Bolo pripojené príslušenstvo USB"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Klepnutím zobrazíte ďalšie možnosti."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Pripojené zariadenie sa nabíja. Ďalšie možností získate klepnutím."</string>
@@ -1710,8 +1713,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Hotovo"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Vypnúť skratku"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Použiť skratku"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Inverzia farieb"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Úprava farieb"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Režim jednej ruky"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Mimoriadne stmavenie"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 67722747d69d..2e582fd2993b 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -209,6 +209,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Osebne aplikacije so blokirane, dokler ne vklopite delovnega profila"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Osebne aplikacije bodo blokirane <xliff:g id="DATE">%1$s</xliff:g> ob <xliff:g id="TIME">%2$s</xliff:g>. Skrbnik za IT ne dovoli, da bi bil delovni profil izklopljen več kot toliko dni: <xliff:g id="NUMBER">%3$d</xliff:g>."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Vklopi"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Klici in sporočila so izklopljeni"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Delovne aplikacije so začasno zaustavljene. Telefonskih klicev in sporočil SMS ne boste prejemali."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Zaženi delovne aplikacije"</string>
<string name="me" msgid="6207584824693813140">"Jaz"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Možnosti tabličnega računalnika"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Možnosti naprave Android TV"</string>
@@ -340,6 +343,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Prepoznava poteze, narejene po tipalu prstnih odtisov naprave."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ustvarjanje posnetka zaslona"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Lahko naredi posnetek zaslona."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Predogled, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"onemogočanje ali spreminjanje vrstice stanja"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Aplikacijam omogoča onemogočenje vrstice stanja ali dodajanje in odstranjevanje ikon sistema."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"postane vrstica stanja"</string>
@@ -1360,8 +1364,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"Vklopljen je način PTP prek USB-ja"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Vklopljen je internet prek USB-ja"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"Vklopljen je način MIDI prek USB-ja"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Naprava je povezana kot spletna kamera"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"Dodatek USB je priključen"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Dotaknite se za več možnosti."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Polnjenje baterije v povezani napravi. Dotaknite se za več možnosti."</string>
@@ -1710,8 +1713,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Končano"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Izklopi bližnjico"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Uporabi bližnjico"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Inverzija barv"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Popravljanje barv"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Enoročni način"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Zelo zatemnjen zaslon"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index e3025d53e9b5..3688c5f48ad1 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Aplikacionet e tua personale janë bllokuar derisa të aktivizosh profilin tënd të punës"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Aplikacionet personale do të bllokohen më <xliff:g id="DATE">%1$s</xliff:g> në <xliff:g id="TIME">%2$s</xliff:g>. Administratori yt i teknologjisë së informacionit nuk lejon që profili yt i punës të qëndrojë joaktiv për më shumë se <xliff:g id="NUMBER">%3$d</xliff:g> ditë."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Aktivizo"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Telefonatat dhe mesazhet janë joaktive"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"I ke vendosur në pauzë aplikacionet e punës. Nuk do të marrësh telefonata ose mesazhe me tekst."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Hiq nga pauza apl. e punës"</string>
<string name="me" msgid="6207584824693813140">"Unë"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Opsionet e tabletit"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Opsionet e Android TV"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Mund të regjistrojë gjestet e kryera në sensorin e gjurmës së gishtit të pajisjes."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Nxirr një pamje të ekranit"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Mund të nxjerrë një pamje e ekranit."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Versioni paraprak, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"çaktivizo ose modifiko shiritin e statusit"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Lejon aplikacionin të çaktivizojë shiritin e statusit dhe të heqë ikonat e sistemit."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"të bëhet shiriti i statusit"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"PTP nëpërmjet USB-së u aktivizua"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Ndarja e internetit përmes USB-së u aktivizua"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"MIDI nëpërmjet USB-së u aktivizua"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Pajisja u lidh si uebkamerë"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"Aksesori i USB-së u lidh"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Trokit për më shumë opsione."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Pajisja e lidhur po karikohet. Trokit për opsione të tjera."</string>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"U krye"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Çaktivizo shkurtoren"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Përdor shkurtoren"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Anasjellja e ngjyrës"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Korrigjimi i ngjyrës"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modaliteti i përdorimit me një dorë"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Shumë më i zbehtë"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 7771805ca7fa..43f17fd94e37 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -208,6 +208,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Личне апликације су блокиране док не укључите пословни профил"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Личне апликације ће бити блокиране: <xliff:g id="DATE">%1$s</xliff:g> у <xliff:g id="TIME">%2$s</xliff:g>. ИТ администратор не дозвољава да пословни профил буде искључен дуже од <xliff:g id="NUMBER">%3$d</xliff:g> дана."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Укључи"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Позиви и поруке су искључени"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Паузирали сте пословне апликације. Нећете добијати телефонске позиве и SMS-ове."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Укључи пословне"</string>
<string name="me" msgid="6207584824693813140">"Ја"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Опције за таблет"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Опције Android TV-а"</string>
@@ -339,6 +342,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Може да региструје покрете на сензору за отисак прста на уређају."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Направи снимак екрана"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Може да направи снимак екрана."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Преглед, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"онемогућавање или измена статусне траке"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Дозвољава апликацији да онемогући статусну траку или да додаје и уклања системске иконе."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"функционисање као статусна трака"</string>
@@ -1359,8 +1363,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"Режим PTP преко USB-а је укључен"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"USB привезивање је укључено"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"Режим MIDI преко USB-а је укључен"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Уређај повезан са веб-камером"</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>
@@ -1709,8 +1712,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Готово"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Искључи пречицу"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Користи пречицу"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Инверзија боја"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Корекција боја"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Режим једном руком"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Додатно затамњено"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index e0130779e2bf..98c5aefcdfb5 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Privata appar blockeras tills du aktiverar jobbprofilen"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Privata appar blockeras den <xliff:g id="DATE">%1$s</xliff:g> kl. <xliff:g id="TIME">%2$s</xliff:g>. IT-administratören tillåter inte att din jobbprofil är inaktiverad i mer än <xliff:g id="NUMBER">%3$d</xliff:g> dagar."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Aktivera"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Samtal och meddelanden är av"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Du har pausat jobbappar. Du får inga telefonsamtal eller sms."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Jobbappar på"</string>
<string name="me" msgid="6207584824693813140">"Jag"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Alternativ för surfplattan"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Alternativ för Android TV"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Kan registrera rörelser som utförs med hjälp av enhetens fingeravtryckssensor."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ta skärmbild"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Kan ta en skärmbild av skärmen."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Förhandsgranskar <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"inaktivera eller ändra statusfält"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Tillåter att appen inaktiverar statusfältet eller lägger till och tar bort systemikoner."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"visas i statusfältet"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"PTP via USB har aktiverats"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Internetdelning via USB har aktiverats"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"MIDI via USB har aktiverats"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Enheten är ansluten som webbkamera"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"USB-tillbehör anslutet"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Tryck för fler alternativ."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Den anslutna enheten laddas. Tryck om du vill ha fler alternativ."</string>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Klar"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Inaktivera kortkommandot"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Använd kortkommandot"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Inverterade färger"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Färgkorrigering"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Enhandsläge"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Extradimmat"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 618d14a52c18..67f6ca2ac08f 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Programu zako za binafsi zimezuiwa hadi uwashe wasifu wako wa kazini"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Programu za binafsi zitazuiwa tarehe <xliff:g id="DATE">%1$s</xliff:g> saa <xliff:g id="TIME">%2$s</xliff:g>. Msimamizi wako wa TEHAMA haruhusu wasifu wako wa kazini kuzimwa kwa zaidi ya siku <xliff:g id="NUMBER">%3$d</xliff:g>."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Washa"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Ujumbe na simu zimezimwa"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Umesitisha programu za kazini. Hutapokea simu au ujumbe wa maandishi."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Acha kusitisha programu za kazini"</string>
<string name="me" msgid="6207584824693813140">"Mimi"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Chaguo za kompyuta ndogo"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Chaguo za Android TV"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Inaweza kurekodi ishara zinazotekelezwa kwenye kitambua alama ya kidole."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Piga picha ya skrini"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Inaweza kupiga picha ya skrini ya onyesho."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Onyesho la kukagua, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"zima au rekebisha mwambaa hali"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Inaruhusu programu kulemaza upau wa hali au kuongeza na kutoa aikoni za mfumo."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"kuwa sehemu ya arifa"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"Umewasha hali ya PTP kupitia USB"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Umewasha hali ya kusambaza mtandao ukitumia USB"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"Umewasha hali ya MIDI kupitia USB"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Kifaa kimeunganishwa kikiwa Kamera ya wavuti"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"Imeunganisha kifuasi cha USB"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Gusa ili upate chaguo zaidi."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Inachaji kifaa kilichounganishwa. Gusa ili upate chaguo zaidi."</string>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Nimemaliza"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Zima kipengele cha Njia ya Mkato"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Tumia Njia ya Mkato"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Ugeuzaji rangi"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Usahihishaji wa rangi"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Hali ya kutumia kwa mkono mmoja"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Kipunguza mwangaza zaidi"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index ff656b440cff..ddf1393ea4e4 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"பணிக் கணக்கை ஆன் செய்யும் வரை உங்கள் தனிப்பட்ட ஆப்ஸ் தடுக்கப்பட்டிருக்கும்"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"<xliff:g id="DATE">%1$s</xliff:g> அன்று <xliff:g id="TIME">%2$s</xliff:g> நேரத்தில் தனிப்பட்ட ஆப்ஸ் தடுக்கப்படும். பணிக் கணக்கை <xliff:g id="NUMBER">%3$d</xliff:g> நாட்களுக்கு மேல் ஆஃப் செய்து வைத்திருப்பதை உங்கள் IT நிர்வாகி அனுமதிக்கவில்லை."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"ஆன் செய்"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"அழைப்புகளும் மெசேஜ்களும் முடக்கப்பட்டன"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"பணி ஆப்ஸை இடைநிறுத்தியுள்ளீர்கள். மொபைல் அழைப்புகளையோ மெசேஜ்களையோ பெறமாட்டீர்கள்."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"பணி ஆப்ஸை இயக்கு"</string>
<string name="me" msgid="6207584824693813140">"நான்"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"டேப்லெட் விருப்பங்கள்"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV விருப்பத்தேர்வுகள்"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"சாதனத்தின் கைரேகை சென்சார்மேல் செய்யப்படும் சைகைகளைக் கேப்ட்சர் செய்ய முடியும்."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ஸ்கிரீன்ஷாட்டை எடுக்கும்"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"டிஸ்ப்ளேவை ஸ்கிரீன்ஷாட் எடுக்க முடியும்."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"மாதிரிக்காட்சி, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"நிலைப் பட்டியை முடக்குதல் அல்லது மாற்றுதல்"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"நிலைப் பட்டியை முடக்க அல்லது முறைமையில் ஐகான்களைச் சேர்க்க மற்றும் அகற்ற ஆப்ஸை அனுமதிக்கிறது."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"நிலைப் பட்டியில் இருக்கும்"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"USB மூலமாக PTP பயன்முறை ஆன் செய்யப்பட்டது"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"USB இணைப்பு முறை ஆன் செய்யப்பட்டது"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"USB மூலமாக MIDI பயன்முறை ஆன் செய்யப்பட்டது"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"சாதனம் வெப்கேமாக இணைக்கப்பட்டுள்ளது"</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>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"முடிந்தது"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"ஷார்ட்கட்டை முடக்கு"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ஷார்ட்கட்டைப் பயன்படுத்து"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"கலர் இன்வெர்ஷன்"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"கலர் கரெக்‌ஷன்"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"ஒற்றைக் கைப் பயன்முறை"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"மிகக் குறைவான வெளிச்சம்"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 46ab23c25b2f..33f5d24d2fa1 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"మీరు మీ కార్యాలయ ప్రొఫైల్‌ను ప్రారంభించే వరకు, మీ వ్యక్తిగత యాప్‌లు బ్లాక్ చేయబడతాయి"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"<xliff:g id="DATE">%1$s</xliff:g> తేదీన <xliff:g id="TIME">%2$s</xliff:g>కు వ్యక్తిగత యాప్‌లు బ్లాక్ చేయబడతాయి. <xliff:g id="NUMBER">%3$d</xliff:g> రోజులకు మించి మీ కార్యాలయ ప్రొఫైల్‌ను ఆఫ్‌లో ఉంచటానికి మీ IT అడ్మిన్ అనుమతించరు."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"ఆన్ చేయి"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"కాల్స్, మెసేజ్‌లు ఆఫ్ చేయబడ్డాయి"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"మీరు వర్క్ యాప్‌లను పాజ్ చేశారు. మీరు ఫోన్ కాల్‌లు లేదా టెక్స్ట్ మెసేజ్‌లను అందుకోరు."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"వర్క్ యాప్‌ల పాజ్‌ను తీసివేయండి"</string>
<string name="me" msgid="6207584824693813140">"నేను"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"టాబ్లెట్ ఎంపికలు"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV ఎంపికలు"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"పరికర వేలిముద్ర సెన్సార్‌లో ఉపయోగించిన సంజ్ఞలను క్యాప్చర్ చేయవచ్చు."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"స్క్రీన్‌షాట్‌ను తీయండి"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"డిస్‌ప్లే యొక్క స్క్రీన్‌షాట్ తీసుకోవచ్చు."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"ప్రివ్యూ, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"స్టేటస్‌ బార్‌ను డిజేబుల్ చేయడం లేదా మార్చడం"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"స్టేటస్‌ బార్‌ను డిజేబుల్ చేయడానికి లేదా సిస్టమ్ చిహ్నాలను జోడించడానికి మరియు తీసివేయడానికి యాప్‌ను అనుమతిస్తుంది."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"స్టేటస్‌ పట్టీగా ఉండటం"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"USB ద్వారా PTP ఆన్ చేయబడింది"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"USB టెథెరింగ్ ఆన్ చేయబడింది"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"USB ద్వారా MIDI ఆన్ చేయబడింది"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"పరికరం వెబ్‌క్యామ్‌గా కనెక్ట్ చేయబడింది"</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>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"పూర్తయింది"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"షార్ట్‌కట్‌ను ఆఫ్ చేయి"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"షార్ట్‌కట్‌ను ఉపయోగించండి"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"కలర్ మార్పిడి"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"కలర్ కరెక్షన్"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"వన్-హ్యాండెడ్ మోడ్"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ఎక్స్‌ట్రా డిమ్"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 39dd58e23a4b..8032880fbddb 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"แอปส่วนตัวจะถูกบล็อกไว้จนกว่าคุณจะเปิดโปรไฟล์งาน"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"แอปส่วนตัวจะถูกบล็อกในวันที่ <xliff:g id="DATE">%1$s</xliff:g> เวลา <xliff:g id="TIME">%2$s</xliff:g> ผู้ดูแลระบบไอทีไม่อนุญาตให้หยุดใช้โปรไฟล์งานเกิน <xliff:g id="NUMBER">%3$d</xliff:g> วัน"</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"เปิด"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"การโทรและข้อความปิดอยู่"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"คุณหยุดแอปงานไว้ชั่วคราว และจะไม่ได้รับสายโทรเข้ารวมถึง SMS"</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"เลิกหยุดแอปงาน"</string>
<string name="me" msgid="6207584824693813140">"ฉัน"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"ตัวเลือกของแท็บเล็ต"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"ตัวเลือกของ Android TV"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"สามารถจับท่าทางสัมผัสที่เกิดขึ้นบนเซ็นเซอร์ลายนิ้วมือของอุปกรณ์"</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"ถ่ายภาพหน้าจอ"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ถ่ายภาพหน้าจอได้"</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"ตัวอย่าง <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"ปิดการใช้งานหรือแก้ไขแถบสถานะ"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"อนุญาตให้แอปพลิเคชันปิดใช้งานแถบสถานะหรือเพิ่มและนำไอคอนระบบออก"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"เป็นแถบสถานะ"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"เปิดโหมด PTP ผ่าน USB"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"เปิดการเชื่อมต่ออินเทอร์เน็ตผ่าน USB"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"เปิดโหมด MIDI ผ่าน USB"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"เชื่อมต่ออุปกรณ์เป็นเว็บแคมแล้ว"</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>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"เสร็จ"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"ปิดทางลัด"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ใช้ทางลัด"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"การกลับสี"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"การแก้สี"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"โหมดมือเดียว"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"หรี่แสงเพิ่มเติม"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index e5b03e04658b..d1383df771ba 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Naka-block ang iyong mga personal na app hangga\'t hindi mo ino-on ang profile sa trabaho mo"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Iba-block ang mga personal na app sa <xliff:g id="DATE">%1$s</xliff:g> nang <xliff:g id="TIME">%2$s</xliff:g>. Hindi pinapayagan ng iyong IT admin na manatiling naka-off ang profile mo sa trabaho nang mahigit <xliff:g id="NUMBER">%3$d</xliff:g> (na) araw."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"I-on"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Naka-off ang mga tawag at mensahe"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Na-pause mo ang mga app para sa trabaho. Hindi ka makakatanggap ng mga tawag sa telepono o text message."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"I-unpause ang app para sa trabaho"</string>
<string name="me" msgid="6207584824693813140">"Ako"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Mga pagpipilian sa tablet"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Mga opsyon sa Android TV"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Makukunan ang mga galaw na ginawa sa sensor para sa fingerprint ng device."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Kumuha ng screenshot"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Puwedeng kumuha ng screenshot ng display."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Preview, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"i-disable o baguhin ang status bar"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Pinapayagan ang app na i-disable ang status bar o magdagdag at mag-alis ng mga icon ng system."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"maging status bar"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"Na-on ang PTP sa pamamagitan ng USB"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Na-on ang pag-tether ng USB"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"Na-on ang MIDI sa pamamagitan ng USB"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Nakakonekta ang device bilang Webcam"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"Nakakonekta ang USB accessory"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"I-tap para sa higit pang mga opsyon."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"China-charge ang nakakonektang device. Mag-tap para sa higit pang opsyon."</string>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Tapos na"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"I-off ang Shortcut"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Gamitin ang Shortcut"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Pag-invert ng kulay"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Pagtatama ng kulay"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"One-Hand mode"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Extra dim"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 78dac1d5cc94..2e7b3c76b1b8 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"İş profilinizi açana kadar kişisel uygulamalarınız engelleniyor"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Kişisel uygulamalar <xliff:g id="DATE">%1$s</xliff:g> tarihinde saat <xliff:g id="TIME">%2$s</xliff:g> itibarıyla engellenecektir. BT yöneticiniz, iş profilinizin <xliff:g id="NUMBER">%3$d</xliff:g> günden fazla kapalı kalmasına izin vermiyor."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Aç"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Aramalar ve mesajlar devre dışı"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"İş uygulamalarını duraklattınız. Telefon aramaları veya kısa mesajlar almayacaksınız."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"İş uygulamalarını devam ettir"</string>
<string name="me" msgid="6207584824693813140">"Ben"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Tablet seçenekleri"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV seçenekleri"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Cihazın parmak izi sensörlerinde gerçekleştirilen hareketleri yakalayabilir."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Ekran görüntüsü al"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Ekran görüntüsü alınabilir."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Önizleme, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"durum çubuğunu devre dışı bırak veya değiştir"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Uygulamaya, durum çubuğunu devre dışı bırakma ve sistem simgelerini ekleyip kaldırma izni verir."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"durum çubuğunda olma"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"USB üzerinden PTP açık"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"USB tethering açık"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"USB üzerinden MIDI açık"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Cihaz, web kamerası olarak bağlandı"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"USB aksesuarı bağlandı"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Diğer seçenekler için dokunun."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Bağlı cihaz şarj ediliyor. Diğer seçenekler için dokunun."</string>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Bitti"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Kısayolu Kapat"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Kısayolu Kullan"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Rengi ters çevirme"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Renk düzeltme"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Tek El modu"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Ekstra loş"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index bae09340f657..5ce099c8e0d1 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -209,6 +209,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Особисті додатки заблоковано, доки ви не ввімкнете робочий профіль"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Особисті додатки буде заблоковано <xliff:g id="DATE">%1$s</xliff:g> о <xliff:g id="TIME">%2$s</xliff:g>. Ваш ІТ-адміністратор не дозволяє, щоб робочий профіль був неактивний більше ніж <xliff:g id="NUMBER">%3$d</xliff:g> дн."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Увімкнути"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Дзвінки та повідомлення вимкнено"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Ви призупинили робочі додатки. Телефонні дзвінки й текстові повідомлення не надходитимуть."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Увімкнути робочі додатки"</string>
<string name="me" msgid="6207584824693813140">"Я"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Парам. пристрою"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Опції Android TV"</string>
@@ -340,6 +343,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Може фіксувати жести на сканері відбитків пальців."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Робити знімки екрана"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Може робити знімки екрана."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"<xliff:g id="DREAM_NAME">%1$s</xliff:g> (попередній перегляд)"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"вимикати чи змін. рядок стану"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Дозволяє програмі вимикати рядок стану чи додавати та видаляти піктограми системи."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"відображатися як рядок стану"</string>
@@ -1360,8 +1364,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"Режим PTP через USB ввімкнено"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Режим USB-модема ввімкнено"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"Режим MIDI через USB ввімкнено"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Пристрій підключено як веб-камеру"</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>
@@ -1710,8 +1713,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Готово"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Вимкнути ярлик"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Використовувати ярлик"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Інверсія кольорів"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Корекція кольору"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Режим керування однією рукою"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Додаткове зменшення яскравості"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 62f1c2b99cef..101cec076ec9 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"آپ کے ذاتی ایپس کو اس وقت تک بلاک کر دیا جاتا ہے جب تک کہ آپ اپنے ورک پروفایل کو آن نہیں کرتے"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"‏‫<xliff:g id="DATE">%1$s</xliff:g> کو <xliff:g id="TIME">%2$s</xliff:g> بجے ذاتی ایپس کو مسدود کر دیا جائے گا۔ آپ کا IT منتظم آپ کی دفتری پروفائل کو <xliff:g id="NUMBER">%3$d</xliff:g> دن سے زیادہ بند رکھنے کی اجازت نہیں دیتا ہے۔"</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"آن کریں"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"کالز اور پیغامات آف ہیں"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"آپ نے ورک ایپس کو موقوف کر دیا ہے۔ آپ کو فون کالز یا ٹیکسٹ پیغامات موصول نہیں ہوں گے۔"</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"ورک ایپس کو غیر موقوف کریں"</string>
<string name="me" msgid="6207584824693813140">"میں"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"ٹیبلیٹ کے اختیارات"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"‏Android TV اختیارات"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"آلہ کے فنگر پرنٹ سینسر پر کیے گئے اشاروں کو کیپچر کر سکتا ہے۔"</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"اسکرین شاٹ لیں"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"ڈسپلے کا اسکرین شاٹ لیا جا سکتا ہے۔"</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"پیش منظر، <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"اسٹیٹس بار کو غیر فعال یا اس میں ترمیم کریں"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"ایپ کو اسٹیٹس بار غیر فعال کرنے یا سسٹم آئیکنز شامل کرنے اور ہٹانے کی اجازت دیتا ہے۔"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"بطور اسٹیٹس بار کام لیں"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"‏USB کے ذریعے PTP آن ہے"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"‏USB ٹیدرنگ آن ہے"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"‏USB کے ذریعے MIDI آن ہے"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"آلہ ویب کیم کے بطور منسلک ہے"</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>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"ہو گیا"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"شارٹ کٹ آف کریں"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"شارٹ کٹ استعمال کریں"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"رنگوں کی تقلیب"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"رنگ کی اصلاح"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"ایک ہاتھ کی وضع"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"اضافی مدھم"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 055a3b5a94c0..1c08daa33e40 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Ish profilingiz yoniqligida shaxsiy ilovalaringiz bloklanadi"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Shaxsiy ilovalar <xliff:g id="DATE">%1$s</xliff:g> <xliff:g id="TIME">%2$s</xliff:g> da bloklanadi. AT administratoringiz ish profili <xliff:g id="NUMBER">%3$d</xliff:g> kundan ortiq oʻchiq qolishini taqiqlagan"</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Yoqish"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Chaqiruv va xabarlar yoniq emas"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Ayrim ishga oid ilovalar pauza qilingan. Telefon chaqiruvlari yoki SMS xabarlar kelmay turadi."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Ishga oid ilovalarni qaytarish"</string>
<string name="me" msgid="6207584824693813140">"Men"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Planshet sozlamalari"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV parametrlari"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Barmoq izi skanerida kiritilgan ishoralarni taniy oladi."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Skrinshot olish"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Ekrandan skrinshot olishi mumkin."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Razm solish, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"holat panelini o‘zgartirish yoki o‘chirish"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Ilova holat panelini o‘chirib qo‘yishi hamda tizim ikonkalarini qo‘shishi yoki olib tashlashi mumkin."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"holat qatorida ko‘rinishi"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"USB orqali PTP rejimi yoqildi"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"USB modem rejimi yoqildi"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"USB orqali MIDI rejimi yoqildi"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Qurilma veb-kamera sifatida ulangan"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"USB qurilma ulandi"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Boshqa parametrlarini ko‘rish uchun bosing."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Ulangan qurilma quvvatlanmoqda. Boshqa parametrlar uchun bosing."</string>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"OK"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Tezkor ishga tushirishni o‘chirib qo‘yish"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Tezkor ishga tushirishdan foydalanish"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Ranglarni akslantirish"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Ranglarni tuzatish"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Ixcham rejim"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Juda xira"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index cd7a7fa1a5f3..6a863a1ba3ee 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Ứng dụng cá nhân của bạn bị chặn cho tới khi bạn bật hồ sơ công việc"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Ứng dụng cá nhân sẽ bị chặn lúc <xliff:g id="TIME">%2$s</xliff:g> vào <xliff:g id="DATE">%1$s</xliff:g>. Quản trị viên CNTT không cho phép bạn tắt hồ sơ công việc quá <xliff:g id="NUMBER">%3$d</xliff:g> ngày."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Bật"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Ngưng nhận cuộc gọi và tin nhắn"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Bạn đã tạm dừng các ứng dụng công việc. Bạn sẽ không nhận được cuộc gọi hoặc tin nhắn văn bản nào."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Dùng ứng dụng công việc"</string>
<string name="me" msgid="6207584824693813140">"Tôi"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Tùy chọn máy tính bảng"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Tùy chọn dành cho Android TV"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Có thể ghi lại các cử chỉ được thực hiện trên cảm biến vân tay của thiết bị."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Chụp ảnh màn hình"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Có thể chụp ảnh màn hình."</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Bản xem trước, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"vô hiệu hóa hoặc sửa đổi thanh trạng thái"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Cho phép ứng dụng vô hiệu hóa thanh trạng thái hoặc thêm và xóa biểu tượng hệ thống."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"trở thành thanh trạng thái"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"Đã bật chế độ PTP qua USB"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Đã bật tính năng chia sẻ Internet qua USB"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"Đã bật chế độ MIDI qua USB"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Đã kết nối thiết bị dưới dạng webcam"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"Đã kết nối phụ kiện USB"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Nhấn để biết thêm tùy chọn."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Đang sạc thiết bị được kết nối. Hãy nhấn để biết thêm các tùy chọn."</string>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Xong"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Tắt phím tắt"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Sử dụng phím tắt"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Đảo màu"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Chỉnh màu"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Chế độ một tay"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Siêu tối"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 238d54c56124..1f0e170eb218 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"系统已屏蔽您的个人应用。您需要开启工作资料,系统才会取消屏蔽这些应用"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"系统将于 <xliff:g id="DATE">%1$s</xliff:g><xliff:g id="TIME">%2$s</xliff:g> 屏蔽个人应用。IT 管理员不允许您的工作资料保持关闭状态超过 <xliff:g id="NUMBER">%3$d</xliff:g> 天。"</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"开启"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"通话和短信已关闭"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"您已暂停工作应用。您将不会收到来电或短信。"</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"恢复工作应用"</string>
<string name="me" msgid="6207584824693813140">"我"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"平板电脑选项"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV 选项"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"可以捕捉在设备指纹传感器上执行的手势。"</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"截取屏幕截图"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"可截取显示画面的屏幕截图。"</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"预览,<xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"停用或修改状态栏"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"允许应用停用状态栏或者增删系统图标。"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"用作状态栏"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"已开启 USB PTP 模式"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"已开启 USB 网络共享模式"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"已开启 USB MIDI 模式"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"设备已连接为摄像头"</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>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"完成"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"关闭快捷方式"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"使用快捷方式"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"颜色反转"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"色彩校正"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"单手模式"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"极暗"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index ca494338d77d..4f6d8e220b4d 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"系統會封鎖您的個人應用程式,直至您開啟工作設定檔為止"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"個人應用程式將於 <xliff:g id="DATE">%1$s</xliff:g> <xliff:g id="TIME">%2$s</xliff:g> 封鎖。IT 管理員不允許您的工作設定檔保持關閉狀態超過 <xliff:g id="NUMBER">%3$d</xliff:g> 天。"</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"開啟"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"通話和訊息功能已關閉"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"您已暫停工作應用程式,因此無法接聽電話或接收訊息。"</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"取消暫停工作應用程式"</string>
<string name="me" msgid="6207584824693813140">"我本人"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"平板電腦選項"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV 選項"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"可以擷取在裝置指紋感應器上執行的手勢。"</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"擷取螢幕擷圖"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"可以擷取螢幕截圖。"</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"預覽,<xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"停用或修改狀態列"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"允許應用程式停用狀態列,並可新增或移除系統圖示。"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"成為狀態列"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"已開啟 USB PTP 模式"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"已開啟 USB 的網絡共享模式"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"已開啟 USB MIDI 模式"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"已連接裝置用作網絡攝影機"</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>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"完成"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"關閉快速鍵"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"使用快速鍵"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"色彩反轉"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"色彩校正"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"單手模式"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"超暗"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index f282ba33ea31..7896196b142f 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"系統已封鎖你的個人應用程式;你必須開啟工作資料夾,這些應用程式才會解除封鎖"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"系統將於 <xliff:g id="DATE">%1$s</xliff:g><xliff:g id="TIME">%2$s</xliff:g> 封鎖個人應用程式。IT 管理員不允許工作資料夾關閉超過 <xliff:g id="NUMBER">%3$d</xliff:g> 天。"</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"開啟"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"通話與訊息功能已關閉"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"你已暫停工作應用程式,因此將無法接聽電話或接收訊息。"</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"取消暫停工作應用程式"</string>
<string name="me" msgid="6207584824693813140">"我"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"平板電腦選項"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV 選項"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"可以擷取使用者對裝置的指紋感應器執行的手勢。"</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"擷取螢幕畫面"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"可以擷取螢幕畫面。"</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"預覽,<xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"停用或變更狀態列"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"允許應用程式停用狀態列,並可新增或移除系統圖示。"</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"以狀態列顯示"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"已開啟 USB PTP 模式"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"已開啟 USB 網路共用模式"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"已開啟 USB MIDI 模式"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"接上的裝置已做為網路攝影機使用"</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>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"完成"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"停用捷徑"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"使用捷徑"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"色彩反轉"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"色彩校正"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"單手模式"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"超暗"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 72180d459faa..1fcbbe2c0b7a 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -207,6 +207,9 @@
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Izinhlelo zakho zokusebenza zomuntu siqu zivinjelwe kuze kube yilapho uvula iphrofayela yakho yomsebenzi"</string>
<string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Izinhlelo zokusebenza zomuntu siqu zizovinjelwa ngomhla ka-<xliff:g id="DATE">%1$s</xliff:g> ngo-<xliff:g id="TIME">%2$s</xliff:g>. Umphathi wakho we-IT akavumeli ukuthi iphrofayela yakho yomsebenzi ihlale ivaliwe izinsuku ezingaphezu kwezi-<xliff:g id="NUMBER">%3$d</xliff:g>."</string>
<string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Vula"</string>
+ <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Amakholi nemiyalezo kuvaliwe"</string>
+ <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Umise ama-app omsebenzi. Ngeke uthole amakholi wefoni noma imiyalezo yombhalo."</string>
+ <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Susa ukumisa ama-app omsebenzi"</string>
<string name="me" msgid="6207584824693813140">"Mina"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Okukhethwa kukho kwethebhulethi"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Izinketho ze-Android TV"</string>
@@ -338,6 +341,7 @@
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Ingathatha ukuthinta okwenziwe kunzwa yezigxivizo zeminwe zedivayisi."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Thatha isithombe-skrini"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Ingathatha isithombe-skrini sesiboniso"</string>
+ <string name="dream_preview_title" msgid="5570751491996100804">"Hlola kuqala, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"khubaza noma guqula ibha yomumo"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Ivumela uhlelo lokusebenza ukuthi yenze umudwa ochaza ngesimo ukuthi ungasebenzi noma ukufaka noma ukukhipha izithonjana zohlelo."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"yiba yibha yesimo"</string>
@@ -1358,8 +1362,7 @@
<string name="usb_ptp_notification_title" msgid="5043437571863443281">"I-PTP nge-USB ivuliwe"</string>
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Kuvulwe ukusebenzisa ifoni njengemodemu kwe-USB"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"I-MIDI nge-USB ivuliwe"</string>
- <!-- no translation found for usb_uvc_notification_title (2030032862673400008) -->
- <skip />
+ <string name="usb_uvc_notification_title" msgid="2030032862673400008">"Idivayisi ixhunywe njengekhamera yewebhu"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"Insiza ye-USB ixhunyiwe"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"Thepha ngezinketho eziningi."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Ishaja idivayisi exhunyiwe. Thepha ukuze uthole okunye okungakhethwa."</string>
@@ -1708,8 +1711,7 @@
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Kwenziwe"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Vala isinqamuleli"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Sebenzisa isinqamuleli"</string>
- <!-- no translation found for color_inversion_feature_name (2672824491933264951) -->
- <skip />
+ <string name="color_inversion_feature_name" msgid="2672824491933264951">"Ukuguqulwa kombala"</string>
<string name="color_correction_feature_name" msgid="7975133554160979214">"Ukulungiswa kombala"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Imodi yesandla esisodwa"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Ukufiphaza okwengeziwe"</string>
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index 4468ebe90ba0..b35481d3c31b 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -227,4 +227,10 @@
<string-array name="device_state_notification_thermal_contents">
<item>@string/concurrent_display_notification_thermal_content</item>
</string-array>
+
+ <!-- Certificate digests for trusted apps that will be allowed to obtain the knownSigner of the
+ demo device provisioning permissions. -->
+ <string-array name="demo_device_provisioning_known_signers">
+ <item>@string/config_retailDemoPackageSignature</item>
+ </string-array>
</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 9252b149797b..2a67b44d6416 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3201,8 +3201,8 @@
<!-- Describes whether this view should allow interactions from AccessibilityServices only
if the service sets the isAccessibilityTool property. -->
- <attr name="accessibilityDataPrivate" format="integer">
- <!-- The system determines whether the view's accessibility data is private
+ <attr name="accessibilityDataSensitive" format="integer">
+ <!-- The system determines whether the view's accessibility data is sensitive
- default (recommended). -->
<enum name="auto" value="0" />
<!-- Allow interactions from AccessibilityServices only if the service sets the
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index d2ee5dea2bb0..1bbe8eeaf37f 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1714,7 +1714,7 @@
this type.
-->
<flag name="remoteMessaging" value="0x200" />
- <!-- The system exmpted foreground service use cases.
+ <!-- The system exempted foreground service use cases.
<p>Requires the app to hold the permission
{@link android.Manifest.permission#FOREGROUND_SERVICE_SYSTEM_EXEMPTED} in order to use
this type. Apps are allowed to use this type only in the use cases listed in
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 12eff6723d88..ffb602d93b0f 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1158,14 +1158,25 @@
<integer name="config_triplePressOnStemPrimaryBehavior">0</integer>
<!-- Control the behavior when the user short presses the stem primary button.
- Stem primary button is only used on watch form factor. If a device is not
- a watch, setting this config is no-op.
- 0 - Nothing
- 1 - Go to launch all apps
+ Stem primary button is only used on watch form factor. If a device is not
+ a watch, setting this config is no-op.
+ 0 - Nothing
+ 1 - Go to launch all apps
-->
<integer name="config_shortPressOnStemPrimaryBehavior">0</integer>
+ <!-- Control the behavior of the search key.
+ 0 - Launch default search activity
+ 1 - Launch target activity defined by config_searchKeyTargetActivity
+ -->
+ <integer name="config_searchKeyBehavior">0</integer>
+
+ <!-- Component name for the default target activity to be launched when user
+ presses the global search key. [DO NOT TRANSLATE]
+ -->
+ <string name="config_searchKeyTargetActivity" translatable="false"></string>
+
<!-- Time to wait while a button is pressed before triggering a very long press. -->
<integer name="config_veryLongPressTimeout">3500</integer>
@@ -1304,6 +1315,13 @@
<!-- Default LED off time for notification LED in milliseconds. -->
<integer name="config_defaultNotificationLedOff">2000</integer>
+ <!-- LED behavior when battery is low.
+ Color for solid is taken from config_notificationsBatteryLowARGB
+ 0 - default, solid when charging, flashing when not charging
+ 1 - always solid when battery is low
+ 2 - always flashing when battery is low -->
+ <integer name="config_notificationsBatteryLowBehavior">0</integer>
+
<!-- Default value for led color when battery is low on charge -->
<integer name="config_notificationsBatteryLowARGB">0xFFFF0000</integer>
@@ -2780,8 +2798,10 @@
<integer name="config_userTypePackageWhitelistMode">13</integer> <!-- 1+4+8 -->
<!-- Whether the main user is a permanent admin user. If the main user is a permanent admin user
- it can't be deleted or downgraded to non-admin status. -->
- <bool name="config_isMainUserPermanentAdmin">false</bool>
+ it can't be deleted or downgraded to non-admin status.
+ This is generally only relevant on headless system user mode devices; on other devices, the
+ main user is the system user which is always a permanent admin anyway. -->
+ <bool name="config_isMainUserPermanentAdmin">true</bool>
<!-- Whether switch to headless system user is allowed. If allowed,
headless system user can run in the foreground even though it is not a full user. -->
@@ -3065,6 +3085,10 @@
<string name="config_credentialManagerDialogComponent" translatable="false"
>com.android.credentialmanager/com.android.credentialmanager.CredentialSelectorActivity</string>
+ <!-- Name of the broadcast receiver that is used to receive provider change events -->
+ <string name="config_credentialManagerReceiverComponent" translatable="false"
+ >com.android.credentialmanager/com.android.credentialmanager.CredentialProviderReceiver</string>
+
<!-- Apps that are authorized to access shared accounts, overridden by product overlays -->
<string name="config_appsAuthorizedForSharedAccounts" translatable="false">;com.android.settings;</string>
@@ -3964,7 +3988,7 @@
<!-- Whether the device supports non-resizable activity in multi windowing modes.
-1: The device doesn't support non-resizable in multi windowing modes.
0: The device supports non-resizable in multi windowing modes only if this is a large
- screen (smallest width >= {@link config_largeScreenSmallestScreenWidthDp}).
+ screen (smallest width >= {@link WindowManager#LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP}).
1: The device always supports non-resizable in multi windowing modes.
-->
<integer name="config_supportsNonResizableMultiWindow">0</integer>
@@ -3974,9 +3998,9 @@
-1: The device ignores the activity min width/height when determining if it can be shown in
multi windowing modes.
0: If this is a small screen (smallest width <
- {@link config_largeScreenSmallestScreenWidthDp}), the device compares the activity min
- width/height with the min multi windowing modes dimensions the device supports to
- determine if the activity can be shown in multi windowing modes
+ {@link WindowManager#LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP}), the device compares the
+ activity min width/height with the min multi windowing modes dimensions the device
+ supports to determine if the activity can be shown in multi windowing modes
1: The device always compare the activity min width/height with the min multi windowing
modes dimensions {@link config_minPercentageMultiWindowSupportWidth} the device
supports to determine if the activity can be shown in multi windowing modes.
@@ -3999,11 +4023,6 @@
-->
<item name="config_minPercentageMultiWindowSupportWidth" format="float" type="dimen">0.5</item>
- <!-- If the display smallest screen width is greater or equal to this value, we will treat it
- as a large screen device, which will have some multi window features enabled by default.
- -->
- <integer name="config_largeScreenSmallestScreenWidthDp">600</integer>
-
<!-- True if the device is using legacy split. -->
<bool name="config_useLegacySplit">false</bool>
diff --git a/core/res/res/values/config_telephony.xml b/core/res/res/values/config_telephony.xml
index 24a7d8588d35..ebda172061d3 100644
--- a/core/res/res/values/config_telephony.xml
+++ b/core/res/res/values/config_telephony.xml
@@ -110,6 +110,10 @@
<string name="config_satellite_service_package" translatable="false"></string>
<java-symbol type="string" name="config_satellite_service_package" />
+ <!-- Telephony pointing UI package name to be launched. -->
+ <string name="config_pointing_ui_package" translatable="false"></string>
+ <java-symbol type="string" name="config_pointing_ui_package" />
+
<!-- Whether enhanced IWLAN handover check is enabled. If enabled, telephony frameworks
will not perform handover if the target transport is out of service, or VoPS not
supported. The network will be torn down on the source transport, and will be
@@ -119,7 +123,7 @@
<java-symbol type="bool" name="config_enhanced_iwlan_handover_check" />
<!-- Whether using the new SubscriptionManagerService or the old SubscriptionController -->
- <bool name="config_using_subscription_manager_service">false</bool>
+ <bool name="config_using_subscription_manager_service">true</bool>
<java-symbol type="bool" name="config_using_subscription_manager_service" />
<!-- Whether asynchronously update the subscription database or not. Async mode increases
diff --git a/core/res/res/values/public-staging.xml b/core/res/res/values/public-staging.xml
index ee021001a54a..69d5feff2de9 100644
--- a/core/res/res/values/public-staging.xml
+++ b/core/res/res/values/public-staging.xml
@@ -114,7 +114,7 @@
<public name="handwritingBoundsOffsetTop" />
<public name="handwritingBoundsOffsetRight" />
<public name="handwritingBoundsOffsetBottom" />
- <public name="accessibilityDataPrivate" />
+ <public name="accessibilityDataSensitive" />
<public name="enableTextStylingShortcuts" />
<public name="requiredDisplayCategory"/>
<public name="removed_maxConcurrentSessionsCount" />
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 7e89fc8b5e46..92dc5694ff2c 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -405,7 +405,6 @@
<java-symbol type="integer" name="config_respectsActivityMinWidthHeightMultiWindow" />
<java-symbol type="dimen" name="config_minPercentageMultiWindowSupportHeight" />
<java-symbol type="dimen" name="config_minPercentageMultiWindowSupportWidth" />
- <java-symbol type="integer" name="config_largeScreenSmallestScreenWidthDp" />
<java-symbol type="bool" name="config_useLegacySplit" />
<java-symbol type="bool" name="config_noHomeScreen" />
<java-symbol type="bool" name="config_supportsSystemDecorsOnSecondaryDisplays" />
@@ -464,6 +463,8 @@
<java-symbol type="integer" name="config_doublePressOnStemPrimaryBehavior" />
<java-symbol type="integer" name="config_triplePressOnStemPrimaryBehavior" />
<java-symbol type="string" name="config_doublePressOnPowerTargetActivity" />
+ <java-symbol type="integer" name="config_searchKeyBehavior" />
+ <java-symbol type="string" name="config_searchKeyTargetActivity" />
<java-symbol type="integer" name="config_windowOutsetBottom" />
<java-symbol type="integer" name="db_connection_pool_size" />
<java-symbol type="integer" name="db_journal_size_limit" />
@@ -2004,6 +2005,7 @@
<java-symbol type="integer" name="config_notificationsBatteryFullARGB" />
<java-symbol type="integer" name="config_notificationsBatteryLedOff" />
<java-symbol type="integer" name="config_notificationsBatteryLedOn" />
+ <java-symbol type="integer" name="config_notificationsBatteryLowBehavior" />
<java-symbol type="integer" name="config_notificationsBatteryLowARGB" />
<java-symbol type="integer" name="config_notificationsBatteryMediumARGB" />
<java-symbol type="integer" name="config_notificationsBatteryNearlyFullLevel" />
@@ -2210,6 +2212,7 @@
<java-symbol type="string" name="config_platformVpnConfirmDialogComponent" />
<java-symbol type="string" name="config_carrierAppInstallDialogComponent" />
<java-symbol type="string" name="config_credentialManagerDialogComponent" />
+ <java-symbol type="string" name="config_credentialManagerReceiverComponent" />
<java-symbol type="string" name="config_defaultNetworkScorerPackageName" />
<java-symbol type="string" name="config_persistentDataPackageName" />
<java-symbol type="string" name="config_deviceConfiguratorPackageName" />
diff --git a/core/res/res/xml/irq_device_map.xml b/core/res/res/xml/irq_device_map.xml
index 86a44d6a9fe0..4fae8fb77687 100644
--- a/core/res/res/xml/irq_device_map.xml
+++ b/core/res/res/xml/irq_device_map.xml
@@ -17,14 +17,15 @@
*/
-->
<irq-device-map>
- <!-- This file maps devices (chips) that can send IRQs to the CPU (and bring it out of sleep) to
- logical subsystems in userspace code. Since each Android device has its own uniquely
- designed chipset, this mapping is expected to be empty by default and should be overridden
- by device specific configs.
+ <!-- This file maps devices (chips) that can send interrupts to the main processor (and bring it
+ out of sleep) to logical subsystems in userspace code. Since each Android device has its own
+ uniquely designed chipset, this mapping is expected to be empty by default and should be
+ overridden by device-specific configs.
This mapping helps the system to meaningfully attribute CPU wakeups to logical work that
happened on the device. The devices are referred to by their names as defined in the kernel.
- Currently defined subsystems are:
+ Currently, defined subsystems are:
- Alarm: Use this to denote wakeup alarms requested by apps via the AlarmManager API.
+ - Wifi: Use this to denote network traffic that uses the wifi transport.
The overlay should use tags <device> and <subsystem> to describe this mapping in the
following way:
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index e164e08e66e6..4f91e7a3545a 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -16,7 +16,7 @@
package android.app.activity;
-import static android.companion.virtual.VirtualDeviceManager.DEVICE_ID_INVALID;
+import static android.content.Context.DEVICE_ID_INVALID;
import static android.content.Intent.ACTION_EDIT;
import static android.content.Intent.ACTION_VIEW;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
diff --git a/core/tests/coretests/src/android/companion/virtual/sensor/VirtualSensorConfigTest.java b/core/tests/coretests/src/android/companion/virtual/sensor/VirtualSensorConfigTest.java
index f97099d04572..16ed3ef42da3 100644
--- a/core/tests/coretests/src/android/companion/virtual/sensor/VirtualSensorConfigTest.java
+++ b/core/tests/coretests/src/android/companion/virtual/sensor/VirtualSensorConfigTest.java
@@ -17,9 +17,15 @@
package android.companion.virtual.sensor;
import static android.hardware.Sensor.TYPE_ACCELEROMETER;
+import static android.hardware.SensorDirectChannel.RATE_STOP;
+import static android.hardware.SensorDirectChannel.RATE_VERY_FAST;
+import static android.hardware.SensorDirectChannel.TYPE_HARDWARE_BUFFER;
+import static android.hardware.SensorDirectChannel.TYPE_MEMORY_FILE;
import static com.google.common.truth.Truth.assertThat;
+import static org.testng.Assert.assertThrows;
+
import android.os.Parcel;
import android.platform.test.annotations.Presubmit;
@@ -40,6 +46,8 @@ public class VirtualSensorConfigTest {
final VirtualSensorConfig originalConfig =
new VirtualSensorConfig.Builder(TYPE_ACCELEROMETER, SENSOR_NAME)
.setVendor(SENSOR_VENDOR)
+ .setHighestDirectReportRateLevel(RATE_VERY_FAST)
+ .setDirectChannelTypesSupported(TYPE_MEMORY_FILE)
.build();
final Parcel parcel = Parcel.obtain();
originalConfig.writeToParcel(parcel, /* flags= */ 0);
@@ -49,6 +57,39 @@ public class VirtualSensorConfigTest {
assertThat(recreatedConfig.getType()).isEqualTo(originalConfig.getType());
assertThat(recreatedConfig.getName()).isEqualTo(originalConfig.getName());
assertThat(recreatedConfig.getVendor()).isEqualTo(originalConfig.getVendor());
+ assertThat(recreatedConfig.getHighestDirectReportRateLevel()).isEqualTo(RATE_VERY_FAST);
+ assertThat(recreatedConfig.getDirectChannelTypesSupported()).isEqualTo(TYPE_MEMORY_FILE);
+ // From hardware/libhardware/include/hardware/sensors-base.h:
+ // 0x400 is SENSOR_FLAG_DIRECT_CHANNEL_ASHMEM (i.e. TYPE_MEMORY_FILE)
+ // 0x800 is SENSOR_FLAG_DIRECT_CHANNEL_GRALLOC (i.e. TYPE_HARDWARE_BUFFER)
+ // 7 is SENSOR_FLAG_SHIFT_DIRECT_REPORT
+ assertThat(recreatedConfig.getFlags()).isEqualTo(0x400 | RATE_VERY_FAST << 7);
+ }
+
+ @Test
+ public void hardwareBufferDirectChannelTypeSupported_throwsException() {
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> new VirtualSensorConfig.Builder(TYPE_ACCELEROMETER, SENSOR_NAME)
+ .setDirectChannelTypesSupported(TYPE_HARDWARE_BUFFER | TYPE_MEMORY_FILE));
+ }
+
+ @Test
+ public void directChannelTypeSupported_missingHighestReportRateLevel_throwsException() {
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> new VirtualSensorConfig.Builder(TYPE_ACCELEROMETER, SENSOR_NAME)
+ .setDirectChannelTypesSupported(TYPE_MEMORY_FILE)
+ .build());
+ }
+
+ @Test
+ public void directChannelTypeSupported_missingDirectChannelTypeSupported_throwsException() {
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> new VirtualSensorConfig.Builder(TYPE_ACCELEROMETER, SENSOR_NAME)
+ .setHighestDirectReportRateLevel(RATE_VERY_FAST)
+ .build());
}
@Test
@@ -56,5 +97,8 @@ public class VirtualSensorConfigTest {
final VirtualSensorConfig config =
new VirtualSensorConfig.Builder(TYPE_ACCELEROMETER, SENSOR_NAME).build();
assertThat(config.getVendor()).isNull();
+ assertThat(config.getHighestDirectReportRateLevel()).isEqualTo(RATE_STOP);
+ assertThat(config.getDirectChannelTypesSupported()).isEqualTo(0);
+ assertThat(config.getFlags()).isEqualTo(0);
}
}
diff --git a/core/tests/coretests/src/android/content/ContextTest.java b/core/tests/coretests/src/android/content/ContextTest.java
index 324f81084f98..d4784374745d 100644
--- a/core/tests/coretests/src/android/content/ContextTest.java
+++ b/core/tests/coretests/src/android/content/ContextTest.java
@@ -16,7 +16,7 @@
package android.content;
-import static android.companion.virtual.VirtualDeviceManager.DEVICE_ID_DEFAULT;
+import static android.content.Context.DEVICE_ID_DEFAULT;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
import static android.view.Display.DEFAULT_DISPLAY;
diff --git a/core/tests/coretests/src/android/content/pm/UserPackageTest.java b/core/tests/coretests/src/android/content/pm/UserPackageTest.java
new file mode 100644
index 000000000000..5114e2cf9327
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/UserPackageTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.platform.test.annotations.Presubmit;
+
+import junit.framework.TestCase;
+
+@Presubmit
+public class UserPackageTest extends TestCase {
+ public void testCacheLimit() {
+ UserPackage.setValidUserIds(new int[]{0});
+ for (int i = 0; i < UserPackage.MAX_NUM_CACHED_ENTRIES_PER_USER; ++i) {
+ UserPackage.of(0, "app" + i);
+ assertEquals(i + 1, UserPackage.numEntriesForUser(0));
+ }
+
+ for (int i = 0; i < UserPackage.MAX_NUM_CACHED_ENTRIES_PER_USER; ++i) {
+ UserPackage.of(0, "appOverLimit" + i);
+ final int numCached = UserPackage.numEntriesForUser(0);
+ assertTrue(numCached >= 1);
+ assertTrue(numCached <= UserPackage.MAX_NUM_CACHED_ENTRIES_PER_USER);
+ }
+ }
+}
diff --git a/core/tests/coretests/src/android/content/res/FontScaleConverterActivityTest.java b/core/tests/coretests/src/android/content/res/FontScaleConverterActivityTest.java
index 55ef85408132..980211fe4cc8 100644
--- a/core/tests/coretests/src/android/content/res/FontScaleConverterActivityTest.java
+++ b/core/tests/coretests/src/android/content/res/FontScaleConverterActivityTest.java
@@ -27,6 +27,7 @@ import android.compat.testing.PlatformCompatChangeRule;
import android.os.Bundle;
import android.platform.test.annotations.Presubmit;
import android.provider.Settings;
+import android.util.PollingCheck;
import android.view.View;
import android.widget.TextView;
@@ -91,6 +92,9 @@ public class FontScaleConverterActivityTest {
var densityRef = new AtomicReference<Float>();
scenario.onActivity(activity -> {
+ assertThat(activity.getResources().getConfiguration().fontScale)
+ .isWithin(0.05f)
+ .of(2f);
densityRef.compareAndSet(null, activity.getResources().getDisplayMetrics().density);
});
var density = densityRef.get();
@@ -141,6 +145,15 @@ public class FontScaleConverterActivityTest {
fontScale
);
});
+
+ PollingCheck.waitFor(/* timeout= */ 5000, () ->
+ InstrumentationRegistry
+ .getInstrumentation()
+ .getContext()
+ .getResources()
+ .getConfiguration()
+ .fontScale == fontScale
+ );
}
private Matcher<View> withTextSizeInRange(float sizeStartPx, float sizeEndPx) {
diff --git a/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt b/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
index 249e2468d87e..a0d8dcf830e8 100644
--- a/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
+++ b/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
@@ -28,6 +28,7 @@ import kotlin.math.ceil
import kotlin.math.floor
import org.junit.Test
import org.junit.runner.RunWith
+import kotlin.random.Random.Default.nextFloat
@Presubmit
@RunWith(AndroidJUnit4::class)
@@ -43,14 +44,56 @@ class FontScaleConverterFactoryTest {
assertThat(table.convertSpToDp(0F)).isWithin(CONVERSION_TOLERANCE).of(0f)
}
- @SmallTest
- fun missingLookupTableReturnsNull() {
- assertThat(FontScaleConverterFactory.forScale(3F)).isNull()
+ @LargeTest
+ @Test
+ fun missingLookupTablePastEnd_returnsLinear() {
+ val table = FontScaleConverterFactory.forScale(3F)!!
+ generateSequenceOfFractions(-10000f..10000f, step = 0.01f)
+ .map {
+ assertThat(table.convertSpToDp(it)).isWithin(CONVERSION_TOLERANCE).of(it * 3f)
+ }
+ assertThat(table.convertSpToDp(1F)).isWithin(CONVERSION_TOLERANCE).of(3f)
+ assertThat(table.convertSpToDp(8F)).isWithin(CONVERSION_TOLERANCE).of(24f)
+ assertThat(table.convertSpToDp(10F)).isWithin(CONVERSION_TOLERANCE).of(30f)
+ assertThat(table.convertSpToDp(5F)).isWithin(CONVERSION_TOLERANCE).of(15f)
+ assertThat(table.convertSpToDp(0F)).isWithin(CONVERSION_TOLERANCE).of(0f)
+ assertThat(table.convertSpToDp(50F)).isWithin(CONVERSION_TOLERANCE).of(150f)
+ assertThat(table.convertSpToDp(100F)).isWithin(CONVERSION_TOLERANCE).of(300f)
}
@SmallTest
- fun missingLookupTable105ReturnsNull() {
- assertThat(FontScaleConverterFactory.forScale(1.05F)).isNull()
+ fun missingLookupTable110_returnsInterpolated() {
+ val table = FontScaleConverterFactory.forScale(1.1F)!!
+
+ assertThat(table.convertSpToDp(1F)).isWithin(CONVERSION_TOLERANCE).of(1.1f)
+ assertThat(table.convertSpToDp(8F)).isWithin(CONVERSION_TOLERANCE).of(8f * 1.1f)
+ assertThat(table.convertSpToDp(10F)).isWithin(CONVERSION_TOLERANCE).of(11f)
+ assertThat(table.convertSpToDp(5F)).isWithin(CONVERSION_TOLERANCE).of(5f * 1.1f)
+ assertThat(table.convertSpToDp(0F)).isWithin(CONVERSION_TOLERANCE).of(0f)
+ assertThat(table.convertSpToDp(50F)).isLessThan(50f * 1.1f)
+ assertThat(table.convertSpToDp(100F)).isLessThan(100f * 1.1f)
+ }
+
+ @Test
+ fun missingLookupTable199_returnsInterpolated() {
+ val table = FontScaleConverterFactory.forScale(1.9999F)!!
+ assertThat(table.convertSpToDp(1F)).isWithin(CONVERSION_TOLERANCE).of(2f)
+ assertThat(table.convertSpToDp(8F)).isWithin(CONVERSION_TOLERANCE).of(16f)
+ assertThat(table.convertSpToDp(10F)).isWithin(CONVERSION_TOLERANCE).of(20f)
+ assertThat(table.convertSpToDp(5F)).isWithin(CONVERSION_TOLERANCE).of(10f)
+ assertThat(table.convertSpToDp(0F)).isWithin(CONVERSION_TOLERANCE).of(0f)
+ }
+
+ @Test
+ fun missingLookupTable160_returnsInterpolated() {
+ val table = FontScaleConverterFactory.forScale(1.6F)!!
+ assertThat(table.convertSpToDp(1F)).isWithin(CONVERSION_TOLERANCE).of(1f * 1.6F)
+ assertThat(table.convertSpToDp(8F)).isWithin(CONVERSION_TOLERANCE).of(8f * 1.6F)
+ assertThat(table.convertSpToDp(10F)).isWithin(CONVERSION_TOLERANCE).of(10f * 1.6F)
+ assertThat(table.convertSpToDp(20F)).isLessThan(20f * 1.6F)
+ assertThat(table.convertSpToDp(100F)).isLessThan(100f * 1.6F)
+ assertThat(table.convertSpToDp(5F)).isWithin(CONVERSION_TOLERANCE).of(5f * 1.6F)
+ assertThat(table.convertSpToDp(0F)).isWithin(CONVERSION_TOLERANCE).of(0f)
}
@SmallTest
@@ -82,21 +125,23 @@ class FontScaleConverterFactoryTest {
@LargeTest
@Test
fun allFeasibleScalesAndConversionsDoNotCrash() {
- generateSequenceOfFractions(-10f..10f, step = 0.01f)
+ generateSequenceOfFractions(-10f..10f, step = 0.1f)
+ .fuzzFractions()
.mapNotNull{ FontScaleConverterFactory.forScale(it) }
.flatMap{ table ->
- generateSequenceOfFractions(-2000f..2000f, step = 0.01f)
+ generateSequenceOfFractions(-2000f..2000f, step = 0.1f)
+ .fuzzFractions()
.map{ Pair(table, it) }
}
.forEach { (table, sp) ->
try {
- assertWithMessage(
- "convertSpToDp(%s) on table: %s",
- sp.toString(),
- table.toString()
- )
- .that(table.convertSpToDp(sp))
- .isFinite()
+ // Truth is slow because it creates a bunch of
+ // objects. Don't use it unless we need to.
+ if (!table.convertSpToDp(sp).isFinite()) {
+ assertWithMessage("convertSpToDp(%s) on table: %s", sp, table)
+ .that(table.convertSpToDp(sp))
+ .isFinite()
+ }
} catch (e: Exception) {
throw AssertionError("Exception during convertSpToDp($sp) on table: $table", e)
}
@@ -130,6 +175,30 @@ class FontScaleConverterFactoryTest {
assertThat(fractions).doesNotContain(-.35f)
}
+ @Test
+ fun testFuzzFractions() {
+ val numFuzzedFractions = 6
+ val fractions = generateSequenceOfFractions(-1000f..1000f, step = 0.1f)
+ .fuzzFractions()
+ .toList()
+ fractions.forEach {
+ assertThat(it).isAtLeast(-1000f)
+ assertThat(it).isLessThan(1001f)
+ }
+
+ val numGeneratedFractions = 1000 * 2 * 10 + 1 // Don't forget the 0 in the middle!
+ assertThat(fractions).hasSize(numGeneratedFractions * numFuzzedFractions)
+
+ assertThat(fractions).contains(100f)
+ assertThat(fractions).contains(500.1f)
+ assertThat(fractions).contains(500.2f)
+ assertThat(fractions).contains(0.2f)
+ assertThat(fractions).contains(0f)
+ assertThat(fractions).contains(-10f)
+ assertThat(fractions).contains(-10f)
+ assertThat(fractions).contains(-10.3f)
+ }
+
companion object {
private const val CONVERSION_TOLERANCE = 0.05f
}
@@ -146,3 +215,9 @@ fun generateSequenceOfFractions(
.takeWhile { it <= endInclusive }
.map{ it.toFloat() / multiplier }
}
+
+private fun Sequence<Float>.fuzzFractions(): Sequence<Float> {
+ return flatMap { i ->
+ listOf(i, i + 0.01f, i + 0.054f, i + 0.099f, i + nextFloat(), i + nextFloat())
+ }
+}
diff --git a/core/tests/coretests/src/android/credentials/CredentialManagerTest.java b/core/tests/coretests/src/android/credentials/CredentialManagerTest.java
index 444e9f222ddc..43334ab08b2f 100644
--- a/core/tests/coretests/src/android/credentials/CredentialManagerTest.java
+++ b/core/tests/coretests/src/android/credentials/CredentialManagerTest.java
@@ -19,7 +19,6 @@ package android.credentials;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
-import static org.junit.Assume.assumeTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.same;
@@ -102,8 +101,12 @@ public class CredentialManagerTest {
mGetRequest = new GetCredentialRequest.Builder(Bundle.EMPTY).addCredentialOption(
new CredentialOption(Credential.TYPE_PASSWORD_CREDENTIAL, Bundle.EMPTY,
Bundle.EMPTY, false)).build();
- mCreateRequest = new CreateCredentialRequest(Credential.TYPE_PASSWORD_CREDENTIAL,
- Bundle.EMPTY, Bundle.EMPTY, false, false);
+ mCreateRequest = new CreateCredentialRequest.Builder(
+ Credential.TYPE_PASSWORD_CREDENTIAL,
+ Bundle.EMPTY, Bundle.EMPTY)
+ .setIsSystemProviderRequired(false)
+ .setAlwaysSendAppInfoToProvider(false)
+ .build();
mClearRequest = new ClearCredentialStateRequest(Bundle.EMPTY);
final Slice slice = new Slice.Builder(Uri.parse("foo://bar"), null).addText("some text",
@@ -593,15 +596,12 @@ public class CredentialManagerTest {
@Test
public void testRegisterCredentialDescription_nullRequest() {
- assumeTrue(CredentialManager.isCredentialDescriptionApiEnabled());
assertThrows(NullPointerException.class,
() -> mCredentialManager.registerCredentialDescription(null));
}
@Test
public void testRegisterCredentialDescription_success() throws RemoteException {
- assumeTrue(CredentialManager.isCredentialDescriptionApiEnabled());
-
mCredentialManager.registerCredentialDescription(mRegisterRequest);
verify(mMockCredentialManagerService).registerCredentialDescription(same(mRegisterRequest),
eq(mPackageName));
@@ -609,16 +609,12 @@ public class CredentialManagerTest {
@Test
public void testUnregisterCredentialDescription_nullRequest() {
- assumeTrue(CredentialManager.isCredentialDescriptionApiEnabled());
-
assertThrows(NullPointerException.class,
() -> mCredentialManager.unregisterCredentialDescription(null));
}
@Test
public void testUnregisterCredentialDescription_success() throws RemoteException {
- assumeTrue(CredentialManager.isCredentialDescriptionApiEnabled());
-
mCredentialManager.unregisterCredentialDescription(mUnregisterRequest);
verify(mMockCredentialManagerService).unregisterCredentialDescription(
same(mUnregisterRequest), eq(mPackageName));
diff --git a/core/tests/coretests/src/android/hardware/face/FaceManagerTest.java b/core/tests/coretests/src/android/hardware/face/FaceManagerTest.java
new file mode 100644
index 000000000000..9b1f0cd9e8da
--- /dev/null
+++ b/core/tests/coretests/src/android/hardware/face/FaceManagerTest.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.face;
+
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.res.Resources;
+import android.os.CancellationSignal;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.test.TestLooper;
+import android.platform.test.annotations.Presubmit;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.junit.MockitoRule;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Presubmit
+@RunWith(MockitoJUnitRunner.class)
+public class FaceManagerTest {
+ private static final int USER_ID = 4;
+ private static final String PACKAGE_NAME = "f.m.test";
+ private static final String ATTRIBUTION_TAG = "blue";
+
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
+ @Mock
+ private Context mContext;
+ @Mock
+ private Resources mResources;
+ @Mock
+ private IFaceService mService;
+ @Mock
+ private FaceManager.AuthenticationCallback mAuthCallback;
+
+ @Captor
+ private ArgumentCaptor<IFaceAuthenticatorsRegisteredCallback> mCaptor;
+ @Captor
+ private ArgumentCaptor<FaceAuthenticateOptions> mOptionsCaptor;
+
+ private List<FaceSensorPropertiesInternal> mProps;
+ private TestLooper mLooper;
+ private Handler mHandler;
+ private FaceManager mFaceManager;
+
+ @Before
+ public void setUp() throws Exception {
+ mLooper = new TestLooper();
+ mHandler = new Handler(mLooper.getLooper());
+
+ when(mContext.getMainLooper()).thenReturn(mLooper.getLooper());
+ when(mContext.getOpPackageName()).thenReturn(PACKAGE_NAME);
+ when(mContext.getAttributionTag()).thenReturn(ATTRIBUTION_TAG);
+ when(mContext.getApplicationInfo()).thenReturn(new ApplicationInfo());
+ when(mContext.getResources()).thenReturn(mResources);
+ when(mResources.getString(anyInt())).thenReturn("string");
+
+ mFaceManager = new FaceManager(mContext, mService);
+ mProps = List.of(new FaceSensorPropertiesInternal(
+ 0 /* id */,
+ FaceSensorProperties.STRENGTH_STRONG,
+ 1 /* maxTemplatesAllowed */,
+ new ArrayList<>() /* componentInfo */,
+ FaceSensorProperties.TYPE_UNKNOWN,
+ true /* supportsFaceDetection */,
+ true /* supportsSelfIllumination */,
+ false /* resetLockoutRequiresChallenge */));
+ }
+
+ @Test
+ public void getSensorPropertiesInternal_noBinderCalls() throws RemoteException {
+ verify(mService).addAuthenticatorsRegisteredCallback(mCaptor.capture());
+
+ mCaptor.getValue().onAllAuthenticatorsRegistered(mProps);
+ List<FaceSensorPropertiesInternal> actual = mFaceManager.getSensorPropertiesInternal();
+
+ assertThat(actual).isEqualTo(mProps);
+ verify(mService, never()).getSensorPropertiesInternal(any());
+ }
+
+ @Test
+ public void authenticate_withOptions() throws Exception {
+ mFaceManager.authenticate(null, new CancellationSignal(), mAuthCallback, mHandler,
+ new FaceAuthenticateOptions.Builder()
+ .setUserId(USER_ID)
+ .setOpPackageName("some.thing")
+ .setAttributionTag(null)
+ .build());
+
+ verify(mService).authenticate(any(IBinder.class), eq(0L),
+ any(IFaceServiceReceiver.class), mOptionsCaptor.capture());
+
+ assertThat(mOptionsCaptor.getValue()).isEqualTo(
+ new FaceAuthenticateOptions.Builder()
+ .setUserId(USER_ID)
+ .setOpPackageName(PACKAGE_NAME)
+ .setAttributionTag(ATTRIBUTION_TAG)
+ .build()
+ );
+ }
+
+ @Test
+ public void authenticate_errorWhenUnavailable() throws Exception {
+ when(mService.authenticate(any(), anyLong(), any(), any()))
+ .thenThrow(new RemoteException());
+
+ mFaceManager.authenticate(null, new CancellationSignal(),
+ mAuthCallback, mHandler,
+ new FaceAuthenticateOptions.Builder().build());
+
+ verify(mAuthCallback).onAuthenticationError(eq(FACE_ERROR_HW_UNAVAILABLE), any());
+ }
+}
diff --git a/core/tests/coretests/src/android/hardware/face/OWNERS b/core/tests/coretests/src/android/hardware/face/OWNERS
new file mode 100644
index 000000000000..6a2192a2c7fb
--- /dev/null
+++ b/core/tests/coretests/src/android/hardware/face/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/biometrics/OWNERS
diff --git a/core/tests/coretests/src/android/hardware/fingerprint/FingerprintManagerTest.java b/core/tests/coretests/src/android/hardware/fingerprint/FingerprintManagerTest.java
new file mode 100644
index 000000000000..f31903a73111
--- /dev/null
+++ b/core/tests/coretests/src/android/hardware/fingerprint/FingerprintManagerTest.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.fingerprint;
+
+import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.res.Resources;
+import android.os.CancellationSignal;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.test.TestLooper;
+import android.platform.test.annotations.Presubmit;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.junit.MockitoRule;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Presubmit
+@RunWith(MockitoJUnitRunner.class)
+public class FingerprintManagerTest {
+ private static final int USER_ID = 9;
+ private static final String PACKAGE_NAME = "finger.food.test";
+ private static final String ATTRIBUTION_TAG = "taz";
+
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
+ @Mock
+ private Context mContext;
+ @Mock
+ private Resources mResources;
+ @Mock
+ private IFingerprintService mService;
+ @Mock
+ private FingerprintManager.AuthenticationCallback mAuthCallback;
+
+ @Captor
+ private ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mCaptor;
+ @Captor
+ private ArgumentCaptor<FingerprintAuthenticateOptions> mOptionsCaptor;
+
+ private List<FingerprintSensorPropertiesInternal> mProps;
+ private TestLooper mLooper;
+ private Handler mHandler;
+ private FingerprintManager mFingerprintManager;
+
+ @Before
+ public void setUp() throws Exception {
+ mLooper = new TestLooper();
+ mHandler = new Handler(mLooper.getLooper());
+
+ when(mContext.getMainLooper()).thenReturn(mLooper.getLooper());
+ when(mContext.getOpPackageName()).thenReturn(PACKAGE_NAME);
+ when(mContext.getAttributionTag()).thenReturn(ATTRIBUTION_TAG);
+ when(mContext.getApplicationInfo()).thenReturn(new ApplicationInfo());
+ when(mContext.getResources()).thenReturn(mResources);
+ when(mResources.getString(anyInt())).thenReturn("string");
+
+ mFingerprintManager = new FingerprintManager(mContext, mService);
+ mProps = List.of(new FingerprintSensorPropertiesInternal(
+ 0 /* sensorId */,
+ FingerprintSensorProperties.STRENGTH_STRONG,
+ 1 /* maxEnrollmentsPerUser */,
+ new ArrayList<>() /* componentInfo */,
+ FingerprintSensorProperties.TYPE_UNKNOWN,
+ true /* halControlsIllumination */,
+ true /* resetLockoutRequiresHardwareAuthToken */,
+ new ArrayList<>() /* sensorLocations */));
+ }
+
+ @Test
+ public void getSensorPropertiesInternal_noBinderCalls() throws RemoteException {
+ verify(mService).addAuthenticatorsRegisteredCallback(mCaptor.capture());
+
+ mCaptor.getValue().onAllAuthenticatorsRegistered(mProps);
+ List<FingerprintSensorPropertiesInternal> actual =
+ mFingerprintManager.getSensorPropertiesInternal();
+
+ assertThat(actual).isEqualTo(mProps);
+ verify(mService, never()).getSensorPropertiesInternal(any());
+ }
+
+ @Test
+ public void authenticate_withOptions() throws Exception {
+ mFingerprintManager.authenticate(null, new CancellationSignal(), mAuthCallback, mHandler,
+ new FingerprintAuthenticateOptions.Builder()
+ .setUserId(USER_ID)
+ .setOpPackageName("some.thing")
+ .setAttributionTag(null)
+ .build());
+
+ verify(mService).authenticate(any(IBinder.class), eq(0L),
+ any(IFingerprintServiceReceiver.class), mOptionsCaptor.capture());
+
+ assertThat(mOptionsCaptor.getValue()).isEqualTo(
+ new FingerprintAuthenticateOptions.Builder()
+ .setUserId(USER_ID)
+ .setOpPackageName(PACKAGE_NAME)
+ .setAttributionTag(ATTRIBUTION_TAG)
+ .build()
+ );
+ }
+
+ @Test
+ public void authenticate_errorWhenUnavailable() throws Exception {
+ when(mService.authenticate(any(), anyLong(), any(), any()))
+ .thenThrow(new RemoteException());
+
+ mFingerprintManager.authenticate(null, new CancellationSignal(),
+ mAuthCallback, mHandler,
+ new FingerprintAuthenticateOptions.Builder().build());
+
+ verify(mAuthCallback).onAuthenticationError(eq(FINGERPRINT_ERROR_HW_UNAVAILABLE), any());
+ }
+}
diff --git a/core/tests/coretests/src/android/hardware/fingerprint/OWNERS b/core/tests/coretests/src/android/hardware/fingerprint/OWNERS
new file mode 100644
index 000000000000..6a2192a2c7fb
--- /dev/null
+++ b/core/tests/coretests/src/android/hardware/fingerprint/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/biometrics/OWNERS
diff --git a/core/tests/coretests/src/android/os/CancellationSignalBeamerTest.java b/core/tests/coretests/src/android/os/CancellationSignalBeamerTest.java
new file mode 100644
index 000000000000..42c97f3876a6
--- /dev/null
+++ b/core/tests/coretests/src/android/os/CancellationSignalBeamerTest.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import static android.os.CancellationSignalBeamer.Sender;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.os.CancellationSignalBeamer.Receiver;
+import android.util.PollingCheck;
+import android.util.PollingCheck.PollingCheckCondition;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.ref.Cleaner;
+import java.lang.ref.Reference;
+import java.util.concurrent.CountDownLatch;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class CancellationSignalBeamerTest {
+
+ private CancellationSignal mSenderSignal = new CancellationSignal();
+ private CancellationSignal mReceivedSignal;
+ private Context mContext = InstrumentationRegistry.getInstrumentation().getContext();
+
+ @Test
+ public void testBeam_null() {
+ try (var token = mSender.beam(null)) {
+ assertThat(token).isNull();
+ invokeGenericService(token);
+ }
+ assertThat(mReceivedSignal).isNull();
+ }
+
+ @Test
+ public void testBeam_nonNull() {
+ try (var token = mSender.beam(mSenderSignal)) {
+ assertThat(token).isNotNull();
+ invokeGenericService(token);
+ }
+ assertThat(mReceivedSignal).isNotNull();
+ }
+
+ @Test
+ public void testBeam_async() {
+ IBinder outerToken;
+ try (var token = mSender.beam(mSenderSignal)) {
+ assertThat(token).isNotNull();
+ outerToken = token;
+ }
+ invokeGenericService(outerToken);
+ assertThat(mReceivedSignal).isNotNull();
+ }
+
+ @Test
+ public void testCancelOnSentSignal_cancelsReceivedSignal() {
+ try (var token = mSender.beam(mSenderSignal)) {
+ invokeGenericService(token);
+ }
+ mSenderSignal.cancel();
+ assertThat(mReceivedSignal.isCanceled()).isTrue();
+ }
+
+ @Test
+ public void testSendingCancelledSignal_cancelsReceivedSignal() {
+ mSenderSignal.cancel();
+ try (var token = mSender.beam(mSenderSignal)) {
+ invokeGenericService(token);
+ }
+ assertThat(mReceivedSignal.isCanceled()).isTrue();
+ }
+
+ @Test
+ public void testUnbeam_null() {
+ assertThat(mReceiver.unbeam(null)).isNull();
+ }
+
+ @Test
+ public void testForget_null() {
+ mReceiver.forget(null);
+ }
+
+ @Test
+ public void testCancel_null() {
+ mReceiver.cancel(null);
+ }
+
+ @Test
+ public void testForget_withUnknownToken() {
+ mReceiver.forget(new Binder());
+ }
+
+ @Test
+ public void testCancel_withUnknownToken() {
+ mReceiver.cancel(new Binder());
+ }
+
+ @Test
+ public void testBinderDied_withUnknownToken() {
+ mReceiver.binderDied(new Binder());
+ }
+
+ @Test
+ public void testReceiverWithCancelOnSenderDead_cancelsOnSenderDeath() {
+ var receiver = new Receiver(true /* cancelOnSenderDeath */);
+ var token = new Binder();
+ var signal = receiver.unbeam(token);
+ receiver.binderDied(token);
+ assertThat(signal.isCanceled()).isTrue();
+ }
+
+ @Test
+ public void testReceiverWithoutCancelOnSenderDead_doesntCancelOnSenderDeath() {
+ var receiver = new Receiver(false /* cancelOnSenderDeath */);
+ var token = new Binder();
+ var signal = receiver.unbeam(token);
+ receiver.binderDied(token);
+ assertThat(signal.isCanceled()).isFalse();
+ }
+
+ @Test
+ public void testDroppingSentSignal_dropsReceivedSignal() throws Exception {
+ // In a multiprocess scenario, sending token over Binder might leak the token
+ // on both ends if we create a reference cycle. Simulate that worst-case scenario
+ // here by leaking it directly, then test that cleanup of the signals still works.
+ var receivedSignalCleaned = new CountDownLatch(1);
+ var tokenRef = new Object[1];
+ // Reference the cancellation signals in a separate method scope, so we don't
+ // accidentally leak them on the stack / in a register.
+ Runnable r = () -> {
+ try (var token = mSender.beam(mSenderSignal)) {
+ tokenRef[0] = token;
+ invokeGenericService(token);
+ }
+ mSenderSignal = null;
+
+ Cleaner.create().register(mReceivedSignal, receivedSignalCleaned::countDown);
+ mReceivedSignal = null;
+ };
+ r.run();
+
+ waitForWithGc(() -> receivedSignalCleaned.getCount() == 0);
+
+ Reference.reachabilityFence(tokenRef[0]);
+ }
+
+ @Test
+ public void testRepeatedBeaming_doesntLeak() throws Exception {
+ var receivedSignalCleaned = new CountDownLatch(1);
+ var tokenRef = new Object[1];
+ // Reference the cancellation signals in a separate method scope, so we don't
+ // accidentally leak them on the stack / in a register.
+ Runnable r = () -> {
+ try (var token = mSender.beam(mSenderSignal)) {
+ tokenRef[0] = token;
+ invokeGenericService(token);
+ }
+ // Beaming again leaves mReceivedSignal dangling, so it should be collected.
+ mSender.beam(mSenderSignal).close();
+
+ Cleaner.create().register(mReceivedSignal, receivedSignalCleaned::countDown);
+ mReceivedSignal = null;
+ };
+ r.run();
+
+ waitForWithGc(() -> receivedSignalCleaned.getCount() == 0);
+
+ Reference.reachabilityFence(tokenRef[0]);
+ }
+
+ private void waitForWithGc(PollingCheckCondition condition) throws IOException {
+ try {
+ PollingCheck.waitFor(() -> {
+ Runtime.getRuntime().gc();
+ return condition.canProceed();
+ });
+ } catch (AssertionError e) {
+ File heap = new File(mContext.getExternalFilesDir(null), "dump.hprof");
+ Debug.dumpHprofData(heap.getAbsolutePath());
+ throw e;
+ }
+ }
+
+ private void invokeGenericService(IBinder cancellationSignalToken) {
+ mReceivedSignal = mReceiver.unbeam(cancellationSignalToken);
+ }
+
+ private final Sender mSender = new Sender() {
+ @Override
+ public void onCancel(IBinder token) {
+ mReceiver.cancel(token);
+ }
+
+ @Override
+ public void onForget(IBinder token) {
+ mReceiver.forget(token);
+ }
+ };
+
+ private final Receiver mReceiver = new Receiver(false);
+}
diff --git a/core/tests/coretests/src/android/provider/NameValueCacheTest.java b/core/tests/coretests/src/android/provider/NameValueCacheTest.java
index 2e31bb581fbc..b6fc137471a4 100644
--- a/core/tests/coretests/src/android/provider/NameValueCacheTest.java
+++ b/core/tests/coretests/src/android/provider/NameValueCacheTest.java
@@ -32,16 +32,18 @@ import android.platform.test.annotations.Presubmit;
import android.test.mock.MockContentResolver;
import android.util.MemoryIntArray;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -59,42 +61,63 @@ public class NameValueCacheTest {
private static final String NAMESPACE = "namespace";
private static final String NAMESPACE2 = "namespace2";
+ private static final String SETTING = "test_setting";
+ private static final String SETTING2 = "test_setting2";
+
@Mock
private IContentProvider mMockIContentProvider;
@Mock
private ContentProvider mMockContentProvider;
private MockContentResolver mMockContentResolver;
- private MemoryIntArray mCacheGenerationStore;
- private int mCurrentGeneration = 123;
+ private MemoryIntArray mConfigsCacheGenerationStore;
+ private MemoryIntArray mSettingsCacheGenerationStore;
+
+ private HashMap<String, HashMap<String, String>> mConfigsStorage;
+ private HashMap<String, String> mSettingsStorage;
- private HashMap<String, HashMap<String, String>> mStorage;
@Before
public void setUp() throws Exception {
Settings.Config.clearProviderForTest();
+ Settings.Secure.clearProviderForTest();
MockitoAnnotations.initMocks(this);
when(mMockContentProvider.getIContentProvider()).thenReturn(mMockIContentProvider);
- mMockContentResolver = new MockContentResolver(InstrumentationRegistry
- .getInstrumentation().getContext());
+ mMockContentResolver = new MockContentResolver(
+ InstrumentationRegistry.getInstrumentation().getContext());
mMockContentResolver.addProvider(Settings.Config.CONTENT_URI.getAuthority(),
mMockContentProvider);
- mCacheGenerationStore = new MemoryIntArray(1);
- mStorage = new HashMap<>();
+ mMockContentResolver.addProvider(Settings.Secure.CONTENT_URI.getAuthority(),
+ mMockContentProvider);
+ mConfigsCacheGenerationStore = new MemoryIntArray(2);
+ mConfigsCacheGenerationStore.set(0, 123);
+ mConfigsCacheGenerationStore.set(1, 456);
+ mSettingsCacheGenerationStore = new MemoryIntArray(2);
+ mSettingsCacheGenerationStore.set(0, 234);
+ mSettingsCacheGenerationStore.set(1, 567);
+ mConfigsStorage = new HashMap<>();
+ mSettingsStorage = new HashMap<>();
// Stores keyValues for a given prefix and increments the generation. (Note that this
// increments the generation no matter what, it doesn't pay attention to if anything
// actually changed).
when(mMockIContentProvider.call(any(), eq(Settings.Config.CONTENT_URI.getAuthority()),
- eq(Settings.CALL_METHOD_SET_ALL_CONFIG),
- any(), any(Bundle.class))).thenAnswer(invocationOnMock -> {
+ eq(Settings.CALL_METHOD_SET_ALL_CONFIG), any(), any(Bundle.class))).thenAnswer(
+ invocationOnMock -> {
Bundle incomingBundle = invocationOnMock.getArgument(4);
HashMap<String, String> keyValues =
(HashMap<String, String>) incomingBundle.getSerializable(
- Settings.CALL_METHOD_FLAGS_KEY);
+ Settings.CALL_METHOD_FLAGS_KEY, HashMap.class);
String prefix = incomingBundle.getString(Settings.CALL_METHOD_PREFIX_KEY);
- mStorage.put(prefix, keyValues);
- mCacheGenerationStore.set(0, ++mCurrentGeneration);
-
+ mConfigsStorage.put(prefix, keyValues);
+ int currentGeneration;
+ // Different prefixes have different generation codes
+ if (prefix.equals(NAMESPACE + "/")) {
+ currentGeneration = mConfigsCacheGenerationStore.get(0);
+ mConfigsCacheGenerationStore.set(0, ++currentGeneration);
+ } else if (prefix.equals(NAMESPACE2 + "/")) {
+ currentGeneration = mConfigsCacheGenerationStore.get(1);
+ mConfigsCacheGenerationStore.set(1, ++currentGeneration);
+ }
Bundle result = new Bundle();
result.putInt(Settings.KEY_CONFIG_SET_ALL_RETURN,
Settings.SET_ALL_RESULT_SUCCESS);
@@ -102,49 +125,101 @@ public class NameValueCacheTest {
});
// Returns the keyValues corresponding to a namespace, or an empty map if the namespace
- // doesn't have anything stored for it. Returns the generation key if the caller asked
- // for one.
+ // doesn't have anything stored for it. Returns the generation key if the map isn't empty
+ // and the caller asked for the generation key.
when(mMockIContentProvider.call(any(), eq(Settings.Config.CONTENT_URI.getAuthority()),
- eq(Settings.CALL_METHOD_LIST_CONFIG),
- any(), any(Bundle.class))).thenAnswer(invocationOnMock -> {
+ eq(Settings.CALL_METHOD_LIST_CONFIG), any(), any(Bundle.class))).thenAnswer(
+ invocationOnMock -> {
Bundle incomingBundle = invocationOnMock.getArgument(4);
String prefix = incomingBundle.getString(Settings.CALL_METHOD_PREFIX_KEY);
- if (!mStorage.containsKey(prefix)) {
- mStorage.put(prefix, new HashMap<>());
+ if (!mConfigsStorage.containsKey(prefix)) {
+ mConfigsStorage.put(prefix, new HashMap<>());
}
- HashMap<String, String> keyValues = mStorage.get(prefix);
+ HashMap<String, String> keyValues = mConfigsStorage.get(prefix);
Bundle bundle = new Bundle();
bundle.putSerializable(Settings.NameValueTable.VALUE, keyValues);
- if (incomingBundle.containsKey(Settings.CALL_METHOD_TRACK_GENERATION_KEY)) {
+ if (!keyValues.isEmpty() && incomingBundle.containsKey(
+ Settings.CALL_METHOD_TRACK_GENERATION_KEY)) {
+ int index = prefix.equals(NAMESPACE + "/") ? 0 : 1;
+ bundle.putParcelable(Settings.CALL_METHOD_TRACK_GENERATION_KEY,
+ mConfigsCacheGenerationStore);
+ bundle.putInt(Settings.CALL_METHOD_GENERATION_INDEX_KEY, index);
+ bundle.putInt(Settings.CALL_METHOD_GENERATION_KEY,
+ mConfigsCacheGenerationStore.get(index));
+ }
+ return bundle;
+ });
+
+ // Stores value for a given setting's name and increments the generation. (Note that this
+ // increments the generation no matter what, it doesn't pay attention to if anything
+ // actually changed).
+ when(mMockIContentProvider.call(any(), eq(Settings.Secure.CONTENT_URI.getAuthority()),
+ eq(Settings.CALL_METHOD_PUT_SECURE), any(), any(Bundle.class))).thenAnswer(
+ invocationOnMock -> {
+ Bundle incomingBundle = invocationOnMock.getArgument(4);
+ String key = invocationOnMock.getArgument(3);
+ String value = incomingBundle.getString(Settings.NameValueTable.VALUE);
+ mSettingsStorage.put(key, value);
+ int currentGeneration;
+ // Different settings have different generation codes
+ if (key.equals(SETTING)) {
+ currentGeneration = mSettingsCacheGenerationStore.get(0);
+ mSettingsCacheGenerationStore.set(0, ++currentGeneration);
+ } else if (key.equals(SETTING2)) {
+ currentGeneration = mSettingsCacheGenerationStore.get(1);
+ mSettingsCacheGenerationStore.set(1, ++currentGeneration);
+ }
+ return null;
+ });
+
+ // Returns the value corresponding to a setting, or null if the setting
+ // doesn't have a value stored for it. Returns the generation key if the value isn't null
+ // and the caller asked for the generation key.
+ when(mMockIContentProvider.call(any(), eq(Settings.Secure.CONTENT_URI.getAuthority()),
+ eq(Settings.CALL_METHOD_GET_SECURE), any(), any(Bundle.class))).thenAnswer(
+ invocationOnMock -> {
+ Bundle incomingBundle = invocationOnMock.getArgument(4);
+ String key = invocationOnMock.getArgument(3);
+ String value = mSettingsStorage.get(key);
+
+ Bundle bundle = new Bundle();
+ bundle.putSerializable(Settings.NameValueTable.VALUE, value);
+
+ if (value != null && incomingBundle.containsKey(
+ Settings.CALL_METHOD_TRACK_GENERATION_KEY)) {
+ int index = key.equals(SETTING) ? 0 : 1;
bundle.putParcelable(Settings.CALL_METHOD_TRACK_GENERATION_KEY,
- mCacheGenerationStore);
- bundle.putInt(Settings.CALL_METHOD_GENERATION_INDEX_KEY, 0);
+ mSettingsCacheGenerationStore);
+ bundle.putInt(Settings.CALL_METHOD_GENERATION_INDEX_KEY, index);
bundle.putInt(Settings.CALL_METHOD_GENERATION_KEY,
- mCacheGenerationStore.get(0));
+ mSettingsCacheGenerationStore.get(index));
}
return bundle;
});
}
+ @After
+ public void cleanUp() throws IOException {
+ mConfigsStorage.clear();
+ mSettingsStorage.clear();
+ }
+
@Test
public void testCaching_singleNamespace() throws Exception {
HashMap<String, String> keyValues = new HashMap<>();
keyValues.put("a", "b");
Settings.Config.setStrings(mMockContentResolver, NAMESPACE, keyValues);
- verify(mMockIContentProvider).call(any(), any(),
- eq(Settings.CALL_METHOD_SET_ALL_CONFIG),
- any(), any(Bundle.class));
+ verify(mMockIContentProvider, times(1)).call(any(), any(),
+ eq(Settings.CALL_METHOD_SET_ALL_CONFIG), any(), any(Bundle.class));
Map<String, String> returnedValues = Settings.Config.getStrings(mMockContentResolver,
- NAMESPACE,
- Collections.emptyList());
- verify(mMockIContentProvider).call(any(), any(),
- eq(Settings.CALL_METHOD_LIST_CONFIG),
- any(), any(Bundle.class));
+ NAMESPACE, Collections.emptyList());
+ verify(mMockIContentProvider, times(1)).call(any(), any(),
+ eq(Settings.CALL_METHOD_LIST_CONFIG), any(), any(Bundle.class));
assertThat(returnedValues).containsExactlyEntriesIn(keyValues);
Map<String, String> cachedKeyValues = Settings.Config.getStrings(mMockContentResolver,
@@ -156,14 +231,12 @@ public class NameValueCacheTest {
keyValues.put("a", "c");
Settings.Config.setStrings(mMockContentResolver, NAMESPACE, keyValues);
verify(mMockIContentProvider, times(2)).call(any(), any(),
- eq(Settings.CALL_METHOD_SET_ALL_CONFIG),
- any(), any(Bundle.class));
+ eq(Settings.CALL_METHOD_SET_ALL_CONFIG), any(), any(Bundle.class));
Map<String, String> returnedValues2 = Settings.Config.getStrings(mMockContentResolver,
NAMESPACE, Collections.emptyList());
verify(mMockIContentProvider, times(2)).call(any(), any(),
- eq(Settings.CALL_METHOD_LIST_CONFIG),
- any(), any(Bundle.class));
+ eq(Settings.CALL_METHOD_LIST_CONFIG), any(), any(Bundle.class));
assertThat(returnedValues2).containsExactlyEntriesIn(keyValues);
Map<String, String> cachedKeyValues2 = Settings.Config.getStrings(mMockContentResolver,
@@ -177,36 +250,31 @@ public class NameValueCacheTest {
HashMap<String, String> keyValues = new HashMap<>();
keyValues.put("a", "b");
Settings.Config.setStrings(mMockContentResolver, NAMESPACE, keyValues);
- verify(mMockIContentProvider).call(any(), any(),
- eq(Settings.CALL_METHOD_SET_ALL_CONFIG),
+ verify(mMockIContentProvider).call(any(), any(), eq(Settings.CALL_METHOD_SET_ALL_CONFIG),
any(), any(Bundle.class));
+ Map<String, String> returnedValues = Settings.Config.getStrings(mMockContentResolver,
+ NAMESPACE, Collections.emptyList());
+ verify(mMockIContentProvider).call(any(), any(), eq(Settings.CALL_METHOD_LIST_CONFIG),
+ any(), any(Bundle.class));
+ assertThat(returnedValues).containsExactlyEntriesIn(keyValues);
+
HashMap<String, String> keyValues2 = new HashMap<>();
keyValues2.put("c", "d");
keyValues2.put("e", "f");
Settings.Config.setStrings(mMockContentResolver, NAMESPACE2, keyValues2);
verify(mMockIContentProvider, times(2)).call(any(), any(),
- eq(Settings.CALL_METHOD_SET_ALL_CONFIG),
- any(), any(Bundle.class));
-
- Map<String, String> returnedValues = Settings.Config.getStrings(mMockContentResolver,
- NAMESPACE,
- Collections.emptyList());
- verify(mMockIContentProvider).call(any(), any(),
- eq(Settings.CALL_METHOD_LIST_CONFIG),
- any(), any(Bundle.class));
- assertThat(returnedValues).containsExactlyEntriesIn(keyValues);
+ eq(Settings.CALL_METHOD_SET_ALL_CONFIG), any(), any(Bundle.class));
Map<String, String> returnedValues2 = Settings.Config.getStrings(mMockContentResolver,
- NAMESPACE2,
- Collections.emptyList());
+ NAMESPACE2, Collections.emptyList());
verify(mMockIContentProvider, times(2)).call(any(), any(),
- eq(Settings.CALL_METHOD_LIST_CONFIG),
- any(), any(Bundle.class));
+ eq(Settings.CALL_METHOD_LIST_CONFIG), any(), any(Bundle.class));
assertThat(returnedValues2).containsExactlyEntriesIn(keyValues2);
Map<String, String> cachedKeyValues = Settings.Config.getStrings(mMockContentResolver,
NAMESPACE, Collections.emptyList());
+ // Modifying the second namespace doesn't affect the cache of the first namespace
verifyNoMoreInteractions(mMockIContentProvider);
assertThat(cachedKeyValues).containsExactlyEntriesIn(keyValues);
@@ -219,17 +287,90 @@ public class NameValueCacheTest {
@Test
public void testCaching_emptyNamespace() throws Exception {
Map<String, String> returnedValues = Settings.Config.getStrings(mMockContentResolver,
- NAMESPACE,
- Collections.emptyList());
- verify(mMockIContentProvider).call(any(), any(),
- eq(Settings.CALL_METHOD_LIST_CONFIG),
- any(), any(Bundle.class));
+ NAMESPACE, Collections.emptyList());
+ verify(mMockIContentProvider, times(1)).call(any(), any(),
+ eq(Settings.CALL_METHOD_LIST_CONFIG), any(), any(Bundle.class));
assertThat(returnedValues).isEmpty();
Map<String, String> cachedKeyValues = Settings.Config.getStrings(mMockContentResolver,
NAMESPACE, Collections.emptyList());
- verifyNoMoreInteractions(mMockIContentProvider);
+ // Empty list won't be cached
+ verify(mMockIContentProvider, times(2)).call(any(), any(),
+ eq(Settings.CALL_METHOD_LIST_CONFIG), any(), any(Bundle.class));
assertThat(cachedKeyValues).isEmpty();
}
+ @Test
+ public void testCaching_singleSetting() throws Exception {
+ Settings.Secure.putString(mMockContentResolver, SETTING, "a");
+ verify(mMockIContentProvider, times(1)).call(any(), any(),
+ eq(Settings.CALL_METHOD_PUT_SECURE), any(), any(Bundle.class));
+
+ String returnedValue = Settings.Secure.getString(mMockContentResolver, SETTING);
+ verify(mMockIContentProvider, times(1)).call(any(), any(),
+ eq(Settings.CALL_METHOD_GET_SECURE), any(), any(Bundle.class));
+ assertThat(returnedValue).isEqualTo("a");
+
+ String cachedValue = Settings.Secure.getString(mMockContentResolver, SETTING);
+ verifyNoMoreInteractions(mMockIContentProvider);
+ assertThat(cachedValue).isEqualTo("a");
+
+ // Modify the value to invalidate the cache.
+ Settings.Secure.putString(mMockContentResolver, SETTING, "b");
+ verify(mMockIContentProvider, times(2)).call(any(), any(),
+ eq(Settings.CALL_METHOD_PUT_SECURE), any(), any(Bundle.class));
+
+ String returnedValue2 = Settings.Secure.getString(mMockContentResolver, SETTING);
+ verify(mMockIContentProvider, times(2)).call(any(), any(),
+ eq(Settings.CALL_METHOD_GET_SECURE), any(), any(Bundle.class));
+ assertThat(returnedValue2).isEqualTo("b");
+
+ String cachedValue2 = Settings.Secure.getString(mMockContentResolver, SETTING);
+ verifyNoMoreInteractions(mMockIContentProvider);
+ assertThat(cachedValue2).isEqualTo("b");
+ }
+
+ @Test
+ public void testCaching_multipleSettings() throws Exception {
+ Settings.Secure.putString(mMockContentResolver, SETTING, "a");
+ verify(mMockIContentProvider, times(1)).call(any(), any(),
+ eq(Settings.CALL_METHOD_PUT_SECURE), any(), any(Bundle.class));
+
+ String returnedValue = Settings.Secure.getString(mMockContentResolver, SETTING);
+ verify(mMockIContentProvider, times(1)).call(any(), any(),
+ eq(Settings.CALL_METHOD_GET_SECURE), any(), any(Bundle.class));
+ assertThat(returnedValue).isEqualTo("a");
+
+ Settings.Secure.putString(mMockContentResolver, SETTING2, "b");
+ verify(mMockIContentProvider, times(2)).call(any(), any(),
+ eq(Settings.CALL_METHOD_PUT_SECURE), any(), any(Bundle.class));
+
+ String returnedValue2 = Settings.Secure.getString(mMockContentResolver, SETTING2);
+ verify(mMockIContentProvider, times(2)).call(any(), any(),
+ eq(Settings.CALL_METHOD_GET_SECURE), any(), any(Bundle.class));
+ assertThat(returnedValue2).isEqualTo("b");
+
+ String cachedValue = Settings.Secure.getString(mMockContentResolver, SETTING);
+ // Modifying the second setting doesn't affect the cache of the first setting
+ verifyNoMoreInteractions(mMockIContentProvider);
+ assertThat(cachedValue).isEqualTo("a");
+
+ String cachedValue2 = Settings.Secure.getString(mMockContentResolver, SETTING2);
+ verifyNoMoreInteractions(mMockIContentProvider);
+ assertThat(cachedValue2).isEqualTo("b");
+ }
+
+ @Test
+ public void testCaching_nullSetting() throws Exception {
+ String returnedValue = Settings.Secure.getString(mMockContentResolver, SETTING);
+ verify(mMockIContentProvider, times(1)).call(any(), any(),
+ eq(Settings.CALL_METHOD_GET_SECURE), any(), any(Bundle.class));
+ assertThat(returnedValue).isNull();
+
+ String cachedValue = Settings.Secure.getString(mMockContentResolver, SETTING);
+ // Empty list won't be cached
+ verify(mMockIContentProvider, times(2)).call(any(), any(),
+ eq(Settings.CALL_METHOD_GET_SECURE), any(), any(Bundle.class));
+ assertThat(cachedValue).isNull();
+ }
}
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index ca1367a710ec..06920524acfc 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -248,17 +248,22 @@ public class InsetsControllerTest {
@Test
public void testSystemDrivenInsetsAnimationLoggingListener_onReady() {
+ var loggingListener = mock(WindowInsetsAnimationControlListener.class);
+
prepareControls();
// only the original thread that created view hierarchy can touch its views
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
- WindowInsetsAnimationControlListener loggingListener =
- mock(WindowInsetsAnimationControlListener.class);
mController.setSystemDrivenInsetsAnimationLoggingListener(loggingListener);
mController.getSourceConsumer(mImeSource).onWindowFocusGained(true);
// since there is no focused view, forcefully make IME visible.
mController.show(WindowInsets.Type.ime(), true /* fromIme */, null /* statsToken */);
- verify(loggingListener).onReady(notNull(), anyInt());
+ // When using the animation thread, this must not invoke onReady()
+ mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw();
});
+ // Wait for onReady() being dispatched on the animation thread.
+ InsetsAnimationThread.get().getThreadHandler().runWithScissors(() -> {}, 500);
+
+ verify(loggingListener).onReady(notNull(), anyInt());
}
@Test
diff --git a/core/tests/coretests/src/android/view/InsetsSourceTest.java b/core/tests/coretests/src/android/view/InsetsSourceTest.java
index 1db6587e1283..6fa8f1117343 100644
--- a/core/tests/coretests/src/android/view/InsetsSourceTest.java
+++ b/core/tests/coretests/src/android/view/InsetsSourceTest.java
@@ -19,6 +19,7 @@ package android.view;
import static android.view.WindowInsets.Type.FIRST;
import static android.view.WindowInsets.Type.LAST;
import static android.view.WindowInsets.Type.SIZE;
+import static android.view.WindowInsets.Type.captionBar;
import static android.view.WindowInsets.Type.ime;
import static android.view.WindowInsets.Type.navigationBars;
@@ -51,11 +52,13 @@ public class InsetsSourceTest {
private final InsetsSource mSource = new InsetsSource(0 /* id */, navigationBars());
private final InsetsSource mImeSource = new InsetsSource(1 /* id */, ime());
+ private final InsetsSource mCaptionSource = new InsetsSource(2 /* id */, captionBar());
@Before
public void setUp() {
mSource.setVisible(true);
mImeSource.setVisible(true);
+ mCaptionSource.setVisible(true);
}
@Test
@@ -107,6 +110,17 @@ public class InsetsSourceTest {
}
@Test
+ public void testCalculateInsets_caption_resizing() {
+ mCaptionSource.setFrame(new Rect(0, 0, 100, 100));
+ Insets insets = mCaptionSource.calculateInsets(new Rect(0, 0, 200, 200), false);
+ assertEquals(Insets.of(0, 100, 0, 0), insets);
+ insets = mCaptionSource.calculateInsets(new Rect(0, 0, 50, 200), false);
+ assertEquals(Insets.of(0, 100, 0, 0), insets);
+ insets = mCaptionSource.calculateInsets(new Rect(100, 100, 200, 500), false);
+ assertEquals(Insets.of(0, 100, 0, 0), insets);
+ }
+
+ @Test
public void testCalculateInsets_invisible() {
mSource.setFrame(new Rect(0, 0, 500, 100));
mSource.setVisible(false);
diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java
index b035c23cb98b..fde1a6d7b04c 100644
--- a/core/tests/coretests/src/android/view/InsetsStateTest.java
+++ b/core/tests/coretests/src/android/view/InsetsStateTest.java
@@ -248,6 +248,18 @@ public class InsetsStateTest {
}
@Test
+ public void testCalculateInsets_captionBarOffset() {
+ mState.getOrCreateSource(ID_CAPTION_BAR, captionBar())
+ .setFrame(new Rect(0, 0, 100, 300))
+ .setVisible(true);
+
+ Insets visibleInsets = mState.calculateVisibleInsets(
+ new Rect(0, 0, 150, 400), TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED,
+ SOFT_INPUT_ADJUST_NOTHING, 0 /* windowFlags */);
+ assertEquals(Insets.of(0, 300, 0, 0), visibleInsets);
+ }
+
+ @Test
public void testCalculateInsets_extraNavRightStatusTop() {
mState.getOrCreateSource(ID_STATUS_BAR, statusBars())
.setFrame(new Rect(0, 0, 100, 100))
diff --git a/core/tests/coretests/src/android/view/KeyEventTest.java b/core/tests/coretests/src/android/view/KeyEventTest.java
index 32078ca99b48..f723f15d2b26 100644
--- a/core/tests/coretests/src/android/view/KeyEventTest.java
+++ b/core/tests/coretests/src/android/view/KeyEventTest.java
@@ -47,14 +47,14 @@ public final class KeyEventTest {
private static final int ACTION = KeyEvent.ACTION_DOWN;
private static final int ANOTHER_ACTION = KeyEvent.ACTION_UP;
private static final int KEYCODE = KeyEvent.KEYCODE_0;
- private static final int REPEAT = 0;
- private static final int ANOTHER_REPEAT = 42;
- private static final int METASTATE = 0;
- private static final int DEVICE_ID = 0;
- private static final int SCAN_CODE = 0;
- private static final int FLAGS = 0;
+ private static final int REPEAT = 4;
+ private static final int ANOTHER_REPEAT = 8;
+ private static final int METASTATE = 15;
+ private static final int DEVICE_ID = 16;
+ private static final int SCAN_CODE = 23;
+ private static final int FLAGS = 42;
private static final int SOURCE = InputDevice.SOURCE_KEYBOARD;
- private static final String CHARACTERS = null;
+ private static final String CHARACTERS = "CHARACTERS, Y U NO @NONNULL?";
private static final int ID_SOURCE_MASK = 0x3 << 30;
@@ -178,7 +178,7 @@ public final class KeyEventTest {
DEVICE_ID, SCAN_CODE, FLAGS, SOURCE);
assertKeyEventFields(key, DOWN_TIME, EVENT_TIME, ACTION, KEYCODE, REPEAT, METASTATE,
- DEVICE_ID, SCAN_CODE, FLAGS, SOURCE, INVALID_DISPLAY, CHARACTERS);
+ DEVICE_ID, SCAN_CODE, FLAGS, SOURCE, INVALID_DISPLAY, /* characters= */ null);
}
@Test
@@ -187,7 +187,8 @@ public final class KeyEventTest {
DEVICE_ID, SCAN_CODE, FLAGS);
assertKeyEventFields(key, DOWN_TIME, EVENT_TIME, ACTION, KEYCODE, REPEAT, METASTATE,
- DEVICE_ID, SCAN_CODE, FLAGS, /* source= */ 0, INVALID_DISPLAY, CHARACTERS);
+ DEVICE_ID, SCAN_CODE, FLAGS, /* source= */ 0, INVALID_DISPLAY,
+ /* characters= */ null);
}
@Test
@@ -197,7 +198,7 @@ public final class KeyEventTest {
assertKeyEventFields(key, DOWN_TIME, EVENT_TIME, ACTION, KEYCODE, REPEAT, METASTATE,
DEVICE_ID, SCAN_CODE, /* flags= */ 0, /* source= */ 0, INVALID_DISPLAY,
- CHARACTERS);
+ /* characters= */ null);
}
@Test
@@ -206,7 +207,7 @@ public final class KeyEventTest {
assertKeyEventFields(key, DOWN_TIME, EVENT_TIME, ACTION, KEYCODE, REPEAT, METASTATE,
/* deviceId= */ KeyCharacterMap.VIRTUAL_KEYBOARD, /* scanCode= */ 0, /* flags= */ 0,
- /* source= */ 0, INVALID_DISPLAY, CHARACTERS);
+ /* source= */ 0, INVALID_DISPLAY, /* characters= */ null);
}
@Test
@@ -215,7 +216,8 @@ public final class KeyEventTest {
assertKeyEventFields(key, DOWN_TIME, EVENT_TIME, ACTION, KEYCODE, REPEAT,
/* metaState= */ 0, /* deviceId= */ KeyCharacterMap.VIRTUAL_KEYBOARD,
- /* scanCode= */ 0, /* flags= */ 0, /* source= */ 0, INVALID_DISPLAY, CHARACTERS);
+ /* scanCode= */ 0, /* flags= */ 0, /* source= */ 0, INVALID_DISPLAY,
+ /* characters= */ null);
}
@Test
@@ -233,8 +235,8 @@ public final class KeyEventTest {
assertKeyEventFields(key, /* downTime= */ 0, /* eventTime= */ 0, ACTION, KEYCODE,
/* repeat= */ 0, /* metaState= */ 0,
- /* deviceId= */ KeyCharacterMap.VIRTUAL_KEYBOARD, /* scanCode= */ 0, FLAGS,
- /* source= */ 0, INVALID_DISPLAY, CHARACTERS);
+ /* deviceId= */ KeyCharacterMap.VIRTUAL_KEYBOARD, /* scanCode= */ 0, /* flags= */ 0,
+ /* source= */ 0, INVALID_DISPLAY, /* characters= */ null);
}
@Test
@@ -244,7 +246,7 @@ public final class KeyEventTest {
assertKeyEventFields(key2, DOWN_TIME, EVENT_TIME, ANOTHER_ACTION, KEYCODE, REPEAT,
METASTATE, DEVICE_ID, SCAN_CODE, FLAGS, InputDevice.SOURCE_KEYBOARD,
- INVALID_DISPLAY, CHARACTERS);
+ INVALID_DISPLAY, /* characters= */ null);
expect.withMessage("id (key1=%s, key2=%s", key1, key2).that(key2.getId())
.isNotEqualTo(key1.getId());
}
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
index 6d635af20645..3d4918b1bd42 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
@@ -58,7 +58,7 @@ public class AccessibilityNodeInfoTest {
// The number of flags held in boolean properties. Their values should also be double-checked
// in the methods above.
- private static final int NUM_BOOLEAN_PROPERTIES = 26;
+ private static final int NUM_BOOLEAN_PROPERTIES = 27;
@Test
public void testStandardActions_serializationFlagIsValid() {
diff --git a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java
index eae1bbc930d4..17ed4c478350 100644
--- a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java
+++ b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java
@@ -15,6 +15,8 @@
*/
package android.view.contentcapture;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.Mockito.mock;
import static org.testng.Assert.assertThrows;
@@ -54,4 +56,19 @@ public class ContentCaptureManagerTest {
assertThrows(NullPointerException.class, () -> manager.removeData(null));
}
+
+ @Test
+ @SuppressWarnings("GuardedBy")
+ public void testFlushViewTreeAppearingEventDisabled_setAndGet() {
+ final IContentCaptureManager mockService = mock(IContentCaptureManager.class);
+ final ContentCaptureOptions options = new ContentCaptureOptions(null);
+ final ContentCaptureManager manager =
+ new ContentCaptureManager(mMockContext, mockService, options);
+
+ assertThat(manager.getFlushViewTreeAppearingEventDisabled()).isFalse();
+ manager.setFlushViewTreeAppearingEventDisabled(true);
+ assertThat(manager.getFlushViewTreeAppearingEventDisabled()).isTrue();
+ manager.setFlushViewTreeAppearingEventDisabled(false);
+ assertThat(manager.getFlushViewTreeAppearingEventDisabled()).isFalse();
+ }
}
diff --git a/core/tests/coretests/src/android/view/stylus/HandwritingInitiatorTest.java b/core/tests/coretests/src/android/view/stylus/HandwritingInitiatorTest.java
index 95aa5d0de119..76f5277cfe0b 100644
--- a/core/tests/coretests/src/android/view/stylus/HandwritingInitiatorTest.java
+++ b/core/tests/coretests/src/android/view/stylus/HandwritingInitiatorTest.java
@@ -32,7 +32,6 @@ import android.app.Instrumentation;
import android.content.Context;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
-import android.view.HandwritingDelegateConfiguration;
import android.view.HandwritingInitiator;
import android.view.InputDevice;
import android.view.MotionEvent;
@@ -210,14 +209,11 @@ public class HandwritingInitiatorTest {
@Test
public void onTouchEvent_startHandwriting_delegate() {
- int delegatorViewId = 234;
- View delegatorView = new View(mContext);
- delegatorView.setId(delegatorViewId);
+ View delegateView = new View(mContext);
+ delegateView.setIsHandwritingDelegate(true);
- mTestView.setHandwritingDelegateConfiguration(
- new HandwritingDelegateConfiguration(
- delegatorViewId,
- () -> mHandwritingInitiator.onInputConnectionCreated(delegatorView)));
+ mTestView.setHandwritingDelegatorCallback(
+ () -> mHandwritingInitiator.onInputConnectionCreated(delegateView));
final int x1 = (sHwArea.left + sHwArea.right) / 2;
final int y1 = (sHwArea.top + sHwArea.bottom) / 2;
@@ -229,7 +225,7 @@ public class HandwritingInitiatorTest {
MotionEvent stylusEvent2 = createStylusEvent(ACTION_MOVE, x2, y2, 0);
mHandwritingInitiator.onTouchEvent(stylusEvent2);
- verify(mHandwritingInitiator, times(1)).startHandwriting(delegatorView);
+ verify(mHandwritingInitiator, times(1)).tryAcceptStylusHandwritingDelegation(delegateView);
}
@Test
diff --git a/core/tests/coretests/src/android/widget/TextViewContextMenuTest.java b/core/tests/coretests/src/android/widget/TextViewContextMenuTest.java
index 0c7550e79cfa..777246b83a57 100644
--- a/core/tests/coretests/src/android/widget/TextViewContextMenuTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewContextMenuTest.java
@@ -33,6 +33,8 @@ import android.app.Activity;
import android.app.PendingIntent;
import android.app.RemoteAction;
import android.content.Intent;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.Icon;
import android.view.ContextMenu;
import android.view.MenuItem;
@@ -167,4 +169,75 @@ public class TextViewContextMenuTest {
assertThat(idCaptor.getValue()).isEqualTo(TextView.ID_ASSIST);
assertThat(titleCaptor.getValue().toString()).isEqualTo(ACTION_TITLE);
}
+
+ @UiThreadTest
+ @Test
+ public void testAdjustIconSpaces() {
+ GradientDrawable gd = new GradientDrawable();
+ gd.setSize(128, 256);
+
+ // Setup mocks
+ ContextMenu menu = mock(ContextMenu.class);
+
+ MenuItem mockIconMenu = newMockMenuItem();
+ when(mockIconMenu.getIcon()).thenReturn(gd);
+
+ MenuItem mockNoIconMenu = newMockMenuItem();
+ when(mockNoIconMenu.getIcon()).thenReturn(null);
+
+ MenuItem mockNoIconMenu2 = newMockMenuItem();
+ when(mockNoIconMenu2.getIcon()).thenReturn(null);
+
+ when(menu.size()).thenReturn(3);
+ when(menu.getItem(0)).thenReturn(mockIconMenu);
+ when(menu.getItem(1)).thenReturn(mockNoIconMenu);
+ when(menu.getItem(2)).thenReturn(mockNoIconMenu2);
+
+
+ // Execute the test method
+ EditText et = mActivity.findViewById(R.id.editText);
+ Editor editor = et.getEditorForTesting();
+ editor.adjustIconSpacing(menu);
+
+ // Verify
+ ArgumentCaptor<Drawable> drawableCaptor = ArgumentCaptor.forClass(Drawable.class);
+ verify(mockNoIconMenu).setIcon(drawableCaptor.capture());
+
+ Drawable paddingDrawable = drawableCaptor.getValue();
+ assertThat(paddingDrawable).isNotNull();
+ assertThat(paddingDrawable.getIntrinsicWidth()).isEqualTo(128);
+ assertThat(paddingDrawable.getIntrinsicHeight()).isEqualTo(256);
+
+ ArgumentCaptor<Drawable> drawableCaptor2 = ArgumentCaptor.forClass(Drawable.class);
+ verify(mockNoIconMenu2).setIcon(drawableCaptor2.capture());
+
+ Drawable paddingDrawable2 = drawableCaptor2.getValue();
+ assertThat(paddingDrawable2).isSameInstanceAs(paddingDrawable);
+ }
+
+ @UiThreadTest
+ @Test
+ public void testAdjustIconSpacesNoIconCase() {
+ // Setup mocks
+ ContextMenu menu = mock(ContextMenu.class);
+
+ MenuItem mockNoIconMenu = newMockMenuItem();
+ when(mockNoIconMenu.getIcon()).thenReturn(null);
+
+ MenuItem mockNoIconMenu2 = newMockMenuItem();
+ when(mockNoIconMenu2.getIcon()).thenReturn(null);
+
+ when(menu.size()).thenReturn(2);
+ when(menu.getItem(0)).thenReturn(mockNoIconMenu);
+ when(menu.getItem(1)).thenReturn(mockNoIconMenu2);
+
+ // Execute the test method
+ EditText et = mActivity.findViewById(R.id.editText);
+ Editor editor = et.getEditorForTesting();
+ editor.adjustIconSpacing(menu);
+
+ // Verify
+ verify(mockNoIconMenu, times(0)).setIcon(any());
+ verify(mockNoIconMenu2, times(0)).setIcon(any());
+ }
}
diff --git a/core/tests/coretests/src/com/android/internal/os/SafeZipPathValidatorCallbackTest.java b/core/tests/coretests/src/com/android/internal/os/SafeZipPathValidatorCallbackTest.java
deleted file mode 100644
index c540a150bf35..000000000000
--- a/core/tests/coretests/src/com/android/internal/os/SafeZipPathValidatorCallbackTest.java
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.os;
-
-import static org.junit.Assert.assertThrows;
-
-import android.compat.testing.PlatformCompatChangeRule;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
-import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TestRule;
-import org.junit.runner.RunWith;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipException;
-import java.util.zip.ZipFile;
-import java.util.zip.ZipInputStream;
-import java.util.zip.ZipOutputStream;
-
-/**
- * Test SafeZipPathCallback.
- */
-@RunWith(AndroidJUnit4.class)
-public class SafeZipPathValidatorCallbackTest {
- @Rule
- public TestRule mCompatChangeRule = new PlatformCompatChangeRule();
-
- @Before
- public void setUp() {
- RuntimeInit.initZipPathValidatorCallback();
- }
-
- @Test
- @EnableCompatChanges({SafeZipPathValidatorCallback.VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL})
- public void testNewZipFile_whenZipFileHasDangerousEntriesAndChangeEnabled_throws()
- throws Exception {
- final String[] dangerousEntryNames = {
- "../foo.bar",
- "foo/../bar.baz",
- "foo/../../bar.baz",
- "foo.bar/..",
- "foo.bar/../",
- "..",
- "../",
- "/foo",
- };
- for (String entryName : dangerousEntryNames) {
- final File tempFile = File.createTempFile("smdc", "zip");
- try {
- writeZipFileOutputStreamWithEmptyEntry(tempFile, entryName);
-
- assertThrows(
- "ZipException expected for entry: " + entryName,
- ZipException.class,
- () -> {
- new ZipFile(tempFile);
- });
- } finally {
- tempFile.delete();
- }
- }
- }
-
- @Test
- @EnableCompatChanges({SafeZipPathValidatorCallback.VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL})
- public void
- testZipInputStreamGetNextEntry_whenZipFileHasDangerousEntriesAndChangeEnabled_throws()
- throws Exception {
- final String[] dangerousEntryNames = {
- "../foo.bar",
- "foo/../bar.baz",
- "foo/../../bar.baz",
- "foo.bar/..",
- "foo.bar/../",
- "..",
- "../",
- "/foo",
- };
- for (String entryName : dangerousEntryNames) {
- byte[] badZipBytes = getZipBytesFromZipOutputStreamWithEmptyEntry(entryName);
- try (ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(badZipBytes))) {
- assertThrows(
- "ZipException expected for entry: " + entryName,
- ZipException.class,
- () -> {
- zis.getNextEntry();
- });
- }
- }
- }
-
- @Test
- @EnableCompatChanges({SafeZipPathValidatorCallback.VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL})
- public void testNewZipFile_whenZipFileHasNormalEntriesAndChangeEnabled_doesNotThrow()
- throws Exception {
- final String[] normalEntryNames = {
- "foo", "foo.bar", "foo..bar",
- };
- for (String entryName : normalEntryNames) {
- final File tempFile = File.createTempFile("smdc", "zip");
- try {
- writeZipFileOutputStreamWithEmptyEntry(tempFile, entryName);
- try {
- new ZipFile((tempFile));
- } catch (ZipException e) {
- throw new AssertionError("ZipException not expected for entry: " + entryName);
- }
- } finally {
- tempFile.delete();
- }
- }
- }
-
- @Test
- @DisableCompatChanges({SafeZipPathValidatorCallback.VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL})
- public void
- testZipInputStreamGetNextEntry_whenZipFileHasNormalEntriesAndChangeEnabled_doesNotThrow()
- throws Exception {
- final String[] normalEntryNames = {
- "foo", "foo.bar", "foo..bar",
- };
- for (String entryName : normalEntryNames) {
- byte[] zipBytes = getZipBytesFromZipOutputStreamWithEmptyEntry(entryName);
- try {
- ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(zipBytes));
- zis.getNextEntry();
- } catch (ZipException e) {
- throw new AssertionError("ZipException not expected for entry: " + entryName);
- }
- }
- }
-
- @Test
- @DisableCompatChanges({SafeZipPathValidatorCallback.VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL})
- public void
- testNewZipFile_whenZipFileHasNormalAndDangerousEntriesAndChangeDisabled_doesNotThrow()
- throws Exception {
- final String[] entryNames = {
- "../foo.bar",
- "foo/../bar.baz",
- "foo/../../bar.baz",
- "foo.bar/..",
- "foo.bar/../",
- "..",
- "../",
- "/foo",
- "foo",
- "foo.bar",
- "foo..bar",
- };
- for (String entryName : entryNames) {
- final File tempFile = File.createTempFile("smdc", "zip");
- try {
- writeZipFileOutputStreamWithEmptyEntry(tempFile, entryName);
- try {
- new ZipFile((tempFile));
- } catch (ZipException e) {
- throw new AssertionError("ZipException not expected for entry: " + entryName);
- }
- } finally {
- tempFile.delete();
- }
- }
- }
-
- @Test
- @DisableCompatChanges({SafeZipPathValidatorCallback.VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL})
- public void
- testZipInputStreamGetNextEntry_whenZipFileHasNormalAndDangerousEntriesAndChangeDisabled_doesNotThrow()
- throws Exception {
- final String[] entryNames = {
- "../foo.bar",
- "foo/../bar.baz",
- "foo/../../bar.baz",
- "foo.bar/..",
- "foo.bar/../",
- "..",
- "../",
- "/foo",
- "foo",
- "foo.bar",
- "foo..bar",
- };
- for (String entryName : entryNames) {
- byte[] zipBytes = getZipBytesFromZipOutputStreamWithEmptyEntry(entryName);
- try {
- ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(zipBytes));
- zis.getNextEntry();
- } catch (ZipException e) {
- throw new AssertionError("ZipException not expected for entry: " + entryName);
- }
- }
- }
-
- private void writeZipFileOutputStreamWithEmptyEntry(File tempFile, String entryName)
- throws IOException {
- FileOutputStream tempFileStream = new FileOutputStream(tempFile);
- writeZipOutputStreamWithEmptyEntry(tempFileStream, entryName);
- tempFileStream.close();
- }
-
- private byte[] getZipBytesFromZipOutputStreamWithEmptyEntry(String entryName)
- throws IOException {
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- writeZipOutputStreamWithEmptyEntry(bos, entryName);
- return bos.toByteArray();
- }
-
- private void writeZipOutputStreamWithEmptyEntry(OutputStream os, String entryName)
- throws IOException {
- ZipOutputStream zos = new ZipOutputStream(os);
- ZipEntry entry = new ZipEntry(entryName);
- zos.putNextEntry(entry);
- zos.write(new byte[2]);
- zos.closeEntry();
- zos.close();
- }
-}
diff --git a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
index 539eb6253f4d..be2c27de637c 100644
--- a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
+++ b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
@@ -51,6 +51,7 @@ import android.app.ActivityThread.ActivityClientRecord;
import android.app.LoadedApk;
import android.app.servertransaction.PendingTransactionActions;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
@@ -293,7 +294,7 @@ public class ActivityThreadClientTest {
private Activity launchActivity(ActivityClientRecord r) {
return mThread.handleLaunchActivity(r, null /* pendingActions */,
- null /* customIntent */);
+ Context.DEVICE_ID_DEFAULT, null /* customIntent */);
}
private void startActivity(ActivityClientRecord r) {
@@ -347,7 +348,7 @@ public class ActivityThreadClientTest {
doNothing().when(packageInfo).updateApplicationInfo(any(), any());
return new ActivityClientRecord(mock(IBinder.class), Intent.makeMainActivity(component),
- 0 /* ident */, info, new Configuration(), 0 /*deviceId */, null /* referrer */,
+ 0 /* ident */, info, new Configuration(), null /* referrer */,
null /* voiceInteractor */, null /* state */, null /* persistentState */,
null /* pendingResults */, null /* pendingNewIntents */,
null /* activityOptions */, true /* isForward */, null /* profilerInfo */,
diff --git a/core/tests/mockingcoretests/src/android/view/DisplayTest.java b/core/tests/mockingcoretests/src/android/view/DisplayTest.java
index 9ccf3b3c9d05..3b8b8c797241 100644
--- a/core/tests/mockingcoretests/src/android/view/DisplayTest.java
+++ b/core/tests/mockingcoretests/src/android/view/DisplayTest.java
@@ -117,6 +117,31 @@ public class DisplayTest {
}
@Test
+ public void testGetReportedHdrTypes_returns_mode_specific_hdr_types() {
+ setDisplayInfoPortrait(mDisplayInfo);
+ float[] alternativeRefreshRates = new float[0];
+ int[] hdrTypesWithDv = new int[] {1, 2, 3, 4};
+ Display.Mode modeWithDv = new Display.Mode(/* modeId= */ 0, 0, 0, 0f,
+ alternativeRefreshRates, hdrTypesWithDv);
+
+ int[] hdrTypesWithoutDv = new int[]{2, 3, 4};
+ Display.Mode modeWithoutDv = new Display.Mode(/* modeId= */ 1, 0, 0, 0f,
+ alternativeRefreshRates, hdrTypesWithoutDv);
+
+ mDisplayInfo.supportedModes = new Display.Mode[] {modeWithoutDv, modeWithDv};
+ mDisplayInfo.hdrCapabilities = new Display.HdrCapabilities(hdrTypesWithDv, 0, 0, 0);
+
+ final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo,
+ DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
+
+ mDisplayInfo.modeId = 0;
+ assertArrayEquals(hdrTypesWithDv, display.getReportedHdrTypes());
+
+ mDisplayInfo.modeId = 1;
+ assertArrayEquals(hdrTypesWithoutDv, display.getReportedHdrTypes());
+ }
+
+ @Test
public void testConstructor_defaultDisplayAdjustments_matchesDisplayInfo() {
setDisplayInfoPortrait(mDisplayInfo);
final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo,
diff --git a/core/tests/overlaytests/device/Android.bp b/core/tests/overlaytests/device/Android.bp
index 0d3b15a41e8c..2b22344a4ef2 100644
--- a/core/tests/overlaytests/device/Android.bp
+++ b/core/tests/overlaytests/device/Android.bp
@@ -29,6 +29,7 @@ android_test {
static_libs: [
"androidx.test.rules",
"testng",
+ "compatibility-device-util-axt",
],
test_suites: ["device-tests"],
data: [
diff --git a/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java b/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java
index 8e4b9efafccd..fcf71ed39ef5 100644
--- a/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java
+++ b/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java
@@ -37,10 +37,12 @@ import android.view.View;
import androidx.test.InstrumentationRegistry;
+import com.android.compatibility.common.util.AmUtils;
import com.android.internal.util.ArrayUtils;
import com.android.overlaytest.view.TestTextView;
import org.junit.Before;
+import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
@@ -70,6 +72,13 @@ public abstract class OverlayBaseTest {
mMode = mode;
}
+ @BeforeClass
+ public static void setUpClass() {
+ // Wait for package_added broadcasts to be handled so that OverlayManagerService
+ // can update it's internal state with the new packages.
+ AmUtils.waitForBroadcastBarrier();
+ }
+
@Before
public void setUp() {
mContext = InstrumentationRegistry.getContext();
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 71050fa8b233..5cb5ffa03e00 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -122,6 +122,7 @@ applications that come with the platform
<permission name="android.permission.BIND_CARRIER_SERVICES"/>
<permission name="android.permission.BIND_CELL_BROADCAST_SERVICE"/>
<permission name="android.permission.BIND_IMS_SERVICE"/>
+ <permission name="android.permission.BIND_SATELLITE_SERVICE"/>
<permission name="android.permission.BIND_TELEPHONY_DATA_SERVICE"/>
<permission name="android.permission.BIND_VISUAL_VOICEMAIL_SERVICE"/>
<permission name="android.permission.CALL_PRIVILEGED"/>
@@ -470,7 +471,7 @@ applications that come with the platform
<permission name="android.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED"/>
<!-- Permission required for CTS test - CallAudioInterceptionTest -->
<permission name="android.permission.CALL_AUDIO_INTERCEPTION"/>
- <!-- Permission required for CTS test - CtsPermission5TestCases -->
+ <!-- Permission required for CTS test - CtsAttributionSourceTestCases -->
<permission name="android.permission.RENOUNCE_PERMISSIONS" />
<permission name="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS" />
<permission name="android.permission.GET_PROCESS_STATE_AND_OOM_SCORE" />
@@ -508,6 +509,8 @@ applications that come with the platform
<permission name="android.permission.ACCESS_AMBIENT_CONTEXT_EVENT"/>
<!-- Permission required for CTS test - CtsTelephonyProviderTestCases -->
<permission name="android.permission.WRITE_APN_SETTINGS"/>
+ <!-- Permission required for GTS test - GtsStatsdHostTestCases -->
+ <permission name="android.permission.READ_RESTRICTED_STATS"/>
</privapp-permissions>
<privapp-permissions package="com.android.statementservice">
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 3d81d37aff20..913eaf2391f6 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -271,6 +271,12 @@
"group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
"at": "com\/android\/server\/wm\/AppTransition.java"
},
+ "-1868518158": {
+ "message": "Pending back animation due to another animation is running",
+ "level": "WARN",
+ "group": "WM_DEBUG_BACK_PREVIEW",
+ "at": "com\/android\/server\/wm\/BackNavigationController.java"
+ },
"-1868124841": {
"message": "screenOnEarly=%b, awake=%b, currentAppOrientation=%d, orientationSensorEnabled=%b, keyguardDrawComplete=%b, windowManagerDrawComplete=%b",
"level": "VERBOSE",
@@ -1291,6 +1297,12 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "-894942237": {
+ "message": "Force Playing Transition: %d",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_WINDOW_TRANSITIONS",
+ "at": "com\/android\/server\/wm\/Transition.java"
+ },
"-883738232": {
"message": "Adding more than one toast window for UID at a time.",
"level": "WARN",
@@ -1549,6 +1561,12 @@
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/DragState.java"
},
+ "-692907078": {
+ "message": "Handling the deferred animation after transition finished",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_BACK_PREVIEW",
+ "at": "com\/android\/server\/wm\/BackNavigationController.java"
+ },
"-677449371": {
"message": "moveTaskToRootTask: moving task=%d to rootTaskId=%d toTop=%b",
"level": "DEBUG",
@@ -4231,12 +4249,6 @@
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/DisplayContent.java"
},
- "1878927091": {
- "message": "prepareSurface: No changes in animation for %s",
- "level": "VERBOSE",
- "group": "WM_DEBUG_ANIM",
- "at": "com\/android\/server\/wm\/WindowStateAnimator.java"
- },
"1891501279": {
"message": "cancelAnimation(): reason=%s",
"level": "DEBUG",
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index a39dd0853ca6..8dd23b70ae61 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -2001,7 +2001,7 @@ public final class Bitmap implements Parcelable {
checkPixelAccess(x, y);
final ColorSpace cs = getColorSpace();
- if (cs.equals(ColorSpace.get(ColorSpace.Named.SRGB))) {
+ if (cs == null || cs.equals(ColorSpace.get(ColorSpace.Named.SRGB))) {
return Color.valueOf(nativeGetPixel(mNativePtr, x, y));
}
// The returned value is in kRGBA_F16_SkColorType, which is packed as
diff --git a/graphics/java/android/graphics/Color.java b/graphics/java/android/graphics/Color.java
index 87a805379b56..0f2f8797b896 100644
--- a/graphics/java/android/graphics/Color.java
+++ b/graphics/java/android/graphics/Color.java
@@ -767,7 +767,7 @@ public class Color {
* Returns the alpha component encoded in the specified color long.
* The returned value is always in the range \([0..1]\).
*
- * @param color The color long whose blue channel to extract
+ * @param color The color long whose alpha channel to extract
* @return A float value in the range \([0..1]\)
*
* @see #colorSpace(long)
diff --git a/graphics/java/android/graphics/Gainmap.java b/graphics/java/android/graphics/Gainmap.java
index a7c508c75ac9..feedb7d3e2bf 100644
--- a/graphics/java/android/graphics/Gainmap.java
+++ b/graphics/java/android/graphics/Gainmap.java
@@ -63,20 +63,20 @@ import libcore.util.NativeAllocationRegistry;
* as follows:
*
* First, let W be a weight parameter determining how much the gainmap will be applied.
- * W = clamp((log(H) - log(displayRatioHdr)) /
- * (log(displayRatioHdr) - log(displayRatioSdr), 0, 1)
+ * W = clamp((log(H) - log(minDisplayRatioForHdrTransition)) /
+ * (log(displayRatioForFullHdr) - log(minDisplayRatioForHdrTransition), 0, 1)
*
* Next, let L be the gainmap value in log space. We compute this from the value G that was
* sampled from the texture as follows:
- * L = mix(log(gainmapRatioMin), log(gainmapRatioMax), pow(G, gainmapGamma))
+ * L = mix(log(ratioMin), log(ratioMax), pow(G, gamma))
*
* Finally, apply the gainmap to compute D, the displayed pixel. If the base image is SDR then
* compute:
* D = (B + epsilonSdr) * exp(L * W) - epsilonHdr
- * If the base image is HDR then compute:
- * D = (B + epsilonHdr) * exp(L * (W - 1)) - epsilonSdr
*
- * In the above math, log() is a natural logarithm and exp() is natural exponentiation.
+ * In the above math, log() is a natural logarithm and exp() is natural exponentiation. The base
+ * for these functions cancels out and does not affect the result, so other bases may be used
+ * if preferred.
*/
public final class Gainmap implements Parcelable {
diff --git a/graphics/java/android/graphics/Mesh.java b/graphics/java/android/graphics/Mesh.java
index 6a1313e16ce5..66fabec91924 100644
--- a/graphics/java/android/graphics/Mesh.java
+++ b/graphics/java/android/graphics/Mesh.java
@@ -341,7 +341,6 @@ public class Mesh {
* @hide so only calls from module can utilize it
*/
long getNativeWrapperInstance() {
- nativeUpdateMesh(mNativeMeshWrapper, mIsIndexed);
return mNativeMeshWrapper;
}
@@ -383,5 +382,4 @@ public class Mesh {
private static native void nativeUpdateUniforms(long builder, String uniformName, int[] values);
- private static native void nativeUpdateMesh(long nativeMeshWrapper, boolean mIsIndexed);
}
diff --git a/graphics/java/android/graphics/text/GraphemeBreak.java b/graphics/java/android/graphics/text/GraphemeBreak.java
new file mode 100644
index 000000000000..f82b2fd659cc
--- /dev/null
+++ b/graphics/java/android/graphics/text/GraphemeBreak.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.text;
+
+/** @hide */
+public class GraphemeBreak {
+ private GraphemeBreak() { }
+
+ /**
+ * Util method that checks if the offsets in given range are grapheme break.
+ *
+ * @param advances the advances of characters in the given text. It contains the font
+ * information used by the algorithm to determine the grapheme break. It's useful
+ * when some character is missing in the font. For example, if the smile emoji
+ * "0xD83D 0xDE0A" is not found in the font and is displayed as 2 characters.
+ * We can't treat it as a single grapheme cluster.
+ * @param text the text to be processed.
+ * @param start the start offset of the queried range, inclusive.
+ * @param end the end offset of the queried range, exclusive.
+ * @param isGraphemeBreak the array to receive the result. The i-th element of the
+ * array will be set to true if the offset (start + i) is a grapheme
+ * break; otherwise, it will be set to false.
+ */
+ public static void isGraphemeBreak(float[] advances, char[] text, int start, int end,
+ boolean[] isGraphemeBreak) {
+ if (start > end) {
+ throw new IllegalArgumentException("start is greater than end: start = " + start
+ + " end = " + end);
+ }
+ if (advances.length < end) {
+ throw new IllegalArgumentException("the length of advances is less than end"
+ + "advances.length = " + advances.length
+ + " end = " + end);
+ }
+ if (isGraphemeBreak.length < end - start) {
+ throw new IndexOutOfBoundsException("isGraphemeBreak doesn't have enough space to "
+ + "receive the result, isGraphemeBreak.length: " + isGraphemeBreak.length
+ + " needed space: " + (end - start));
+ }
+ nIsGraphemeBreak(advances, text, start, end, isGraphemeBreak);
+ }
+
+ private static native void nIsGraphemeBreak(float[] advances, char[] text, int start, int end,
+ boolean[] isGraphemeBreak);
+}
diff --git a/graphics/java/android/graphics/text/LineBreaker.java b/graphics/java/android/graphics/text/LineBreaker.java
index 67eb117cb17c..babcfc3815f4 100644
--- a/graphics/java/android/graphics/text/LineBreaker.java
+++ b/graphics/java/android/graphics/text/LineBreaker.java
@@ -22,7 +22,6 @@ import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Px;
-import android.os.Trace;
import dalvik.annotation.optimization.CriticalNative;
import dalvik.annotation.optimization.FastNative;
@@ -476,26 +475,19 @@ public class LineBreaker {
@NonNull MeasuredText measuredPara,
@NonNull ParagraphConstraints constraints,
@IntRange(from = 0) int lineNumber) {
- Trace.traceBegin(Trace.TRACE_TAG_VIEW, "compute line break");
- long result = 0;
- try {
- result = nComputeLineBreaks(
- mNativePtr,
-
- // Inputs
- measuredPara.getChars(),
- measuredPara.getNativePtr(),
- measuredPara.getChars().length,
- constraints.mFirstWidth,
- constraints.mFirstWidthLineCount,
- constraints.mWidth,
- constraints.mVariableTabStops,
- constraints.mDefaultTabStop,
- lineNumber);
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_VIEW);
- }
- return new Result(result);
+ return new Result(nComputeLineBreaks(
+ mNativePtr,
+
+ // Inputs
+ measuredPara.getChars(),
+ measuredPara.getNativePtr(),
+ measuredPara.getChars().length,
+ constraints.mFirstWidth,
+ constraints.mFirstWidthLineCount,
+ constraints.mWidth,
+ constraints.mVariableTabStops,
+ constraints.mDefaultTabStop,
+ lineNumber));
}
@FastNative
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index 9f3c19b2b545..caefb2e9516c 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -752,8 +752,6 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
@GuardedBy("mLock")
void onActivityCreated(@NonNull WindowContainerTransaction wct,
@NonNull Activity launchedActivity) {
- // TODO(b/229680885): we don't support launching into primary yet because we want to always
- // launch the new activity on top.
resolveActivityToContainer(wct, launchedActivity, false /* isOnReparent */);
updateCallbackIfNecessary();
}
@@ -789,6 +787,13 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
return true;
}
+ final TaskFragmentContainer container = getContainerWithActivity(activity);
+ if (!isOnReparent && container != null
+ && container.getTaskContainer().getTopTaskFragmentContainer() != container) {
+ // Do not resolve if the launched activity is not the top-most container in the Task.
+ return true;
+ }
+
/*
* We will check the following to see if there is any embedding rule matched:
* 1. Whether the new launched activity should always expand.
@@ -811,6 +816,13 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
return true;
}
+ // Skip resolving the following split-rules if the launched activity has been requested
+ // to be launched into its current container.
+ if (container != null && container.isActivityInRequestedTaskFragment(
+ activity.getActivityToken())) {
+ return true;
+ }
+
// 3. Whether the new launched activity has already been in a split with a rule matched.
if (isNewActivityInSplitWithRuleMatched(activity)) {
return true;
@@ -2066,6 +2078,12 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
if (!container.hasActivity(activityToken)
&& container.getTaskFragmentToken()
.equals(initialTaskFragmentToken)) {
+ if (ActivityClient.getInstance().isRequestedToLaunchInTaskFragment(
+ activityToken, initialTaskFragmentToken)) {
+ container.addPendingAppearedInRequestedTaskFragmentActivity(
+ activity);
+ }
+
// The onTaskFragmentInfoChanged callback containing this activity has
// not reached the client yet, so add the activity to the pending
// appeared activities.
@@ -2157,6 +2175,14 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
// TODO(b/232042367): Consolidate the activity create handling so that we can handle
// cross-process the same as normal.
+ // Early return if the launching taskfragment is already been set.
+ if (options.getBinder(ActivityOptions.KEY_LAUNCH_TASK_FRAGMENT_TOKEN) != null) {
+ synchronized (mLock) {
+ mCurrentIntent = intent;
+ }
+ return super.onStartActivity(who, intent, options);
+ }
+
final Activity launchingActivity;
if (who instanceof Activity) {
// We will check if the new activity should be split with the activity that launched
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
index b38f8245a2aa..6c553a836dbd 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
@@ -86,6 +86,12 @@ class TaskFragmentContainer {
@Nullable
private Intent mPendingAppearedIntent;
+ /**
+ * The activities that were explicitly requested to be launched in its current TaskFragment,
+ * but haven't been added to {@link #mInfo} yet.
+ */
+ final ArrayList<IBinder> mPendingAppearedInRequestedTaskFragmentActivities = new ArrayList<>();
+
/** Containers that are dependent on this one and should be completely destroyed on exit. */
private final List<TaskFragmentContainer> mContainersToFinishOnExit =
new ArrayList<>();
@@ -296,6 +302,8 @@ class TaskFragmentContainer {
void removePendingAppearedActivity(@NonNull IBinder activityToken) {
mPendingAppearedActivities.remove(activityToken);
+ // Also remove the activity from the mPendingInRequestedTaskFragmentActivities.
+ mPendingAppearedInRequestedTaskFragmentActivities.remove(activityToken);
}
@GuardedBy("mController.mLock")
@@ -424,7 +432,7 @@ class TaskFragmentContainer {
for (int i = mPendingAppearedActivities.size() - 1; i >= 0; --i) {
final IBinder activityToken = mPendingAppearedActivities.get(i);
if (infoActivities.contains(activityToken)) {
- mPendingAppearedActivities.remove(i);
+ removePendingAppearedActivity(activityToken);
}
}
}
@@ -720,6 +728,29 @@ class TaskFragmentContainer {
mLastCompanionTaskFragment = fragmentToken;
}
+ /**
+ * Adds the pending appeared activity that has requested to be launched in this task fragment.
+ * @see android.app.ActivityClient#isRequestedToLaunchInTaskFragment
+ */
+ void addPendingAppearedInRequestedTaskFragmentActivity(Activity activity) {
+ final IBinder activityToken = activity.getActivityToken();
+ if (hasActivity(activityToken)) {
+ return;
+ }
+ mPendingAppearedInRequestedTaskFragmentActivities.add(activity.getActivityToken());
+ }
+
+ /**
+ * Checks if the given activity has requested to be launched in this task fragment.
+ * @see #addPendingAppearedInRequestedTaskFragmentActivity
+ */
+ boolean isActivityInRequestedTaskFragment(IBinder activityToken) {
+ if (mInfo != null && mInfo.getActivitiesRequestedInTaskFragment().contains(activityToken)) {
+ return true;
+ }
+ return mPendingAppearedInRequestedTaskFragmentActivities.contains(activityToken);
+ }
+
/** Gets the parent leaf Task id. */
int getTaskId() {
return mTaskContainer.getTaskId();
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java
index 459ec9f89c4a..a069ac7256d6 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java
@@ -177,6 +177,7 @@ public class EmbeddingTestUtils {
1,
isVisible,
Collections.singletonList(activity.getActivityToken()),
+ new ArrayList<>(),
new Point(),
false /* isTaskClearedForReuse */,
false /* isTaskFragmentClearedForPip */,
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
index bbb454d31c38..dd087e8eb7c9 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
@@ -124,7 +124,7 @@ public class JetpackTaskFragmentOrganizerTest {
private TaskFragmentInfo createMockInfo(TaskFragmentContainer container) {
return new TaskFragmentInfo(container.getTaskFragmentToken(),
mock(WindowContainerToken.class), new Configuration(), 0 /* runningActivityCount */,
- false /* isVisible */, new ArrayList<>(), new Point(),
+ false /* isVisible */, new ArrayList<>(), new ArrayList<>(), new Point(),
false /* isTaskClearedForReuse */, false /* isTaskFragmentClearedForPip */,
false /* isClearedForReorderActivityToFront */, new Point());
}
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
index 61cd7485ff1d..3d0e1c8cf788 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
@@ -700,7 +700,7 @@ public class SplitControllerTest {
final boolean result = mSplitController.resolveActivityToContainer(mTransaction, mActivity,
false /* isOnReparent */);
- assertFalse(result);
+ assertTrue(result);
verify(mSplitPresenter, never()).startActivityToSide(any(), any(), any(), any(), any(),
any(), anyBoolean());
}
@@ -734,7 +734,7 @@ public class SplitControllerTest {
final boolean result = mSplitController.resolveActivityToContainer(mTransaction, mActivity,
false /* isOnReparent */);
- assertFalse(result);
+ assertTrue(result);
verify(mSplitPresenter, never()).startActivityToSide(any(), any(), any(), any(), any(),
any(), anyBoolean());
}
@@ -808,7 +808,7 @@ public class SplitControllerTest {
final Activity launchedActivity = createMockActivity();
primaryContainer.addPendingAppearedActivity(launchedActivity);
- assertFalse(mSplitController.resolveActivityToContainer(mTransaction, launchedActivity,
+ assertTrue(mSplitController.resolveActivityToContainer(mTransaction, launchedActivity,
false /* isOnReparent */));
}
@@ -944,7 +944,7 @@ public class SplitControllerTest {
boolean result = mSplitController.resolveActivityToContainer(mTransaction, mActivity,
false /* isOnReparent */);
- assertFalse(result);
+ assertTrue(result);
assertEquals(primaryContainer, mSplitController.getContainerWithActivity(mActivity));
diff --git a/libs/WindowManager/Shell/res/color/split_divider_background.xml b/libs/WindowManager/Shell/res/color-night/taskbar_background.xml
index 049980803ee3..9473cdd607d6 100644
--- a/libs/WindowManager/Shell/res/color/split_divider_background.xml
+++ b/libs/WindowManager/Shell/res/color-night/taskbar_background.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright (C) 2021 The Android Open Source Project
+ ~ Copyright (C) 2023 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
@@ -14,6 +14,7 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
+<!-- Should be the same as in packages/apps/Launcher3/res/color-night-v31/taskbar_background.xml -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@android:color/system_neutral1_500" android:lStar="15" />
</selector> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/color/taskbar_background.xml b/libs/WindowManager/Shell/res/color/taskbar_background.xml
index b3d260299106..0e165fca4fd3 100644
--- a/libs/WindowManager/Shell/res/color/taskbar_background.xml
+++ b/libs/WindowManager/Shell/res/color/taskbar_background.xml
@@ -16,5 +16,5 @@
-->
<!-- Should be the same as in packages/apps/Launcher3/res/color-v31/taskbar_background.xml -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:color="@android:color/system_neutral1_500" android:lStar="15" />
+ <item android:color="@android:color/system_neutral1_500" android:lStar="95" />
</selector> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/drawable/desktop_mode_decor_menu_background.xml b/libs/WindowManager/Shell/res/drawable/desktop_mode_decor_menu_background.xml
index 9167382d0898..c6e634c6622c 100644
--- a/libs/WindowManager/Shell/res/drawable/desktop_mode_decor_menu_background.xml
+++ b/libs/WindowManager/Shell/res/drawable/desktop_mode_decor_menu_background.xml
@@ -17,6 +17,6 @@
<shape android:shape="rectangle"
xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@android:color/white" />
- <corners android:radius="20dp" />
+ <corners android:radius="@dimen/caption_menu_corner_radius" />
<stroke android:width="1dp" android:color="#b3b3b3"/>
</shape>
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background.xml b/libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background.xml
deleted file mode 100644
index 0d8811357c05..000000000000
--- a/libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2022 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <solid android:color="@color/letterbox_education_accent_primary"/>
- <corners android:radius="12dp"/>
-</shape> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background_ripple.xml b/libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background_ripple.xml
index 42572d64b96f..a2699681e656 100644
--- a/libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background_ripple.xml
+++ b/libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background_ripple.xml
@@ -14,7 +14,30 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="@color/letterbox_education_dismiss_button_background_ripple">
- <item android:drawable="@drawable/letterbox_education_dismiss_button_background"/>
-</ripple> \ No newline at end of file
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ android:insetTop="@dimen/letterbox_education_dialog_vertical_inset"
+ android:insetBottom="@dimen/letterbox_education_dialog_vertical_inset">
+ <ripple android:color="@color/letterbox_education_dismiss_button_background_ripple">
+ <item android:id="@android:id/mask">
+ <shape android:shape="rectangle">
+ <corners android:radius="@dimen/letterbox_education_dialog_button_radius"/>
+ <solid android:color="@android:color/white"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <solid android:color="@android:color/transparent"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <solid android:color="@color/letterbox_education_accent_primary"/>
+ <corners android:radius="@dimen/letterbox_education_dialog_button_radius"/>
+ <padding android:left="@dimen/letterbox_education_dialog_horizontal_padding"
+ android:top="@dimen/letterbox_education_dialog_vertical_padding"
+ android:right="@dimen/letterbox_education_dialog_horizontal_padding"
+ android:bottom="@dimen/letterbox_education_dialog_vertical_padding"/>
+ </shape>
+ </item>
+ </ripple>
+</inset>
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background.xml b/libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background.xml
deleted file mode 100644
index 60f3cfe6dde6..000000000000
--- a/libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2023 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.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
- android:shape="rectangle">
- <solid android:color="?androidprv:attr/colorAccentPrimaryVariant"/>
- <corners android:radius="@dimen/letterbox_restart_dialog_button_radius"/>
-</shape> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background_ripple.xml b/libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background_ripple.xml
index ef97ea19e993..1f125148775d 100644
--- a/libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background_ripple.xml
+++ b/libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background_ripple.xml
@@ -14,7 +14,31 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="@color/letterbox_restart_button_background_ripple">
- <item android:drawable="@drawable/letterbox_restart_button_background"/>
-</ripple> \ No newline at end of file
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:insetTop="@dimen/letterbox_restart_dialog_vertical_inset"
+ android:insetBottom="@dimen/letterbox_restart_dialog_vertical_inset">
+ <ripple android:color="@color/letterbox_restart_dismiss_button_background_ripple">
+ <item android:id="@android:id/mask">
+ <shape android:shape="rectangle">
+ <corners android:radius="@dimen/letterbox_restart_dialog_button_radius"/>
+ <solid android:color="@android:color/white"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <solid android:color="@android:color/transparent"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <solid android:color="?androidprv:attr/colorAccentPrimaryVariant"/>
+ <corners android:radius="@dimen/letterbox_restart_dialog_button_radius"/>
+ <padding android:left="@dimen/letterbox_restart_dialog_horizontal_padding"
+ android:top="@dimen/letterbox_restart_dialog_vertical_padding"
+ android:right="@dimen/letterbox_restart_dialog_horizontal_padding"
+ android:bottom="@dimen/letterbox_restart_dialog_vertical_padding"/>
+ </shape>
+ </item>
+ </ripple>
+</inset> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background.xml b/libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background.xml
deleted file mode 100644
index af89d41ee6b5..000000000000
--- a/libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2023 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.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
- android:shape="rectangle">
- <stroke android:color="?androidprv:attr/colorAccentPrimaryVariant" android:width="1dp"/>
- <solid android:color="?androidprv:attr/colorSurface" />
- <corners android:radius="@dimen/letterbox_restart_dialog_button_radius"/>
-</shape> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background_ripple.xml b/libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background_ripple.xml
index e32aefca78ac..3aa0981e45aa 100644
--- a/libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background_ripple.xml
+++ b/libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background_ripple.xml
@@ -14,7 +14,33 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="@color/letterbox_restart_dismiss_button_background_ripple">
- <item android:drawable="@drawable/letterbox_restart_dismiss_button_background"/>
-</ripple> \ No newline at end of file
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:insetTop="@dimen/letterbox_restart_dialog_vertical_inset"
+ android:insetBottom="@dimen/letterbox_restart_dialog_vertical_inset">
+ <ripple android:color="@color/letterbox_restart_dismiss_button_background_ripple">
+ <item android:id="@android:id/mask">
+ <shape android:shape="rectangle">
+ <corners android:radius="@dimen/letterbox_restart_dialog_button_radius"/>
+ <solid android:color="@android:color/white"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <solid android:color="@android:color/transparent"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <stroke android:color="?androidprv:attr/colorAccentPrimaryVariant"
+ android:width="1dp"/>
+ <solid android:color="?androidprv:attr/colorSurface"/>
+ <corners android:radius="@dimen/letterbox_restart_dialog_button_radius"/>
+ <padding android:left="@dimen/letterbox_restart_dialog_horizontal_padding"
+ android:top="@dimen/letterbox_restart_dialog_vertical_padding"
+ android:right="@dimen/letterbox_restart_dialog_horizontal_padding"
+ android:bottom="@dimen/letterbox_restart_dialog_vertical_padding"/>
+ </shape>
+ </item>
+ </ripple>
+</inset> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/layout/compat_mode_hint.xml b/libs/WindowManager/Shell/res/layout/compat_mode_hint.xml
index 44b2f45052ba..3d3c00381164 100644
--- a/libs/WindowManager/Shell/res/layout/compat_mode_hint.xml
+++ b/libs/WindowManager/Shell/res/layout/compat_mode_hint.xml
@@ -29,11 +29,15 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lineSpacingExtra="4sp"
+ android:letterSpacing="0.02"
android:background="@drawable/compat_hint_bubble"
android:padding="16dp"
android:textAlignment="viewStart"
android:textColor="@color/compat_controls_text"
- android:textSize="14sp"/>
+ android:textSize="14sp"
+ android:fontFamily="@*android:string/config_bodyFontFamily"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead"
+ />
<ImageView
android:layout_width="wrap_content"
diff --git a/libs/WindowManager/Shell/res/layout/desktop_mode_decor_handle_menu.xml b/libs/WindowManager/Shell/res/layout/desktop_mode_decor_handle_menu.xml
index f6e3f2edfa14..f9aeb6a8448a 100644
--- a/libs/WindowManager/Shell/res/layout/desktop_mode_decor_handle_menu.xml
+++ b/libs/WindowManager/Shell/res/layout/desktop_mode_decor_handle_menu.xml
@@ -21,7 +21,6 @@
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@drawable/desktop_mode_decor_menu_background"
- android:elevation="@dimen/caption_menu_elevation"
android:divider="?android:attr/dividerHorizontal"
android:showDividers="middle"
android:dividerPadding="18dip">
@@ -63,38 +62,46 @@
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="0.5" />
- <Button
+ <ImageButton
style="@style/CaptionWindowingButtonStyle"
android:id="@+id/fullscreen_button"
android:contentDescription="@string/fullscreen_text"
- android:background="@drawable/caption_fullscreen_button"/>
+ android:src="@drawable/caption_fullscreen_button"
+ android:scaleType="fitCenter"
+ android:background="?android:selectableItemBackgroundBorderless"/>
<Space
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1" />
- <Button
+ <ImageButton
style="@style/CaptionWindowingButtonStyle"
android:id="@+id/split_screen_button"
android:contentDescription="@string/split_screen_text"
- android:background="@drawable/caption_split_screen_button"/>
+ android:src="@drawable/caption_split_screen_button"
+ android:scaleType="fitCenter"
+ android:background="?android:selectableItemBackgroundBorderless"/>
<Space
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1" />
- <Button
+ <ImageButton
style="@style/CaptionWindowingButtonStyle"
android:id="@+id/floating_button"
android:contentDescription="@string/float_button_text"
- android:background="@drawable/caption_floating_button"/>
+ android:src="@drawable/caption_floating_button"
+ android:scaleType="fitCenter"
+ android:background="?android:selectableItemBackgroundBorderless"/>
<Space
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1" />
- <Button
+ <ImageButton
style="@style/CaptionWindowingButtonStyle"
android:id="@+id/desktop_button"
android:contentDescription="@string/desktop_text"
- android:background="@drawable/caption_desktop_button"/>
+ android:src="@drawable/caption_desktop_button"
+ android:scaleType="fitCenter"
+ android:background="?android:selectableItemBackgroundBorderless"/>
<Space
android:layout_width="0dp"
android:layout_height="1dp"
diff --git a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml
index c65f24d84e37..095576b581df 100644
--- a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml
+++ b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml
@@ -29,6 +29,8 @@
android:layout_marginBottom="20dp"/>
<TextView
+ android:fontFamily="@*android:string/config_bodyFontFamily"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Body2"
android:id="@+id/letterbox_education_dialog_action_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml
index 3a44eb9089dd..413cfd78fd91 100644
--- a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml
+++ b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml
@@ -16,9 +16,7 @@
<com.android.wm.shell.compatui.letterboxedu.LetterboxEduDialogLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:background="@android:color/system_neutral1_900">
+ style="@style/LetterboxDialog">
<!-- The background of the top-level layout acts as the background dim. -->
@@ -69,6 +67,8 @@
android:text="@string/letterbox_education_dialog_title"
android:textAlignment="center"
android:textColor="@color/compat_controls_text"
+ android:fontFamily="@*android:string/config_bodyFontFamilyMedium"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Headline"
android:textSize="24sp"/>
<LinearLayout
@@ -95,10 +95,16 @@
</LinearLayout>
<Button
+ android:fontFamily="@*android:string/config_bodyFontFamily"
+ android:fontWeight="500"
+ android:lineHeight="20dp"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Small"
android:id="@+id/letterbox_education_dialog_dismiss_button"
+ android:textStyle="bold"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_marginTop="40dp"
+ android:textSize="14sp"
android:background=
"@drawable/letterbox_education_dismiss_button_background_ripple"
android:text="@string/letterbox_education_got_it"
diff --git a/libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml b/libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml
index ba9852c4dd6b..5aff4159e135 100644
--- a/libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml
+++ b/libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml
@@ -16,14 +16,10 @@
<com.android.wm.shell.compatui.RestartDialogLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:background="@android:color/system_neutral1_900">
+ style="@style/LetterboxDialog">
<!-- The background of the top-level layout acts as the background dim. -->
- <!--TODO (b/266288912): Resolve overdraw warning -->
-
<!-- Vertical margin will be set dynamically since it depends on task bounds.
Setting the alpha of the dialog container to 0, since it shouldn't be visible until the
enter animation starts. -->
diff --git a/libs/WindowManager/Shell/res/values-af/strings.xml b/libs/WindowManager/Shell/res/values-af/strings.xml
index ee00e2651f62..76e9fd538cf3 100644
--- a/libs/WindowManager/Shell/res/values-af/strings.xml
+++ b/libs/WindowManager/Shell/res/values-af/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Bo 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Bo 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Volskerm onder"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Verdeel links"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Verdeel regs"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Verdeel bo"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Verdeel onder"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Gebruik eenhandmodus"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Swiep van die onderkant van die skerm af op of tik enige plek bo die program om uit te gaan"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Begin eenhandmodus"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Maak toe"</string>
<string name="back_button_text" msgid="1469718707134137085">"Terug"</string>
<string name="handle_text" msgid="1766582106752184456">"Handvatsel"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Appikoon"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Volskerm"</string>
<string name="desktop_text" msgid="1077633567027630454">"Rekenaarmodus"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Verdeelde skerm"</string>
<string name="more_button_text" msgid="3655388105592893530">"Meer"</string>
<string name="float_button_text" msgid="9221657008391364581">"Sweef"</string>
+ <string name="select_text" msgid="5139083974039906583">"Kies"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Skermskoot"</string>
+ <string name="close_text" msgid="4986518933445178928">"Maak toe"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Maak kieslys toe"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-am/strings.xml b/libs/WindowManager/Shell/res/values-am/strings.xml
index 781038f1e61e..969af096f571 100644
--- a/libs/WindowManager/Shell/res/values-am/strings.xml
+++ b/libs/WindowManager/Shell/res/values-am/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"ከላይ 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"ከላይ 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"የታች ሙሉ ማያ ገጽ"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"ወደ ግራ ከፋፍል"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"ወደ ቀኝ ከፋፍል"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"ወደ ላይ ከፋፍል"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"ወደ ታች ከፋፍል"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"ባለአንድ እጅ ሁነታን በመጠቀም ላይ"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"ለመውጣት ከማያው ግርጌ ወደ ላይ ይጥረጉ ወይም ከመተግበሪያው በላይ ማንኛውም ቦታ ላይ መታ ያድርጉ"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"ባለአንድ እጅ ሁነታ ጀምር"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"ዝጋ"</string>
<string name="back_button_text" msgid="1469718707134137085">"ተመለስ"</string>
<string name="handle_text" msgid="1766582106752184456">"መያዣ"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"የመተግበሪያ አዶ"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"ሙሉ ማያ"</string>
<string name="desktop_text" msgid="1077633567027630454">"የዴስክቶፕ ሁነታ"</string>
<string name="split_screen_text" msgid="1396336058129570886">"የተከፈለ ማያ ገጽ"</string>
<string name="more_button_text" msgid="3655388105592893530">"ተጨማሪ"</string>
<string name="float_button_text" msgid="9221657008391364581">"ተንሳፋፊ"</string>
+ <string name="select_text" msgid="5139083974039906583">"ምረጥ"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"ቅጽበታዊ ገጽ እይታ"</string>
+ <string name="close_text" msgid="4986518933445178928">"ዝጋ"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"ምናሌ ዝጋ"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ar/strings.xml b/libs/WindowManager/Shell/res/values-ar/strings.xml
index 7325da135d94..94014bc106bc 100644
--- a/libs/WindowManager/Shell/res/values-ar/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ar/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"ضبط حجم النافذة العلوية ليكون ٥٠%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"ضبط حجم النافذة العلوية ليكون ٣٠%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"عرض النافذة السفلية بملء الشاشة"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"تقسيم لليسار"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"تقسيم لليمين"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"تقسيم للأعلى"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"تقسيم للأسفل"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"استخدام وضع \"التصفح بيد واحدة\""</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"للخروج، مرِّر سريعًا من أسفل الشاشة إلى أعلاها أو انقر في أي مكان فوق التطبيق."</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"بدء وضع \"التصفح بيد واحدة\""</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"إغلاق"</string>
<string name="back_button_text" msgid="1469718707134137085">"رجوع"</string>
<string name="handle_text" msgid="1766582106752184456">"مقبض"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"رمز التطبيق"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"ملء الشاشة"</string>
<string name="desktop_text" msgid="1077633567027630454">"وضع سطح المكتب"</string>
<string name="split_screen_text" msgid="1396336058129570886">"تقسيم الشاشة"</string>
<string name="more_button_text" msgid="3655388105592893530">"المزيد"</string>
<string name="float_button_text" msgid="9221657008391364581">"نافذة عائمة"</string>
+ <string name="select_text" msgid="5139083974039906583">"اختيار"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"لقطة شاشة"</string>
+ <string name="close_text" msgid="4986518933445178928">"إغلاق"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"إغلاق القائمة"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-as/strings.xml b/libs/WindowManager/Shell/res/values-as/strings.xml
index 3fd705e8a07b..519b5cd2e6cb 100644
--- a/libs/WindowManager/Shell/res/values-as/strings.xml
+++ b/libs/WindowManager/Shell/res/values-as/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"শীর্ষ স্ক্ৰীনখন ৫০% কৰক"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"শীর্ষ স্ক্ৰীনখন ৩০% কৰক"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"তলৰ স্ক্ৰীনখন সম্পূৰ্ণ স্ক্ৰীন কৰক"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"বাওঁফালে বিভাজন কৰক"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"সোঁফালে বিভাজন কৰক"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"একেবাৰে ওপৰৰফালে বিভাজন কৰক"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"একেবাৰে তলৰফালে বিভাজন কৰক"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"এখন হাতেৰে ব্যৱহাৰ কৰা ম’ড ব্যৱহাৰ কৰা"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"বাহিৰ হ’বলৈ স্ক্ৰীনখনৰ একেবাৰে তলৰ পৰা ওপৰলৈ ছোৱাইপ কৰক অথবা এপ্‌টোৰ ওপৰত যিকোনো ঠাইত টিপক"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"এখন হাতেৰে ব্যৱহাৰ কৰা ম\'ডটো আৰম্ভ কৰক"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"বন্ধ কৰক"</string>
<string name="back_button_text" msgid="1469718707134137085">"উভতি যাওক"</string>
<string name="handle_text" msgid="1766582106752184456">"হেণ্ডেল"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"এপৰ চিহ্ন"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"সম্পূৰ্ণ স্ক্ৰীন"</string>
<string name="desktop_text" msgid="1077633567027630454">"ডেস্কটপ ম’ড"</string>
<string name="split_screen_text" msgid="1396336058129570886">"বিভাজিত স্ক্ৰীন"</string>
<string name="more_button_text" msgid="3655388105592893530">"অধিক"</string>
<string name="float_button_text" msgid="9221657008391364581">"ওপঙা"</string>
+ <string name="select_text" msgid="5139083974039906583">"বাছনি কৰক"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"স্ক্ৰীনশ্বট"</string>
+ <string name="close_text" msgid="4986518933445178928">"বন্ধ কৰক"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"মেনু বন্ধ কৰক"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-az/strings.xml b/libs/WindowManager/Shell/res/values-az/strings.xml
index a31b1e7eb9cd..5f7db280b6f0 100644
--- a/libs/WindowManager/Shell/res/values-az/strings.xml
+++ b/libs/WindowManager/Shell/res/values-az/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Yuxarı 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Yuxarı 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Aşağı tam ekran"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Sola ayırın"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Sağa ayırın"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Yuxarı ayırın"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Aşağı ayırın"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Birəlli rejim istifadəsi"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Çıxmaq üçün ekranın aşağısından yuxarıya doğru sürüşdürün və ya tətbiqin yuxarısında istənilən yerə toxunun"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Birəlli rejim başlasın"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Bağlayın"</string>
<string name="back_button_text" msgid="1469718707134137085">"Geriyə"</string>
<string name="handle_text" msgid="1766582106752184456">"Hər kəsə açıq istifadəçi adı"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Tətbiq ikonası"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Tam Ekran"</string>
<string name="desktop_text" msgid="1077633567027630454">"Masaüstü Rejimi"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Bölünmüş Ekran"</string>
<string name="more_button_text" msgid="3655388105592893530">"Ardı"</string>
<string name="float_button_text" msgid="9221657008391364581">"Üzən pəncərə"</string>
+ <string name="select_text" msgid="5139083974039906583">"Seçin"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Skrinşot"</string>
+ <string name="close_text" msgid="4986518933445178928">"Bağlayın"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Menyunu bağlayın"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
index c0e4789d3d97..0f54e86bc54c 100644
--- a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Gornji ekran 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Gornji ekran 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Režim celog ekrana za donji ekran"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Podelite levo"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Podelite desno"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Podelite u vrhu"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Podelite u dnu"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Korišćenje režima jednom rukom"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Da biste izašli, prevucite nagore od dna ekrana ili dodirnite bilo gde iznad aplikacije"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Pokrenite režim jednom rukom"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Zatvorite"</string>
<string name="back_button_text" msgid="1469718707134137085">"Nazad"</string>
<string name="handle_text" msgid="1766582106752184456">"Identifikator"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Ikona aplikacije"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Preko celog ekrana"</string>
<string name="desktop_text" msgid="1077633567027630454">"Režim za računare"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Podeljeni ekran"</string>
<string name="more_button_text" msgid="3655388105592893530">"Još"</string>
<string name="float_button_text" msgid="9221657008391364581">"Plutajuće"</string>
+ <string name="select_text" msgid="5139083974039906583">"Izaberite"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Snimak ekrana"</string>
+ <string name="close_text" msgid="4986518933445178928">"Zatvorite"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Zatvorite meni"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-be/strings.xml b/libs/WindowManager/Shell/res/values-be/strings.xml
index b67e2cdca49e..bf1113dcb066 100644
--- a/libs/WindowManager/Shell/res/values-be/strings.xml
+++ b/libs/WindowManager/Shell/res/values-be/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Верхні экран – 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Верхні экран – 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Ніжні экран – поўнаэкранны рэжым"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Падзяліць злева"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Падзяліць справа"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Падзяліць уверсе"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Падзяліць унізе"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Выкарыстоўваецца рэжым кіравання адной рукой"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Каб выйсці, правядзіце па экране пальцам знізу ўверх або націсніце ў любым месцы над праграмай"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Запусціць рэжым кіравання адной рукой"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Закрыць"</string>
<string name="back_button_text" msgid="1469718707134137085">"Назад"</string>
<string name="handle_text" msgid="1766582106752184456">"Маркер"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Значок праграмы"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"На ўвесь экран"</string>
<string name="desktop_text" msgid="1077633567027630454">"Рэжым працоўнага стала"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Падзяліць экран"</string>
<string name="more_button_text" msgid="3655388105592893530">"Яшчэ"</string>
<string name="float_button_text" msgid="9221657008391364581">"Зрабіць рухомым акном"</string>
+ <string name="select_text" msgid="5139083974039906583">"Выбраць"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Здымак экрана"</string>
+ <string name="close_text" msgid="4986518933445178928">"Закрыць"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Закрыць меню"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-bg/strings.xml b/libs/WindowManager/Shell/res/values-bg/strings.xml
index 9bf396dc04c9..996280e41e53 100644
--- a/libs/WindowManager/Shell/res/values-bg/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bg/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Горен екран: 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Горен екран: 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Долен екран: Показване на цял екран"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Разделяне в лявата част"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Разделяне в дясната част"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Разделяне в горната част"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Разделяне в долната част"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Използване на режима за работа с една ръка"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"За изход прекарайте пръст нагоре от долната част на екрана или докоснете произволно място над приложението"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Стартиране на режима за работа с една ръка"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Затваряне"</string>
<string name="back_button_text" msgid="1469718707134137085">"Назад"</string>
<string name="handle_text" msgid="1766582106752184456">"Манипулатор"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Икона на приложението"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Цял екран"</string>
<string name="desktop_text" msgid="1077633567027630454">"Режим за настолни компютри"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Разделяне на екрана"</string>
<string name="more_button_text" msgid="3655388105592893530">"Още"</string>
<string name="float_button_text" msgid="9221657008391364581">"Плаващо"</string>
+ <string name="select_text" msgid="5139083974039906583">"Избиране"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Екранна снимка"</string>
+ <string name="close_text" msgid="4986518933445178928">"Затваряне"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Затваряне на менюто"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-bn/strings.xml b/libs/WindowManager/Shell/res/values-bn/strings.xml
index affb62e74591..582b9a749cbb 100644
--- a/libs/WindowManager/Shell/res/values-bn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bn/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"শীর্ষ ৫০%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"শীর্ষ ৩০%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"নীচের অংশ নিয়ে পূর্ণ স্ক্রিন"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"স্ক্রিনের বাঁদিকে স্প্লিট করুন"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"স্ক্রিনের ডানদিকে স্প্লিট করুন"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"স্ক্রিনের উপরের দিকে স্প্লিট করুন"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"স্প্লিট করার বোতাম"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"\'এক হাতে ব্যবহার করার মোড\'-এর ব্যবহার"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"বেরিয়ে আসার জন্য, স্ক্রিনের নিচ থেকে উপরের দিকে সোয়াইপ করুন অথবা অ্যাপ আইকনের উপরে যেকোনও জায়গায় ট্যাপ করুন"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"\'এক হাতে ব্যবহার করার মোড\' শুরু করুন"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"বন্ধ করুন"</string>
<string name="back_button_text" msgid="1469718707134137085">"ফিরে যান"</string>
<string name="handle_text" msgid="1766582106752184456">"হাতল"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"অ্যাপ আইকন"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"ফুলস্ক্রিন"</string>
<string name="desktop_text" msgid="1077633567027630454">"ডেস্কটপ মোড"</string>
<string name="split_screen_text" msgid="1396336058129570886">"স্প্লিট স্ক্রিন"</string>
<string name="more_button_text" msgid="3655388105592893530">"আরও"</string>
<string name="float_button_text" msgid="9221657008391364581">"ফ্লোট"</string>
+ <string name="select_text" msgid="5139083974039906583">"বেছে নিন"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"স্ক্রিনশট"</string>
+ <string name="close_text" msgid="4986518933445178928">"বন্ধ করুন"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"\'মেনু\' বন্ধ করুন"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-bs/strings.xml b/libs/WindowManager/Shell/res/values-bs/strings.xml
index dd2f871c5ebb..29d4ac4e88c6 100644
--- a/libs/WindowManager/Shell/res/values-bs/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bs/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Gore 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Gore 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Donji ekran kao cijeli ekran"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Podjela ulijevo"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Podjela udesno"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Podjela nagore"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Podjela nadolje"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Korištenje načina rada jednom rukom"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Da izađete, prevucite s dna ekrana prema gore ili dodirnite bilo gdje iznad aplikacije"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Započinjanje načina rada jednom rukom"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Zatvaranje"</string>
<string name="back_button_text" msgid="1469718707134137085">"Nazad"</string>
<string name="handle_text" msgid="1766582106752184456">"Identifikator"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Ikona aplikacije"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Cijeli ekran"</string>
<string name="desktop_text" msgid="1077633567027630454">"Način rada radne površine"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Podijeljeni ekran"</string>
<string name="more_button_text" msgid="3655388105592893530">"Više"</string>
<string name="float_button_text" msgid="9221657008391364581">"Lebdeći"</string>
+ <string name="select_text" msgid="5139083974039906583">"Odabir"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Snimak ekrana"</string>
+ <string name="close_text" msgid="4986518933445178928">"Zatvaranje"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Zatvaranje menija"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ca/strings.xml b/libs/WindowManager/Shell/res/values-ca/strings.xml
index 937e0d9d4b3f..a55d7b7446d2 100644
--- a/libs/WindowManager/Shell/res/values-ca/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ca/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Pantalla superior al 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Pantalla superior al 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Pantalla inferior completa"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Divideix a l\'esquerra"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Divideix a la dreta"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Divideix a la part superior"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Divideix a la part inferior"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"S\'està utilitzant el mode d\'una mà"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Per sortir, llisca cap amunt des de la part inferior de la pantalla o toca qualsevol lloc a sobre de l\'aplicació"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Inicia el mode d\'una mà"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Tanca"</string>
<string name="back_button_text" msgid="1469718707134137085">"Enrere"</string>
<string name="handle_text" msgid="1766582106752184456">"Ansa"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Icona de l\'aplicació"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Pantalla completa"</string>
<string name="desktop_text" msgid="1077633567027630454">"Mode d\'escriptori"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Pantalla dividida"</string>
<string name="more_button_text" msgid="3655388105592893530">"Més"</string>
<string name="float_button_text" msgid="9221657008391364581">"Flotant"</string>
+ <string name="select_text" msgid="5139083974039906583">"Selecciona"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Captura de pantalla"</string>
+ <string name="close_text" msgid="4986518933445178928">"Tanca"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Tanca el menú"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-cs/strings.xml b/libs/WindowManager/Shell/res/values-cs/strings.xml
index a35889546ec9..38f911dd1038 100644
--- a/libs/WindowManager/Shell/res/values-cs/strings.xml
+++ b/libs/WindowManager/Shell/res/values-cs/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"50 % nahoře"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"30 % nahoře"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Dolní část na celou obrazovku"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Rozdělit vlevo"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Rozdělit vpravo"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Rozdělit nahoře"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Rozdělit dole"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Používání režimu jedné ruky"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Režim ukončíte, když přejedete prstem z dolní části obrazovky nahoru nebo klepnete kamkoli nad aplikaci"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Spustit režim jedné ruky"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Zavřít"</string>
<string name="back_button_text" msgid="1469718707134137085">"Zpět"</string>
<string name="handle_text" msgid="1766582106752184456">"Úchyt"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Ikona aplikace"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Celá obrazovka"</string>
<string name="desktop_text" msgid="1077633567027630454">"Režim počítače"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Rozdělená obrazovka"</string>
<string name="more_button_text" msgid="3655388105592893530">"Více"</string>
<string name="float_button_text" msgid="9221657008391364581">"Plovoucí"</string>
+ <string name="select_text" msgid="5139083974039906583">"Vybrat"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Snímek obrazovky"</string>
+ <string name="close_text" msgid="4986518933445178928">"Zavřít"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Zavřít nabídku"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-da/strings.xml b/libs/WindowManager/Shell/res/values-da/strings.xml
index 7a40efd0382c..ca151289a9d9 100644
--- a/libs/WindowManager/Shell/res/values-da/strings.xml
+++ b/libs/WindowManager/Shell/res/values-da/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Øverste 50 %"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Øverste 30 %"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Vis nederste del i fuld skærm"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Vis i venstre side"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Vis i højre side"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Vis øverst"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Vis nederst"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Brug af enhåndstilstand"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Du kan afslutte ved at stryge opad fra bunden af skærmen eller trykke et vilkårligt sted over appen"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Start enhåndstilstand"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Luk"</string>
<string name="back_button_text" msgid="1469718707134137085">"Tilbage"</string>
<string name="handle_text" msgid="1766582106752184456">"Håndtag"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Appikon"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Fuld skærm"</string>
<string name="desktop_text" msgid="1077633567027630454">"Computertilstand"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Opdelt skærm"</string>
<string name="more_button_text" msgid="3655388105592893530">"Mere"</string>
<string name="float_button_text" msgid="9221657008391364581">"Svævende"</string>
+ <string name="select_text" msgid="5139083974039906583">"Vælg"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Screenshot"</string>
+ <string name="close_text" msgid="4986518933445178928">"Luk"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Luk menu"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-de/strings.xml b/libs/WindowManager/Shell/res/values-de/strings.xml
index 8f6275209280..916fa85f74e7 100644
--- a/libs/WindowManager/Shell/res/values-de/strings.xml
+++ b/libs/WindowManager/Shell/res/values-de/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"50 % oben"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"30 % oben"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Vollbild unten"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Links teilen"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Rechts teilen"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Oben teilen"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Unten teilen"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Einhandmodus wird verwendet"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Wenn du die App schließen möchtest, wische vom unteren Rand des Displays nach oben oder tippe auf eine beliebige Stelle oberhalb der App"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Einhandmodus starten"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Schließen"</string>
<string name="back_button_text" msgid="1469718707134137085">"Zurück"</string>
<string name="handle_text" msgid="1766582106752184456">"Ziehpunkt"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"App-Symbol"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Vollbild"</string>
<string name="desktop_text" msgid="1077633567027630454">"Desktopmodus"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Geteilter Bildschirm"</string>
<string name="more_button_text" msgid="3655388105592893530">"Mehr"</string>
<string name="float_button_text" msgid="9221657008391364581">"Frei schwebend"</string>
+ <string name="select_text" msgid="5139083974039906583">"Auswählen"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Screenshot"</string>
+ <string name="close_text" msgid="4986518933445178928">"Schließen"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Menü schließen"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-el/strings.xml b/libs/WindowManager/Shell/res/values-el/strings.xml
index 8d0faebf269d..58d19f77c15e 100644
--- a/libs/WindowManager/Shell/res/values-el/strings.xml
+++ b/libs/WindowManager/Shell/res/values-el/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Πάνω 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Πάνω 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Κάτω πλήρης οθόνη"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Διαχωρισμός αριστερά"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Διαχωρισμός δεξιά"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Διαχωρισμός επάνω"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Διαχωρισμός κάτω"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Χρήση λειτουργίας ενός χεριού"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Για έξοδο, σύρετε προς τα πάνω από το κάτω μέρος της οθόνης ή πατήστε οπουδήποτε πάνω από την εφαρμογή."</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Έναρξη λειτουργίας ενός χεριού"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Κλείσιμο"</string>
<string name="back_button_text" msgid="1469718707134137085">"Πίσω"</string>
<string name="handle_text" msgid="1766582106752184456">"Λαβή"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Εικονίδιο εφαρμογής"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Πλήρης οθόνη"</string>
<string name="desktop_text" msgid="1077633567027630454">"Λειτουργία επιφάνειας εργασίας"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Διαχωρισμός οθόνης"</string>
<string name="more_button_text" msgid="3655388105592893530">"Περισσότερα"</string>
<string name="float_button_text" msgid="9221657008391364581">"Κινούμενο"</string>
+ <string name="select_text" msgid="5139083974039906583">"Επιλογή"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Στιγμιότυπο οθόνης"</string>
+ <string name="close_text" msgid="4986518933445178928">"Κλείσιμο"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Κλείσιμο μενού"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
index a108e8930251..d5da5c6b067d 100644
--- a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
@@ -98,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Close"</string>
<string name="back_button_text" msgid="1469718707134137085">"Back"</string>
<string name="handle_text" msgid="1766582106752184456">"Handle"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"App icon"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Full screen"</string>
<string name="desktop_text" msgid="1077633567027630454">"Desktop mode"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Split screen"</string>
<string name="more_button_text" msgid="3655388105592893530">"More"</string>
<string name="float_button_text" msgid="9221657008391364581">"Float"</string>
+ <string name="select_text" msgid="5139083974039906583">"Select"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Screenshot"</string>
+ <string name="close_text" msgid="4986518933445178928">"Close"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Close menu"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
index cfa9abc5bc13..c1f1549a7630 100644
--- a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
@@ -98,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Close"</string>
<string name="back_button_text" msgid="1469718707134137085">"Back"</string>
<string name="handle_text" msgid="1766582106752184456">"Handle"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"App Icon"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Fullscreen"</string>
<string name="desktop_text" msgid="1077633567027630454">"Desktop Mode"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Split Screen"</string>
<string name="more_button_text" msgid="3655388105592893530">"More"</string>
<string name="float_button_text" msgid="9221657008391364581">"Float"</string>
+ <string name="select_text" msgid="5139083974039906583">"Select"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Screenshot"</string>
+ <string name="close_text" msgid="4986518933445178928">"Close"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Close Menu"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
index a108e8930251..d5da5c6b067d 100644
--- a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
@@ -98,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Close"</string>
<string name="back_button_text" msgid="1469718707134137085">"Back"</string>
<string name="handle_text" msgid="1766582106752184456">"Handle"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"App icon"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Full screen"</string>
<string name="desktop_text" msgid="1077633567027630454">"Desktop mode"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Split screen"</string>
<string name="more_button_text" msgid="3655388105592893530">"More"</string>
<string name="float_button_text" msgid="9221657008391364581">"Float"</string>
+ <string name="select_text" msgid="5139083974039906583">"Select"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Screenshot"</string>
+ <string name="close_text" msgid="4986518933445178928">"Close"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Close menu"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
index a108e8930251..d5da5c6b067d 100644
--- a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
@@ -98,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Close"</string>
<string name="back_button_text" msgid="1469718707134137085">"Back"</string>
<string name="handle_text" msgid="1766582106752184456">"Handle"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"App icon"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Full screen"</string>
<string name="desktop_text" msgid="1077633567027630454">"Desktop mode"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Split screen"</string>
<string name="more_button_text" msgid="3655388105592893530">"More"</string>
<string name="float_button_text" msgid="9221657008391364581">"Float"</string>
+ <string name="select_text" msgid="5139083974039906583">"Select"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Screenshot"</string>
+ <string name="close_text" msgid="4986518933445178928">"Close"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Close menu"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-en-rXC/strings.xml b/libs/WindowManager/Shell/res/values-en-rXC/strings.xml
index 65af7781ad98..5968df5d9035 100644
--- a/libs/WindowManager/Shell/res/values-en-rXC/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rXC/strings.xml
@@ -98,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‏‎‏‏‏‎‎‎‎‎‏‏‏‎‏‎‎‎‏‎‏‎‎‏‎‎‎‏‏‏‏‎‎‎‏‏‎‏‏‎‏‏‎‎‎‎‎‎‎‏‎‎‏‏‎Close‎‏‎‎‏‎"</string>
<string name="back_button_text" msgid="1469718707134137085">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‎‏‏‎‎‏‎‏‎‏‏‏‏‏‎‏‎‏‏‎‎‎‎‎‏‎‎‏‎‎‏‎‎‏‏‏‏‎‏‎‎‎‎‎‎‎‏‎‏‏‏‏‏‏‎‏‎Back‎‏‎‎‏‎"</string>
<string name="handle_text" msgid="1766582106752184456">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‏‎‎‎‎‏‎‎‎‎‏‎‏‎‎‏‎‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‎‏‏‎‎‏‏‏‎‎‎‎‏‎‎‎‏‎‎‎‎Handle‎‏‎‎‏‎"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‏‎‏‏‏‎‎‏‎‎‎‎‏‏‎‏‎‎‏‏‏‏‎‎‏‏‏‎‎‎‎‎‏‎‏‏‎‎‏‎‏‏‎‏‏‏‏‎‏‎‎‎‏‏‎App Icon‎‏‎‎‏‎"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‎‎‎‎‏‎‏‏‎‎‎‎‎‏‏‎‏‏‏‎‏‏‏‏‏‎‎‏‎‏‏‏‎‏‎‎‎‏‎‏‏‏‎‏‏‎‎‏‎‏‏‏‏‎Fullscreen‎‏‎‎‏‎"</string>
<string name="desktop_text" msgid="1077633567027630454">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‏‏‏‎‏‎‎‏‎‎‎‎‏‏‎‎‎‎‎‎‏‎‏‎‎‎‎‏‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‎‏‏‏‎‏‏‎‎Desktop Mode‎‏‎‎‏‎"</string>
<string name="split_screen_text" msgid="1396336058129570886">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‏‎‏‏‎‎‎‎‎‏‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‎‎‏‎‏‎‏‏‏‏‏‎‎‎‎‏‏‏‎‏‏‏‎‎‎‏‎‎‎‏‏‎‎Split Screen‎‏‎‎‏‎"</string>
<string name="more_button_text" msgid="3655388105592893530">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‎‏‏‏‎‏‎‏‎‎‎‏‏‎‎‎‎‎‏‏‏‎‏‎‏‏‎‏‏‏‎‎‎‎‎‏‏‎‏‎‏‏‏‎‎‎‎‎‏‎‏‏‎‏‎‎More‎‏‎‎‏‎"</string>
<string name="float_button_text" msgid="9221657008391364581">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‎‎‎‎‎‏‏‎‎‎‎‏‏‎‏‎‎‎‏‏‎‏‎‏‎‎‎‏‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎Float‎‏‎‎‏‎"</string>
+ <string name="select_text" msgid="5139083974039906583">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‏‎‏‎‎‎‏‏‎‏‏‎‎‎‏‏‎‏‎‎‏‎‏‎‏‏‏‎‏‏‏‏‎‎‎‏‏‎‏‎‎‏‎‏‎‎‏‎‎‎‏‎‏‏‏‎Select‎‏‎‎‏‎"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‏‎‎‎‎‎‎‏‏‏‎‏‏‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‏‎‎‎‏‏‏‎‎‏‏‏‏‏‎‏‎‎‎‏‎‏‎‏‏‏‏‎Screenshot‎‏‎‎‏‎"</string>
+ <string name="close_text" msgid="4986518933445178928">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‏‏‎‎‏‏‏‎‏‎‏‏‎‎‏‎‎‎‏‏‎‎‏‏‎‏‏‏‎‏‏‏‎‎‎‎‏‎‎‏‏‏‎‏‏‎‎‎‏‏‎‎‎‎‎Close‎‏‎‎‏‎"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‎‎‏‎‏‎‏‎‏‎‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‏‎‏‏‎‏‏‎‏‎‎‏‏‏‏‏‏‎‎‎‎‏‎‎‎‏‏‎‏‎Close Menu‎‏‎‎‏‎"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
index c26532eb3860..e9b052242ba6 100644
--- a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
+++ b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Superior: 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Superior: 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Pantalla inferior completa"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Dividir a la izquierda"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Dividir a la derecha"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Dividir en la parte superior"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Dividir en la parte inferior"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Cómo usar el modo de una mano"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Para salir, desliza el dedo hacia arriba desde la parte inferior de la pantalla o presiona cualquier parte arriba de la app"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Iniciar el modo de una mano"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Cerrar"</string>
<string name="back_button_text" msgid="1469718707134137085">"Atrás"</string>
<string name="handle_text" msgid="1766582106752184456">"Controlador"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Ícono de la app"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Pantalla completa"</string>
<string name="desktop_text" msgid="1077633567027630454">"Modo de escritorio"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Pantalla dividida"</string>
<string name="more_button_text" msgid="3655388105592893530">"Más"</string>
<string name="float_button_text" msgid="9221657008391364581">"Flotante"</string>
+ <string name="select_text" msgid="5139083974039906583">"Seleccionar"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Captura de pantalla"</string>
+ <string name="close_text" msgid="4986518933445178928">"Cerrar"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Cerrar menú"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-es/strings.xml b/libs/WindowManager/Shell/res/values-es/strings.xml
index 58deed555fd9..2c32e710e8ff 100644
--- a/libs/WindowManager/Shell/res/values-es/strings.xml
+++ b/libs/WindowManager/Shell/res/values-es/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Superior 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Superior 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Pantalla inferior completa"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Dividir en la parte izquierda"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Dividir en la parte derecha"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Dividir en la parte superior"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Dividir en la parte inferior"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Usar modo Una mano"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Para salir, desliza el dedo hacia arriba desde la parte inferior de la pantalla o toca cualquier zona que haya encima de la aplicación"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Iniciar modo Una mano"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Cerrar"</string>
<string name="back_button_text" msgid="1469718707134137085">"Atrás"</string>
<string name="handle_text" msgid="1766582106752184456">"Controlador"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Icono de la aplicación"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Pantalla completa"</string>
<string name="desktop_text" msgid="1077633567027630454">"Modo Escritorio"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Pantalla dividida"</string>
<string name="more_button_text" msgid="3655388105592893530">"Más"</string>
<string name="float_button_text" msgid="9221657008391364581">"Flotante"</string>
+ <string name="select_text" msgid="5139083974039906583">"Seleccionar"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Captura de pantalla"</string>
+ <string name="close_text" msgid="4986518933445178928">"Cerrar"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Cerrar menú"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-et/strings.xml b/libs/WindowManager/Shell/res/values-et/strings.xml
index c0d0588900ad..6ba77c3ac0e2 100644
--- a/libs/WindowManager/Shell/res/values-et/strings.xml
+++ b/libs/WindowManager/Shell/res/values-et/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Ülemine: 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Ülemine: 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Alumine täisekraan"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Jaga vasakule"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Jaga paremale"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Jaga üles"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Jaga alla"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Ühekäerežiimi kasutamine"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Väljumiseks pühkige ekraani alaosast üles või puudutage rakenduse kohal olevat ala"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Ühekäerežiimi käivitamine"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Sule"</string>
<string name="back_button_text" msgid="1469718707134137085">"Tagasi"</string>
<string name="handle_text" msgid="1766582106752184456">"Käepide"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Rakenduse ikoon"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Täisekraan"</string>
<string name="desktop_text" msgid="1077633567027630454">"Lauaarvuti režiim"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Jagatud ekraanikuva"</string>
<string name="more_button_text" msgid="3655388105592893530">"Rohkem"</string>
<string name="float_button_text" msgid="9221657008391364581">"Hõljuv"</string>
+ <string name="select_text" msgid="5139083974039906583">"Vali"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Ekraanipilt"</string>
+ <string name="close_text" msgid="4986518933445178928">"Sule"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Sule menüü"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-eu/strings.xml b/libs/WindowManager/Shell/res/values-eu/strings.xml
index 6a1f45727203..ef11e4703d3d 100644
--- a/libs/WindowManager/Shell/res/values-eu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-eu/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Ezarri goialdea % 50en"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Ezarri goialdea % 30en"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Ezarri behealdea pantaila osoan"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Zatitu ezkerraldean"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Zatitu eskuinaldean"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Zatitu goialdean"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Zatitu behealdean"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Esku bakarreko modua erabiltzea"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Irteteko, pasatu hatza pantailaren behealdetik gora edo sakatu aplikazioaren gainaldea"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Abiarazi esku bakarreko modua"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Itxi"</string>
<string name="back_button_text" msgid="1469718707134137085">"Atzera"</string>
<string name="handle_text" msgid="1766582106752184456">"Kontu-izena"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Aplikazioaren ikonoa"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Pantaila osoa"</string>
<string name="desktop_text" msgid="1077633567027630454">"Ordenagailuetarako modua"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Pantaila zatitua"</string>
<string name="more_button_text" msgid="3655388105592893530">"Gehiago"</string>
<string name="float_button_text" msgid="9221657008391364581">"Leiho gainerakorra"</string>
+ <string name="select_text" msgid="5139083974039906583">"Hautatu"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Pantaila-argazkia"</string>
+ <string name="close_text" msgid="4986518933445178928">"Itxi"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Itxi menua"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-fa/strings.xml b/libs/WindowManager/Shell/res/values-fa/strings.xml
index 59c119d18c2d..b0cfd32d2515 100644
--- a/libs/WindowManager/Shell/res/values-fa/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fa/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"٪۵۰ بالا"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"٪۳۰ بالا"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"تمام‌صفحه پایین"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"تقسیم از چپ"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"تقسیم از راست"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"تقسیم از بالا"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"تقسیم از پایین"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"استفاده از حالت یک‌دستی"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"برای خارج شدن، از پایین صفحه‌نمایش تند به‌طرف بالا بکشید یا در هر جایی از بالای برنامه که می‌خواهید ضربه بزنید"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"آغاز «حالت یک‌دستی»"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"بستن"</string>
<string name="back_button_text" msgid="1469718707134137085">"برگشتن"</string>
<string name="handle_text" msgid="1766582106752184456">"دستگیره"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"نماد برنامه"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"تمام‌صفحه"</string>
<string name="desktop_text" msgid="1077633567027630454">"حالت رایانه"</string>
<string name="split_screen_text" msgid="1396336058129570886">"صفحهٔ دونیمه"</string>
<string name="more_button_text" msgid="3655388105592893530">"بیشتر"</string>
<string name="float_button_text" msgid="9221657008391364581">"شناور"</string>
+ <string name="select_text" msgid="5139083974039906583">"انتخاب"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"نماگرفت"</string>
+ <string name="close_text" msgid="4986518933445178928">"بستن"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"بستن منو"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-fi/strings.xml b/libs/WindowManager/Shell/res/values-fi/strings.xml
index edb1dae1269d..90a196bcd46e 100644
--- a/libs/WindowManager/Shell/res/values-fi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fi/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Yläosa 50 %"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Yläosa 30 %"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Alaosa koko näytölle"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Vasemmalla"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Oikealla"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Ylhäällä"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Alhaalla"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Yhden käden moodin käyttö"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Poistu pyyhkäisemällä ylös näytön alareunasta tai napauttamalla sovelluksen yllä"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Käynnistä yhden käden moodi"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Sulje"</string>
<string name="back_button_text" msgid="1469718707134137085">"Takaisin"</string>
<string name="handle_text" msgid="1766582106752184456">"Kahva"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Sovelluskuvake"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Koko näyttö"</string>
<string name="desktop_text" msgid="1077633567027630454">"Työpöytätila"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Jaettu näyttö"</string>
<string name="more_button_text" msgid="3655388105592893530">"Lisää"</string>
<string name="float_button_text" msgid="9221657008391364581">"Kelluva ikkuna"</string>
+ <string name="select_text" msgid="5139083974039906583">"Valitse"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Kuvakaappaus"</string>
+ <string name="close_text" msgid="4986518933445178928">"Sulje"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Sulje valikko"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
index ee6e7be45024..bc82f5123585 100644
--- a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"50 % dans le haut"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"30 % dans le haut"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Plein écran dans le bas"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Diviser à gauche"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Diviser à droite"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Diviser dans la partie supérieure"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Diviser dans la partie inférieure"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Utiliser le mode Une main"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Pour quitter, balayez l\'écran du bas vers le haut, ou touchez n\'importe où sur l\'écran en haut de l\'application"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Démarrer le mode Une main"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Fermer"</string>
<string name="back_button_text" msgid="1469718707134137085">"Retour"</string>
<string name="handle_text" msgid="1766582106752184456">"Identifiant"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Icône de l\'application"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Plein écran"</string>
<string name="desktop_text" msgid="1077633567027630454">"Mode Bureau"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Écran partagé"</string>
<string name="more_button_text" msgid="3655388105592893530">"Plus"</string>
<string name="float_button_text" msgid="9221657008391364581">"Flottant"</string>
+ <string name="select_text" msgid="5139083974039906583">"Sélectionner"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Capture d\'écran"</string>
+ <string name="close_text" msgid="4986518933445178928">"Fermer"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Fermer le menu"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-fr/strings.xml b/libs/WindowManager/Shell/res/values-fr/strings.xml
index c9fc0613260b..61b7fad839ab 100644
--- a/libs/WindowManager/Shell/res/values-fr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Écran du haut à 50 %"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Écran du haut à 30 %"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Écran du bas en plein écran"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Affichée à gauche"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Affichée à droite"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Affichée en haut"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Affichée en haut"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Utiliser le mode une main"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Pour quitter, balayez l\'écran de bas en haut ou appuyez n\'importe où au-dessus de l\'application"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Démarrer le mode une main"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Fermer"</string>
<string name="back_button_text" msgid="1469718707134137085">"Retour"</string>
<string name="handle_text" msgid="1766582106752184456">"Poignée"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Icône d\'application"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Plein écran"</string>
<string name="desktop_text" msgid="1077633567027630454">"Mode ordinateur"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Écran partagé"</string>
<string name="more_button_text" msgid="3655388105592893530">"Plus"</string>
<string name="float_button_text" msgid="9221657008391364581">"Flottante"</string>
+ <string name="select_text" msgid="5139083974039906583">"Sélectionner"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Capture d\'écran"</string>
+ <string name="close_text" msgid="4986518933445178928">"Fermer"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Fermer le menu"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-gl/strings.xml b/libs/WindowManager/Shell/res/values-gl/strings.xml
index 3e1a93fe424e..482519897401 100644
--- a/libs/WindowManager/Shell/res/values-gl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-gl/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"50 % arriba"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"30 % arriba"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Pantalla completa abaixo"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Dividir (esquerda)"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Dividir (dereita)"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Dividir (arriba)"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Dividir (abaixo)"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Como se usa o modo dunha soa man?"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Para saír, pasa o dedo cara arriba desde a parte inferior da pantalla ou toca calquera lugar da zona situada encima da aplicación"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Iniciar modo dunha soa man"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Pechar"</string>
<string name="back_button_text" msgid="1469718707134137085">"Atrás"</string>
<string name="handle_text" msgid="1766582106752184456">"Controlador"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Icona de aplicación"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Pantalla completa"</string>
<string name="desktop_text" msgid="1077633567027630454">"Modo de escritorio"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Pantalla dividida"</string>
<string name="more_button_text" msgid="3655388105592893530">"Máis"</string>
<string name="float_button_text" msgid="9221657008391364581">"Flotante"</string>
+ <string name="select_text" msgid="5139083974039906583">"Seleccionar"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Captura de pantalla"</string>
+ <string name="close_text" msgid="4986518933445178928">"Pechar"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Pechar o menú"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-gu/strings.xml b/libs/WindowManager/Shell/res/values-gu/strings.xml
index 24950f760e5a..c1eedf8dbf7d 100644
--- a/libs/WindowManager/Shell/res/values-gu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-gu/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"શીર્ષ 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"શીર્ષ 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"તળિયાની પૂર્ણ સ્ક્રીન"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"ડાબે વિભાજિત કરો"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"જમણે વિભાજિત કરો"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"ઉપર વિભાજિત કરો"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"નીચે વિભાજિત કરો"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"એક-હાથે વાપરો મોડનો ઉપયોગ કરી રહ્યાં છીએ"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"બહાર નીકળવા માટે, સ્ક્રીનની નીચેના ભાગથી ઉપરની તરફ સ્વાઇપ કરો અથવા ઍપના આઇકન પર ગમે ત્યાં ટૅપ કરો"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"એક-હાથે વાપરો મોડ શરૂ કરો"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"બંધ કરો"</string>
<string name="back_button_text" msgid="1469718707134137085">"પાછળ"</string>
<string name="handle_text" msgid="1766582106752184456">"હૅન્ડલ"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"ઍપનું આઇકન"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"પૂર્ણસ્ક્રીન"</string>
<string name="desktop_text" msgid="1077633567027630454">"ડેસ્કટૉપ મોડ"</string>
<string name="split_screen_text" msgid="1396336058129570886">"સ્ક્રીનને વિભાજિત કરો"</string>
<string name="more_button_text" msgid="3655388105592893530">"વધુ"</string>
<string name="float_button_text" msgid="9221657008391364581">"ફ્લોટિંગ વિન્ડો"</string>
+ <string name="select_text" msgid="5139083974039906583">"પસંદ કરો"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"સ્ક્રીનશૉટ"</string>
+ <string name="close_text" msgid="4986518933445178928">"બંધ કરો"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"મેનૂ બંધ કરો"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-hi/strings.xml b/libs/WindowManager/Shell/res/values-hi/strings.xml
index 9f36799092e1..a12a779c78a1 100644
--- a/libs/WindowManager/Shell/res/values-hi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hi/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"ऊपर की स्क्रीन को 50% बनाएं"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"ऊपर की स्क्रीन को 30% बनाएं"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"नीचे की स्क्रीन को फ़ुल स्क्रीन बनाएं"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"स्क्रीन को बाएं हिस्से में स्प्लिट करें"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"स्क्रीन को दाएं हिस्से में स्प्लिट करें"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"स्क्रीन को ऊपर के हिस्से में स्प्लिट करें"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"स्क्रीन को सबसे नीचे वाले हिस्से में स्प्लिट करें"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"वन-हैंडेड मोड का इस्तेमाल करना"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"इस मोड से बाहर निकलने के लिए, स्क्रीन के सबसे निचले हिस्से से ऊपर की ओर स्वाइप करें या ऐप्लिकेशन के बाहर कहीं भी टैप करें"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"वन-हैंडेड मोड चालू करें"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"बंद करें"</string>
<string name="back_button_text" msgid="1469718707134137085">"वापस जाएं"</string>
<string name="handle_text" msgid="1766582106752184456">"हैंडल"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"ऐप्लिकेशन आइकॉन"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"फ़ुलस्क्रीन"</string>
<string name="desktop_text" msgid="1077633567027630454">"डेस्कटॉप मोड"</string>
<string name="split_screen_text" msgid="1396336058129570886">"स्प्लिट स्क्रीन मोड"</string>
<string name="more_button_text" msgid="3655388105592893530">"ज़्यादा देखें"</string>
<string name="float_button_text" msgid="9221657008391364581">"फ़्लोट"</string>
+ <string name="select_text" msgid="5139083974039906583">"चुनें"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"स्क्रीनशॉट"</string>
+ <string name="close_text" msgid="4986518933445178928">"बंद करें"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"मेन्यू बंद करें"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-hr/strings.xml b/libs/WindowManager/Shell/res/values-hr/strings.xml
index 9459e4c5f2af..3ce055e0b879 100644
--- a/libs/WindowManager/Shell/res/values-hr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hr/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Gornji zaslon na 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Gornji zaslon na 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Donji zaslon u cijeli zaslon"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Podijeli lijevo"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Podijeli desno"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Podijeli gore"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Podijeli dolje"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Korištenje načina rada jednom rukom"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Za izlaz prijeđite prstom od dna zaslona prema gore ili dodirnite bio gdje iznad aplikacije"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Pokretanje načina rada jednom rukom"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Zatvori"</string>
<string name="back_button_text" msgid="1469718707134137085">"Natrag"</string>
<string name="handle_text" msgid="1766582106752184456">"Pokazivač"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Ikona aplikacije"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Puni zaslon"</string>
<string name="desktop_text" msgid="1077633567027630454">"Stolni način rada"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Razdvojeni zaslon"</string>
<string name="more_button_text" msgid="3655388105592893530">"Više"</string>
<string name="float_button_text" msgid="9221657008391364581">"Plutajući"</string>
+ <string name="select_text" msgid="5139083974039906583">"Odaberite"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Snimka zaslona"</string>
+ <string name="close_text" msgid="4986518933445178928">"Zatvorite"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Zatvorite izbornik"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-hu/strings.xml b/libs/WindowManager/Shell/res/values-hu/strings.xml
index fc9341b82c36..dc916610d3fc 100644
--- a/libs/WindowManager/Shell/res/values-hu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hu/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Felső 50%-ra"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Felső 30%-ra"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Alsó teljes képernyőre"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Osztás a képernyő bal oldalán"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Osztás a képernyő jobb oldalán"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Osztás a képernyő tetején"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Osztás alul"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Egykezes mód használata"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"A kilépéshez csúsztasson felfelé a képernyő aljáról, vagy koppintson az alkalmazás felett a képernyő bármelyik részére"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Egykezes mód indítása"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Bezárás"</string>
<string name="back_button_text" msgid="1469718707134137085">"Vissza"</string>
<string name="handle_text" msgid="1766582106752184456">"Fogópont"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Alkalmazásikon"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Teljes képernyő"</string>
<string name="desktop_text" msgid="1077633567027630454">"Asztali üzemmód"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Osztott képernyő"</string>
<string name="more_button_text" msgid="3655388105592893530">"Továbbiak"</string>
<string name="float_button_text" msgid="9221657008391364581">"Lebegő"</string>
+ <string name="select_text" msgid="5139083974039906583">"Kiválasztás"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Képernyőkép"</string>
+ <string name="close_text" msgid="4986518933445178928">"Bezárás"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Menü bezárása"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-hy/strings.xml b/libs/WindowManager/Shell/res/values-hy/strings.xml
index 6943532c17be..5c58634181f5 100644
--- a/libs/WindowManager/Shell/res/values-hy/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hy/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Վերևի էկրանը՝ 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Վերևի էկրանը՝ 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Ներքևի էկրանը՝ լիաէկրան"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Հավելվածը ձախ կողմում"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Հավելվածը աջ կողմում"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Հավելվածը վերևում"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Հավելվածը ներքևում"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Ինչպես օգտվել մեկ ձեռքի ռեժիմից"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Դուրս գալու համար մատը սահեցրեք էկրանի ներքևից վերև կամ հպեք հավելվածի վերևում որևէ տեղ։"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Գործարկել մեկ ձեռքի ռեժիմը"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Փակել"</string>
<string name="back_button_text" msgid="1469718707134137085">"Հետ"</string>
<string name="handle_text" msgid="1766582106752184456">"Նշիչ"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Հավելվածի պատկերակ"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Լիաէկրան"</string>
<string name="desktop_text" msgid="1077633567027630454">"Համակարգչի ռեժիմ"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Տրոհված էկրան"</string>
<string name="more_button_text" msgid="3655388105592893530">"Ավելին"</string>
<string name="float_button_text" msgid="9221657008391364581">"Լողացող պատուհան"</string>
+ <string name="select_text" msgid="5139083974039906583">"Ընտրել"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Սքրինշոթ"</string>
+ <string name="close_text" msgid="4986518933445178928">"Փակել"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Փակել ընտրացանկը"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-in/strings.xml b/libs/WindowManager/Shell/res/values-in/strings.xml
index 4fca32dfc812..c863c7099c29 100644
--- a/libs/WindowManager/Shell/res/values-in/strings.xml
+++ b/libs/WindowManager/Shell/res/values-in/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Atas 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Atas 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Layar penuh di bawah"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Pisahkan ke kiri"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Pisahkan ke kanan"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Pisahkan ke atas"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Pisahkan ke bawah"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Menggunakan mode satu tangan"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Untuk keluar, geser layar dari bawah ke atas atau ketuk di mana saja di atas aplikasi"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Mulai mode satu tangan"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Tutup"</string>
<string name="back_button_text" msgid="1469718707134137085">"Kembali"</string>
<string name="handle_text" msgid="1766582106752184456">"Tuas"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Ikon Aplikasi"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Layar Penuh"</string>
<string name="desktop_text" msgid="1077633567027630454">"Mode Desktop"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Layar Terpisah"</string>
<string name="more_button_text" msgid="3655388105592893530">"Lainnya"</string>
<string name="float_button_text" msgid="9221657008391364581">"Mengambang"</string>
+ <string name="select_text" msgid="5139083974039906583">"Pilih"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Screenshot"</string>
+ <string name="close_text" msgid="4986518933445178928">"Tutup"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Tutup Menu"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-is/strings.xml b/libs/WindowManager/Shell/res/values-is/strings.xml
index 1bc019e7f67e..9f1936ccbd37 100644
--- a/libs/WindowManager/Shell/res/values-is/strings.xml
+++ b/libs/WindowManager/Shell/res/values-is/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Efri 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Efri 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Neðri á öllum skjánum"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Skipta vinstra megin"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Skipta hægra megin"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Skipta efst"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Skipta neðst"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Notkun einhentrar stillingar"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Til að loka skaltu strjúka upp frá neðri hluta skjásins eða ýta hvar sem er fyrir ofan forritið"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Ræsa einhenta stillingu"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Loka"</string>
<string name="back_button_text" msgid="1469718707134137085">"Til baka"</string>
<string name="handle_text" msgid="1766582106752184456">"Handfang"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Tákn forrits"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Allur skjárinn"</string>
<string name="desktop_text" msgid="1077633567027630454">"Skjáborðsstilling"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Skjáskipting"</string>
<string name="more_button_text" msgid="3655388105592893530">"Meira"</string>
<string name="float_button_text" msgid="9221657008391364581">"Reikult"</string>
+ <string name="select_text" msgid="5139083974039906583">"Velja"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Skjámynd"</string>
+ <string name="close_text" msgid="4986518933445178928">"Loka"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Loka valmynd"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-it/strings.xml b/libs/WindowManager/Shell/res/values-it/strings.xml
index 8d2715a181de..2a955d58a76f 100644
--- a/libs/WindowManager/Shell/res/values-it/strings.xml
+++ b/libs/WindowManager/Shell/res/values-it/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Schermata superiore al 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Schermata superiore al 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Schermata inferiore a schermo intero"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Dividi a sinistra"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Dividi a destra"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Dividi in alto"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Dividi in basso"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Usare la modalità a una mano"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Per uscire, scorri verso l\'alto dalla parte inferiore dello schermo oppure tocca un punto qualsiasi sopra l\'app"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Avvia la modalità a una mano"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Chiudi"</string>
<string name="back_button_text" msgid="1469718707134137085">"Indietro"</string>
<string name="handle_text" msgid="1766582106752184456">"Handle"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Icona dell\'app"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Schermo intero"</string>
<string name="desktop_text" msgid="1077633567027630454">"Modalità desktop"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Schermo diviso"</string>
<string name="more_button_text" msgid="3655388105592893530">"Altro"</string>
<string name="float_button_text" msgid="9221657008391364581">"Mobile"</string>
+ <string name="select_text" msgid="5139083974039906583">"Seleziona"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Screenshot"</string>
+ <string name="close_text" msgid="4986518933445178928">"Chiudi"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Chiudi il menu"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-iw/strings.xml b/libs/WindowManager/Shell/res/values-iw/strings.xml
index 26f3236e5947..b1e71514bd60 100644
--- a/libs/WindowManager/Shell/res/values-iw/strings.xml
+++ b/libs/WindowManager/Shell/res/values-iw/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"עליון 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"למעלה 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"מסך תחתון מלא"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"פיצול שמאלה"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"פיצול ימינה"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"פיצול למעלה"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"פיצול למטה"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"איך להשתמש בתכונה \'מצב שימוש ביד אחת\'"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"כדי לצאת, יש להחליק למעלה מתחתית המסך או להקיש במקום כלשהו במסך מעל האפליקציה"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"הפעלה של מצב שימוש ביד אחת"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"סגירה"</string>
<string name="back_button_text" msgid="1469718707134137085">"חזרה"</string>
<string name="handle_text" msgid="1766582106752184456">"נקודת אחיזה"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"סמל האפליקציה"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"מסך מלא"</string>
<string name="desktop_text" msgid="1077633567027630454">"ממשק המחשב"</string>
<string name="split_screen_text" msgid="1396336058129570886">"מסך מפוצל"</string>
<string name="more_button_text" msgid="3655388105592893530">"עוד"</string>
<string name="float_button_text" msgid="9221657008391364581">"בלונים"</string>
+ <string name="select_text" msgid="5139083974039906583">"בחירה"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"צילום מסך"</string>
+ <string name="close_text" msgid="4986518933445178928">"סגירה"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"סגירת התפריט"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ja/strings.xml b/libs/WindowManager/Shell/res/values-ja/strings.xml
index 91fd724791fa..a765d8c28c6c 100644
--- a/libs/WindowManager/Shell/res/values-ja/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ja/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"上 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"上 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"下部全画面"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"左に分割"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"右に分割"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"上に分割"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"下に分割"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"片手モードの使用"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"終了するには、画面を下から上にスワイプするか、アプリの任意の場所をタップします"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"片手モードを開始します"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"閉じる"</string>
<string name="back_button_text" msgid="1469718707134137085">"戻る"</string>
<string name="handle_text" msgid="1766582106752184456">"ハンドル"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"アプリのアイコン"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"全画面表示"</string>
<string name="desktop_text" msgid="1077633567027630454">"デスクトップ モード"</string>
<string name="split_screen_text" msgid="1396336058129570886">"分割画面"</string>
<string name="more_button_text" msgid="3655388105592893530">"その他"</string>
<string name="float_button_text" msgid="9221657008391364581">"フローティング"</string>
+ <string name="select_text" msgid="5139083974039906583">"選択"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"スクリーンショット"</string>
+ <string name="close_text" msgid="4986518933445178928">"閉じる"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"メニューを閉じる"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ka/strings.xml b/libs/WindowManager/Shell/res/values-ka/strings.xml
index a711afd5e39e..51f05225dd53 100644
--- a/libs/WindowManager/Shell/res/values-ka/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ka/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"ზედა ეკრანი — 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"ზედა ეკრანი — 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"ქვედა ნაწილის სრულ ეკრანზე გაშლა"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"გაყოფა მარცხნივ"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"გაყოფა მარჯვნივ"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"გაყოფა ზემოთ"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"გაყოფა ქვემოთ"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"ცალი ხელის რეჟიმის გამოყენება"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"გასასვლელად გადაფურცლეთ ეკრანის ქვედა კიდიდან ზემოთ ან შეეხეთ ნებისმიერ ადგილას აპის ზემოთ"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"ცალი ხელის რეჟიმის დაწყება"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"დახურვა"</string>
<string name="back_button_text" msgid="1469718707134137085">"უკან"</string>
<string name="handle_text" msgid="1766582106752184456">"იდენტიფიკატორი"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"აპის ხატულა"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"სრულ ეკრანზე"</string>
<string name="desktop_text" msgid="1077633567027630454">"დესკტოპის რეჟიმი"</string>
<string name="split_screen_text" msgid="1396336058129570886">"ეკრანის გაყოფა"</string>
<string name="more_button_text" msgid="3655388105592893530">"სხვა"</string>
<string name="float_button_text" msgid="9221657008391364581">"ფარფატი"</string>
+ <string name="select_text" msgid="5139083974039906583">"არჩევა"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"ეკრანის ანაბეჭდი"</string>
+ <string name="close_text" msgid="4986518933445178928">"დახურვა"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"მენიუს დახურვა"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-kk/strings.xml b/libs/WindowManager/Shell/res/values-kk/strings.xml
index a2e868805d08..4fe2604ca230 100644
--- a/libs/WindowManager/Shell/res/values-kk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-kk/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"50% жоғарғы жақта"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"30% жоғарғы жақта"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Төменгісін толық экранға шығару"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Сол жақтан шығару"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Оң жақтан шығару"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Жоғарыдан шығару"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Астынан шығару"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Бір қолмен енгізу режимін пайдалану"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Шығу үшін экранның төменгі жағынан жоғары қарай сырғытыңыз немесе қолданбаның үстінен кез келген жерден түртіңіз."</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Бір қолмен енгізу режимін іске қосу"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Жабу"</string>
<string name="back_button_text" msgid="1469718707134137085">"Артқа"</string>
<string name="handle_text" msgid="1766582106752184456">"Идентификатор"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Қолданба белгішесі"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Толық экран"</string>
<string name="desktop_text" msgid="1077633567027630454">"Компьютер режимі"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Экранды бөлу"</string>
<string name="more_button_text" msgid="3655388105592893530">"Қосымша"</string>
<string name="float_button_text" msgid="9221657008391364581">"Қалқыма"</string>
+ <string name="select_text" msgid="5139083974039906583">"Таңдау"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Скриншот"</string>
+ <string name="close_text" msgid="4986518933445178928">"Жабу"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Мәзірді жабу"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-km/strings.xml b/libs/WindowManager/Shell/res/values-km/strings.xml
index 7a486b86747c..f590055da0ad 100644
--- a/libs/WindowManager/Shell/res/values-km/strings.xml
+++ b/libs/WindowManager/Shell/res/values-km/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"ខាងលើ 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"ខាងលើ 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"អេក្រង់ពេញខាងក្រោម"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"បំបែក​ខាងឆ្វេង"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"បំបែក​ខាងស្ដាំ"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"បំបែក​ខាងលើ"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"បំបែក​ខាងក្រោម"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"កំពុងប្រើ​មុខងារប្រើដៃម្ខាង"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"ដើម្បីចាកចេញ សូមអូសឡើងលើ​ពីផ្នែកខាងក្រោមអេក្រង់ ឬចុចផ្នែកណាមួយ​នៅខាងលើកម្មវិធី"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"ចាប់ផ្ដើម​មុខងារប្រើដៃម្ខាង"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"បិទ"</string>
<string name="back_button_text" msgid="1469718707134137085">"ថយក្រោយ"</string>
<string name="handle_text" msgid="1766582106752184456">"ឈ្មោះអ្នកប្រើប្រាស់"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"រូប​កម្មវិធី"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"អេក្រង់​ពេញ"</string>
<string name="desktop_text" msgid="1077633567027630454">"មុខងារកុំព្យូទ័រ"</string>
<string name="split_screen_text" msgid="1396336058129570886">"មុខងារ​បំបែក​អេក្រង់"</string>
<string name="more_button_text" msgid="3655388105592893530">"ច្រើនទៀត"</string>
<string name="float_button_text" msgid="9221657008391364581">"អណ្ដែត"</string>
+ <string name="select_text" msgid="5139083974039906583">"ជ្រើសរើស"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"រូបថតអេក្រង់"</string>
+ <string name="close_text" msgid="4986518933445178928">"បិទ"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"បិទ​ម៉ឺនុយ"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-kn/strings.xml b/libs/WindowManager/Shell/res/values-kn/strings.xml
index 5fcdcf2c8fac..22030eb3dab6 100644
--- a/libs/WindowManager/Shell/res/values-kn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-kn/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"50% ಮೇಲಕ್ಕೆ"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"30% ಮೇಲಕ್ಕೆ"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"ಕೆಳಗಿನ ಪೂರ್ಣ ಪರದೆ"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"ಎಡಕ್ಕೆ ವಿಭಜಿಸಿ"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"ಬಲಕ್ಕೆ ವಿಭಜಿಸಿ"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"ಮೇಲಕ್ಕೆ ವಿಭಜಿಸಿ"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"ಕೆಳಕ್ಕೆ ವಿಭಜಿಸಿ"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"ಒಂದು ಕೈ ಮೋಡ್ ಬಳಸುವುದರ ಬಗ್ಗೆ"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"ನಿರ್ಗಮಿಸಲು, ಸ್ಕ್ರೀನ್‌ನ ಕೆಳಗಿನಿಂದ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ ಅಥವಾ ಆ್ಯಪ್‌ನ ಮೇಲೆ ಎಲ್ಲಿಯಾದರೂ ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"ಒಂದು ಕೈ ಮೋಡ್ ಅನ್ನು ಪ್ರಾರಂಭಿಸಿ"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"ಮುಚ್ಚಿರಿ"</string>
<string name="back_button_text" msgid="1469718707134137085">"ಹಿಂದಕ್ಕೆ"</string>
<string name="handle_text" msgid="1766582106752184456">"ಹ್ಯಾಂಡಲ್"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"ಆ್ಯಪ್ ಐಕಾನ್"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"ಫುಲ್‌ಸ್ಕ್ರೀನ್"</string>
<string name="desktop_text" msgid="1077633567027630454">"ಡೆಸ್ಕ್‌ಟಾಪ್ ಮೋಡ್"</string>
<string name="split_screen_text" msgid="1396336058129570886">"ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್"</string>
<string name="more_button_text" msgid="3655388105592893530">"ಇನ್ನಷ್ಟು"</string>
<string name="float_button_text" msgid="9221657008391364581">"ಫ್ಲೋಟ್"</string>
+ <string name="select_text" msgid="5139083974039906583">"ಆಯ್ಕೆಮಾಡಿ"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್"</string>
+ <string name="close_text" msgid="4986518933445178928">"ಮುಚ್ಚಿ"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"ಮೆನು ಮುಚ್ಚಿ"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ko/strings.xml b/libs/WindowManager/Shell/res/values-ko/strings.xml
index 74cff1f5b13e..4f4d0c5f5edf 100644
--- a/libs/WindowManager/Shell/res/values-ko/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ko/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"위쪽 화면 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"위쪽 화면 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"아래쪽 화면 전체화면"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"왼쪽으로 분할"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"오른쪽으로 분할"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"위쪽으로 분할"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"아래쪽으로 분할"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"한 손 사용 모드 사용하기"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"화면 하단에서 위로 스와이프하거나 앱 상단을 탭하여 종료합니다."</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"한 손 사용 모드 시작"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"닫기"</string>
<string name="back_button_text" msgid="1469718707134137085">"뒤로"</string>
<string name="handle_text" msgid="1766582106752184456">"핸들"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"앱 아이콘"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"전체 화면"</string>
<string name="desktop_text" msgid="1077633567027630454">"데스크톱 모드"</string>
<string name="split_screen_text" msgid="1396336058129570886">"화면 분할"</string>
<string name="more_button_text" msgid="3655388105592893530">"더보기"</string>
<string name="float_button_text" msgid="9221657008391364581">"플로팅"</string>
+ <string name="select_text" msgid="5139083974039906583">"선택"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"스크린샷"</string>
+ <string name="close_text" msgid="4986518933445178928">"닫기"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"메뉴 닫기"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ky/strings.xml b/libs/WindowManager/Shell/res/values-ky/strings.xml
index 477c65d2e68e..4305e9051ebc 100644
--- a/libs/WindowManager/Shell/res/values-ky/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ky/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Үстүнкү экранды 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Үстүнкү экранды 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Ылдыйкы экранды толук экран режимине өткөрүү"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Солго бөлүү"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Оңго бөлүү"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Өйдө бөлүү"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Ылдый бөлүү"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Бир кол режимин колдонуу"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Чыгуу үчүн экранды ылдый жагынан өйдө сүрүңүз же колдонмонун өйдө жагын басыңыз"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Бир кол режимин баштоо"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Жабуу"</string>
<string name="back_button_text" msgid="1469718707134137085">"Артка"</string>
<string name="handle_text" msgid="1766582106752184456">"Маркер"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Колдонмонун сүрөтчөсү"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Толук экран"</string>
<string name="desktop_text" msgid="1077633567027630454">"Компьютер режими"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Экранды бөлүү"</string>
<string name="more_button_text" msgid="3655388105592893530">"Дагы"</string>
<string name="float_button_text" msgid="9221657008391364581">"Калкыма"</string>
+ <string name="select_text" msgid="5139083974039906583">"Тандоо"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Скриншот"</string>
+ <string name="close_text" msgid="4986518933445178928">"Жабуу"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Менюну жабуу"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-lo/strings.xml b/libs/WindowManager/Shell/res/values-lo/strings.xml
index 81b082600f76..1926b33f9169 100644
--- a/libs/WindowManager/Shell/res/values-lo/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lo/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"ເທິງສຸດ 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"ເທິງສຸດ 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"ເຕັມໜ້າຈໍລຸ່ມສຸດ"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"ແຍກຊ້າຍ"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"ແຍກຂວາ"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"ແຍກເທິງ"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"ແຍກລຸ່ມ"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"ກຳລັງໃຊ້ໂໝດມືດຽວ"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"ເພື່ອອອກ, ໃຫ້ປັດຂຶ້ນຈາກລຸ່ມສຸດຂອງໜ້າຈໍ ຫຼື ແຕະບ່ອນໃດກໍໄດ້ຢູ່ເໜືອແອັບ"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"ເລີ່ມໂໝດມືດຽວ"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"ປິດ"</string>
<string name="back_button_text" msgid="1469718707134137085">"ກັບຄືນ"</string>
<string name="handle_text" msgid="1766582106752184456">"ມືບັງຄັບ"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"ໄອຄອນແອັບ"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"ເຕັມຈໍ"</string>
<string name="desktop_text" msgid="1077633567027630454">"ໂໝດເດັສທັອບ"</string>
<string name="split_screen_text" msgid="1396336058129570886">"ແບ່ງໜ້າຈໍ"</string>
<string name="more_button_text" msgid="3655388105592893530">"ເພີ່ມເຕີມ"</string>
<string name="float_button_text" msgid="9221657008391364581">"ລອຍ"</string>
+ <string name="select_text" msgid="5139083974039906583">"ເລືອກ"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"ຮູບໜ້າຈໍ"</string>
+ <string name="close_text" msgid="4986518933445178928">"ປິດ"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"ປິດເມນູ"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-lt/strings.xml b/libs/WindowManager/Shell/res/values-lt/strings.xml
index 0447ec7b2797..d3dc1b0cab41 100644
--- a/libs/WindowManager/Shell/res/values-lt/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lt/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Viršutinis ekranas 50 %"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Viršutinis ekranas 30 %"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Apatinis ekranas viso ekrano režimu"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Išskaidyti kairėn"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Išskaidyti dešinėn"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Išskaidyti viršuje"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Išskaidyti apačioje"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Vienos rankos režimo naudojimas"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Jei norite išeiti, perbraukite aukštyn nuo ekrano apačios arba palieskite bet kur virš programos"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Pradėti vienos rankos režimą"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Uždaryti"</string>
<string name="back_button_text" msgid="1469718707134137085">"Atgal"</string>
<string name="handle_text" msgid="1766582106752184456">"Rankenėlė"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Programos piktograma"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Visas ekranas"</string>
<string name="desktop_text" msgid="1077633567027630454">"Stalinio kompiuterio režimas"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Išskaidyto ekrano režimas"</string>
<string name="more_button_text" msgid="3655388105592893530">"Daugiau"</string>
<string name="float_button_text" msgid="9221657008391364581">"Slankusis langas"</string>
+ <string name="select_text" msgid="5139083974039906583">"Pasirinkti"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Ekrano kopija"</string>
+ <string name="close_text" msgid="4986518933445178928">"Uždaryti"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Uždaryti meniu"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-lv/strings.xml b/libs/WindowManager/Shell/res/values-lv/strings.xml
index e612ddda69eb..74ec371b481f 100644
--- a/libs/WindowManager/Shell/res/values-lv/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lv/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Augšdaļa 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Augšdaļa 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Apakšdaļu pa visu ekrānu"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Sadalījums pa kreisi"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Sadalījums pa labi"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Sadalījums augšdaļā"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Sadalījums apakšdaļā"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Vienas rokas režīma izmantošana"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Lai izietu, velciet augšup no ekrāna apakšdaļas vai pieskarieties jebkurā vietā virs lietotnes"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Pāriet vienas rokas režīmā"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Aizvērt"</string>
<string name="back_button_text" msgid="1469718707134137085">"Atpakaļ"</string>
<string name="handle_text" msgid="1766582106752184456">"Turis"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Lietotnes ikona"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Pilnekrāna režīms"</string>
<string name="desktop_text" msgid="1077633567027630454">"Darbvirsmas režīms"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Sadalīt ekrānu"</string>
<string name="more_button_text" msgid="3655388105592893530">"Vairāk"</string>
<string name="float_button_text" msgid="9221657008391364581">"Peldošs"</string>
+ <string name="select_text" msgid="5139083974039906583">"Atlasīt"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Ekrānuzņēmums"</string>
+ <string name="close_text" msgid="4986518933445178928">"Aizvērt"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Aizvērt izvēlni"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-mk/strings.xml b/libs/WindowManager/Shell/res/values-mk/strings.xml
index 3c5449c22690..a809aa7d030f 100644
--- a/libs/WindowManager/Shell/res/values-mk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mk/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Горниот 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Горниот 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Долниот на цел екран"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Подели налево"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Подели надесно"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Подели нагоре"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Подели долу"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Користење на режимот со една рака"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"За да излезете, повлечете нагоре од дното на екранот или допрете каде било над апликацијата"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Започни го режимот со една рака"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Затвори"</string>
<string name="back_button_text" msgid="1469718707134137085">"Назад"</string>
<string name="handle_text" msgid="1766582106752184456">"Прекар"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Икона на апликацијата"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Цел екран"</string>
<string name="desktop_text" msgid="1077633567027630454">"Режим за компјутер"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Поделен екран"</string>
<string name="more_button_text" msgid="3655388105592893530">"Повеќе"</string>
<string name="float_button_text" msgid="9221657008391364581">"Лебдечко"</string>
+ <string name="select_text" msgid="5139083974039906583">"Изберете"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Слика од екранот"</string>
+ <string name="close_text" msgid="4986518933445178928">"Затворете"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Затворете го менито"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ml/strings.xml b/libs/WindowManager/Shell/res/values-ml/strings.xml
index 0df5c3a84a42..ffa73b09f06e 100644
--- a/libs/WindowManager/Shell/res/values-ml/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ml/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"മുകളിൽ 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"മുകളിൽ 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"താഴെ പൂർണ്ണ സ്ക്രീൻ"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"ഇടത് ഭാഗത്തേക്ക് വിഭജിക്കുക"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"വലത് ഭാഗത്തേക്ക് വിഭജിക്കുക"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"മുകളിലേക്ക് വിഭജിക്കുക"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"താഴേക്ക് വിഭജിക്കുക"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"ഒറ്റക്കൈ മോഡ് എങ്ങനെ ഉപയോഗിക്കാം"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"പുറത്ത് കടക്കാൻ, സ്ക്രീനിന്റെ ചുവടെ നിന്ന് മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്യുക അല്ലെങ്കിൽ ആപ്പിന് മുകളിലായി എവിടെയെങ്കിലും ടാപ്പ് ചെയ്യുക"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"ഒറ്റക്കൈ മോഡ് ആരംഭിച്ചു"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"അടയ്ക്കുക"</string>
<string name="back_button_text" msgid="1469718707134137085">"മടങ്ങുക"</string>
<string name="handle_text" msgid="1766582106752184456">"ഹാൻഡിൽ"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"ആപ്പ് ഐക്കൺ"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"പൂർണ്ണസ്ക്രീൻ"</string>
<string name="desktop_text" msgid="1077633567027630454">"ഡെസ്‌ക്ടോപ്പ് മോഡ്"</string>
<string name="split_screen_text" msgid="1396336058129570886">"സ്‌ക്രീൻ വിഭജനം"</string>
<string name="more_button_text" msgid="3655388105592893530">"കൂടുതൽ"</string>
<string name="float_button_text" msgid="9221657008391364581">"ഫ്ലോട്ട്"</string>
+ <string name="select_text" msgid="5139083974039906583">"തിരഞ്ഞെടുക്കുക"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"സ്ക്രീൻഷോട്ട്"</string>
+ <string name="close_text" msgid="4986518933445178928">"അടയ്ക്കുക"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"മെനു അടയ്ക്കുക"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-mn/strings.xml b/libs/WindowManager/Shell/res/values-mn/strings.xml
index 5f9d3db43e41..8b15bf90758c 100644
--- a/libs/WindowManager/Shell/res/values-mn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mn/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Дээд 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Дээд 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Доод бүтэн дэлгэц"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Зүүн талд хуваах"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Баруун талд хуваах"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Дээд талд хуваах"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Доод талд хуваах"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Нэг гарын горимыг ашиглаж байна"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Гарахын тулд дэлгэцийн доод хэсгээс дээш шударч эсвэл апп дээр хүссэн газраа товшино уу"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Нэг гарын горимыг эхлүүлэх"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Хаах"</string>
<string name="back_button_text" msgid="1469718707134137085">"Буцах"</string>
<string name="handle_text" msgid="1766582106752184456">"Бариул"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Aппын дүрс тэмдэг"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Бүтэн дэлгэц"</string>
<string name="desktop_text" msgid="1077633567027630454">"Дэлгэцийн горим"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Дэлгэцийг хуваах"</string>
<string name="more_button_text" msgid="3655388105592893530">"Бусад"</string>
<string name="float_button_text" msgid="9221657008391364581">"Хөвөгч"</string>
+ <string name="select_text" msgid="5139083974039906583">"Сонгох"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Дэлгэцийн агшин"</string>
+ <string name="close_text" msgid="4986518933445178928">"Хаах"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Цэсийг хаах"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-mr/strings.xml b/libs/WindowManager/Shell/res/values-mr/strings.xml
index 4e29c11b2299..3e30871a96fe 100644
--- a/libs/WindowManager/Shell/res/values-mr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mr/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"शीर्ष 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"शीर्ष 10"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"तळाशी फुल स्क्रीन"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"डावीकडे स्प्लिट करा"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"उजवीकडे स्प्लिट करा"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"सर्वात वरती स्प्लिट करा"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"खालती स्प्लिट करा"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"एकहाती मोड वापरणे"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"बाहेर पडण्यासाठी स्क्रीनच्या खालून वरच्या दिशेने स्वाइप करा किंवा ॲपवर कोठेही टॅप करा"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"एकहाती मोड सुरू करा"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"बंद करा"</string>
<string name="back_button_text" msgid="1469718707134137085">"मागे जा"</string>
<string name="handle_text" msgid="1766582106752184456">"हँडल"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"अ‍ॅप आयकन"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"फुलस्‍क्रीन"</string>
<string name="desktop_text" msgid="1077633567027630454">"डेस्कटॉप मोड"</string>
<string name="split_screen_text" msgid="1396336058129570886">"स्प्लिट स्क्रीन"</string>
<string name="more_button_text" msgid="3655388105592893530">"आणखी"</string>
<string name="float_button_text" msgid="9221657008391364581">"फ्लोट"</string>
+ <string name="select_text" msgid="5139083974039906583">"निवडा"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"स्क्रीनशॉट"</string>
+ <string name="close_text" msgid="4986518933445178928">"बंद करा"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"मेनू बंद करा"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ms/strings.xml b/libs/WindowManager/Shell/res/values-ms/strings.xml
index 27844728b8aa..259930c6a3f6 100644
--- a/libs/WindowManager/Shell/res/values-ms/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ms/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Atas 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Atas 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Skrin penuh bawah"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Pisah kiri"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Pisah kanan"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Pisah atas"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Pisah bawah"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Menggunakan mod sebelah tangan"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Untuk keluar, leret ke atas daripada bahagian bawah skrin atau ketik pada mana-mana di bahagian atas apl"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Mulakan mod sebelah tangan"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Tutup"</string>
<string name="back_button_text" msgid="1469718707134137085">"Kembali"</string>
<string name="handle_text" msgid="1766582106752184456">"Pemegang"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Ikon Apl"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Skrin penuh"</string>
<string name="desktop_text" msgid="1077633567027630454">"Mod Desktop"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Skrin Pisah"</string>
<string name="more_button_text" msgid="3655388105592893530">"Lagi"</string>
<string name="float_button_text" msgid="9221657008391364581">"Terapung"</string>
+ <string name="select_text" msgid="5139083974039906583">"Pilih"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Tangkapan skrin"</string>
+ <string name="close_text" msgid="4986518933445178928">"Tutup"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Tutup Menu"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-my/strings.xml b/libs/WindowManager/Shell/res/values-my/strings.xml
index 2b781069695f..5e5f79ab6b6c 100644
--- a/libs/WindowManager/Shell/res/values-my/strings.xml
+++ b/libs/WindowManager/Shell/res/values-my/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"အပေါ်ဘက် မျက်နှာပြင် ၅၀%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"အပေါ်ဘက် မျက်နှာပြင် ၃၀%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"အောက်ခြေ မျက်နှာပြင်အပြည့်"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"ဘယ်ဘက်ကို ခွဲရန်"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"ညာဘက်ကို ခွဲရန်"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"ထိပ်ပိုင်းကို ခွဲရန်"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"အောက်ခြေကို ခွဲရန်"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"လက်တစ်ဖက်သုံးမုဒ် အသုံးပြုခြင်း"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"ထွက်ရန် ဖန်သားပြင်၏အောက်ခြေမှ အပေါ်သို့ပွတ်ဆွဲပါ သို့မဟုတ် အက်ပ်အပေါ်ဘက် မည်သည့်နေရာတွင်မဆို တို့ပါ"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"လက်တစ်ဖက်သုံးမုဒ်ကို စတင်လိုက်သည်"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"ပိတ်ရန်"</string>
<string name="back_button_text" msgid="1469718707134137085">"နောက်သို့"</string>
<string name="handle_text" msgid="1766582106752184456">"သုံးသူအမည်"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"အက်ပ်သင်္ကေတ"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"ဖန်သားပြင်အပြည့်"</string>
<string name="desktop_text" msgid="1077633567027630454">"ဒက်စ်တော့မုဒ်"</string>
<string name="split_screen_text" msgid="1396336058129570886">"မျက်နှာပြင် ခွဲ၍ပြသရန်"</string>
<string name="more_button_text" msgid="3655388105592893530">"ပိုပြပါ"</string>
<string name="float_button_text" msgid="9221657008391364581">"မျှောရန်"</string>
+ <string name="select_text" msgid="5139083974039906583">"ရွေးရန်"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"ဖန်သားပြင်ဓာတ်ပုံ"</string>
+ <string name="close_text" msgid="4986518933445178928">"ပိတ်ရန်"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"မီနူး ပိတ်ရန်"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-nb/strings.xml b/libs/WindowManager/Shell/res/values-nb/strings.xml
index 3e7c63a53bfc..2c53a7c59299 100644
--- a/libs/WindowManager/Shell/res/values-nb/strings.xml
+++ b/libs/WindowManager/Shell/res/values-nb/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Sett størrelsen på den øverste delen av skjermen til 50 %"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Sett størrelsen på den øverste delen av skjermen til 30 %"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Utvid den nederste delen av skjermen til hele skjermen"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Del opp til venstre"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Del opp til høyre"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Del opp øverst"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Del opp nederst"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Bruk av enhåndsmodus"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"For å avslutte, sveip opp fra bunnen av skjermen eller trykk hvor som helst over appen"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Start enhåndsmodus"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Lukk"</string>
<string name="back_button_text" msgid="1469718707134137085">"Tilbake"</string>
<string name="handle_text" msgid="1766582106752184456">"Håndtak"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Appikon"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Fullskjerm"</string>
<string name="desktop_text" msgid="1077633567027630454">"Skrivebordmodus"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Delt skjerm"</string>
<string name="more_button_text" msgid="3655388105592893530">"Mer"</string>
<string name="float_button_text" msgid="9221657008391364581">"Svevende"</string>
+ <string name="select_text" msgid="5139083974039906583">"Velg"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Skjermdump"</string>
+ <string name="close_text" msgid="4986518933445178928">"Lukk"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Lukk menyen"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ne/strings.xml b/libs/WindowManager/Shell/res/values-ne/strings.xml
index 1865ee5b5102..38dbd15cd3f2 100644
--- a/libs/WindowManager/Shell/res/values-ne/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ne/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"माथिल्लो भाग ५०%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"माथिल्लो भाग ३०%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"तल्लो भाग फुल स्क्रिन"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"बायाँतिर स्प्लिट गर्नुहोस्"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"दायाँतिर स्प्लिट गर्नुहोस्"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"सिरानतिर स्प्लिट गर्नुहोस्"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"पुछारतिर स्प्लिट गर्नुहोस्"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"एक हाते मोड प्रयोग गरिँदै छ"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"बाहिर निस्कन, स्क्रिनको पुछारबाट माथितिर स्वाइप गर्नुहोस् वा एपभन्दा माथि जुनसुकै ठाउँमा ट्याप गर्नुहोस्"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"एक हाते मोड सुरु गर्नुहोस्"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"बन्द गर्नुहोस्"</string>
<string name="back_button_text" msgid="1469718707134137085">"पछाडि"</string>
<string name="handle_text" msgid="1766582106752184456">"ह्यान्डल"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"एपको आइकन"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"फुल स्क्रिन"</string>
<string name="desktop_text" msgid="1077633567027630454">"डेस्कटप मोड"</string>
<string name="split_screen_text" msgid="1396336058129570886">"स्प्लिट स्क्रिन"</string>
<string name="more_button_text" msgid="3655388105592893530">"थप"</string>
<string name="float_button_text" msgid="9221657008391364581">"फ्लोट"</string>
+ <string name="select_text" msgid="5139083974039906583">"चयन गर्नुहोस्"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"स्क्रिनसट"</string>
+ <string name="close_text" msgid="4986518933445178928">"बन्द गर्नुहोस्"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"मेनु बन्द गर्नुहोस्"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-night/colors.xml b/libs/WindowManager/Shell/res/values-night/colors.xml
index 83c4d93982f4..5c6bb57a7f1c 100644
--- a/libs/WindowManager/Shell/res/values-night/colors.xml
+++ b/libs/WindowManager/Shell/res/values-night/colors.xml
@@ -15,6 +15,7 @@
-->
<resources>
+ <color name="docked_divider_handle">#ffffff</color>
<!-- Bubbles -->
<color name="bubbles_icon_tint">@color/GM2_grey_200</color>
<!-- Splash screen-->
diff --git a/libs/WindowManager/Shell/res/values-nl/strings.xml b/libs/WindowManager/Shell/res/values-nl/strings.xml
index 91437ac2302f..9cb7ddcf5284 100644
--- a/libs/WindowManager/Shell/res/values-nl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-nl/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Bovenste scherm 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Bovenste scherm 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Onderste scherm op volledig scherm"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Gesplitst scherm links"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Gesplitst scherm rechts"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Gesplitst scherm boven"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Gesplitst scherm onder"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Bediening met 1 hand gebruiken"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Als je wilt afsluiten, swipe je omhoog vanaf de onderkant van het scherm of tik je ergens boven de app"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Bediening met 1 hand starten"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Sluiten"</string>
<string name="back_button_text" msgid="1469718707134137085">"Terug"</string>
<string name="handle_text" msgid="1766582106752184456">"Gebruikersnaam"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"App-icoon"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Volledig scherm"</string>
<string name="desktop_text" msgid="1077633567027630454">"Desktopmodus"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Gesplitst scherm"</string>
<string name="more_button_text" msgid="3655388105592893530">"Meer"</string>
<string name="float_button_text" msgid="9221657008391364581">"Zwevend"</string>
+ <string name="select_text" msgid="5139083974039906583">"Selecteren"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Screenshot"</string>
+ <string name="close_text" msgid="4986518933445178928">"Sluiten"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Menu sluiten"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-or/strings.xml b/libs/WindowManager/Shell/res/values-or/strings.xml
index d330749c82d3..c3bed0a0535c 100644
--- a/libs/WindowManager/Shell/res/values-or/strings.xml
+++ b/libs/WindowManager/Shell/res/values-or/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"ଉପର ଆଡ଼କୁ 50% କରନ୍ତୁ"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"ଉପର ଆଡ଼କୁ 30% କରନ୍ତୁ"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"ତଳ ଅଂଶର ପୂର୍ଣ୍ଣ ସ୍କ୍ରୀନ୍‍"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"ବାମପଟକୁ ସ୍ପ୍ଲିଟ କରନ୍ତୁ"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"ଡାହାଣପଟକୁ ସ୍ପ୍ଲିଟ କରନ୍ତୁ"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"ଶୀର୍ଷକୁ ସ୍ପ୍ଲିଟ କରନ୍ତୁ"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"ନିମ୍ନକୁ ସ୍ଲିଟ କରନ୍ତୁ"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"ଏକ-ହାତ ମୋଡ୍ ବ୍ୟବହାର କରି"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"ବାହାରି ଯିବା ପାଇଁ, ସ୍କ୍ରିନର ତଳୁ ଉପରକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ କିମ୍ବା ଆପରେ ଯେ କୌଣସି ସ୍ଥାନରେ ଟାପ୍ କରନ୍ତୁ"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"ଏକ-ହାତ ମୋଡ୍ ଆରମ୍ଭ କରନ୍ତୁ"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"ବନ୍ଦ କରନ୍ତୁ"</string>
<string name="back_button_text" msgid="1469718707134137085">"ପଛକୁ ଫେରନ୍ତୁ"</string>
<string name="handle_text" msgid="1766582106752184456">"ହେଣ୍ଡେଲ"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"ଆପ ଆଇକନ"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"ପୂର୍ଣ୍ଣସ୍କ୍ରିନ"</string>
<string name="desktop_text" msgid="1077633567027630454">"ଡେସ୍କଟପ ମୋଡ"</string>
<string name="split_screen_text" msgid="1396336058129570886">"ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନ"</string>
<string name="more_button_text" msgid="3655388105592893530">"ଅଧିକ"</string>
<string name="float_button_text" msgid="9221657008391364581">"ଫ୍ଲୋଟ"</string>
+ <string name="select_text" msgid="5139083974039906583">"ଚୟନ କରନ୍ତୁ"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"ସ୍କ୍ରିନସଟ"</string>
+ <string name="close_text" msgid="4986518933445178928">"ବନ୍ଦ କରନ୍ତୁ"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"ମେନୁ ବନ୍ଦ କରନ୍ତୁ"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-pa/strings.xml b/libs/WindowManager/Shell/res/values-pa/strings.xml
index 51d491b50c40..5a1611d830b4 100644
--- a/libs/WindowManager/Shell/res/values-pa/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pa/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"ਉੱਪਰ 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"ਉੱਪਰ 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"ਹੇਠਾਂ ਪੂਰੀ ਸਕ੍ਰੀਨ"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"ਖੱਬੇ ਪਾਸੇ ਵੰਡੋ"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"ਸੱਜੇ ਪਾਸੇ ਵੰਡੋ"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"ਸਿਖਰ \'ਤੇ ਵੰਡੋ"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"ਹੇਠਾਂ ਵੰਡੋ"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"ਇੱਕ ਹੱਥ ਮੋਡ ਵਰਤਣਾ"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"ਬਾਹਰ ਜਾਣ ਲਈ, ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਾਂ ਤੋਂ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ ਜਾਂ ਐਪ \'ਤੇ ਕਿਤੇ ਵੀ ਟੈਪ ਕਰੋ"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"ਇੱਕ ਹੱਥ ਮੋਡ ਸ਼ੁਰੂ ਕਰੋ"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"ਬੰਦ ਕਰੋ"</string>
<string name="back_button_text" msgid="1469718707134137085">"ਪਿੱਛੇ"</string>
<string name="handle_text" msgid="1766582106752184456">"ਹੈਂਡਲ"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"ਐਪ ਪ੍ਰਤੀਕ"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"ਪੂਰੀ-ਸਕ੍ਰੀਨ"</string>
<string name="desktop_text" msgid="1077633567027630454">"ਡੈਸਕਟਾਪ ਮੋਡ"</string>
<string name="split_screen_text" msgid="1396336058129570886">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ"</string>
<string name="more_button_text" msgid="3655388105592893530">"ਹੋਰ"</string>
<string name="float_button_text" msgid="9221657008391364581">"ਫ਼ਲੋਟ"</string>
+ <string name="select_text" msgid="5139083974039906583">"ਚੁਣੋ"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"ਸਕ੍ਰੀਨਸ਼ਾਟ"</string>
+ <string name="close_text" msgid="4986518933445178928">"ਬੰਦ ਕਰੋ"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"ਮੀਨੂ ਬੰਦ ਕਰੋ"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-pl/strings.xml b/libs/WindowManager/Shell/res/values-pl/strings.xml
index 32e9840ac791..9f92538a5cb1 100644
--- a/libs/WindowManager/Shell/res/values-pl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pl/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"50% górnej części ekranu"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"30% górnej części ekranu"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Dolna część ekranu na pełnym ekranie"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Podziel po lewej"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Podziel po prawej"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Podziel u góry"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Podziel u dołu"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Korzystanie z trybu jednej ręki"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Aby zamknąć, przesuń palcem z dołu ekranu w górę lub kliknij dowolne miejsce nad aplikacją"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Uruchom tryb jednej ręki"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Zamknij"</string>
<string name="back_button_text" msgid="1469718707134137085">"Wstecz"</string>
<string name="handle_text" msgid="1766582106752184456">"Uchwyt"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Ikona aplikacji"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Pełny ekran"</string>
<string name="desktop_text" msgid="1077633567027630454">"Tryb pulpitu"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Podzielony ekran"</string>
<string name="more_button_text" msgid="3655388105592893530">"Więcej"</string>
<string name="float_button_text" msgid="9221657008391364581">"Pływające"</string>
+ <string name="select_text" msgid="5139083974039906583">"Wybierz"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Zrzut ekranu"</string>
+ <string name="close_text" msgid="4986518933445178928">"Zamknij"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Zamknij menu"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
index 1a29af24587a..a46493c829a9 100644
--- a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Parte superior a 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Parte superior a 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Parte inferior em tela cheia"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Dividir para a esquerda"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Dividir para a direita"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Dividir para cima"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Dividir para baixo"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Como usar o modo para uma mão"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Para sair, deslize de baixo para cima na tela ou toque em qualquer lugar acima do app"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Iniciar o modo para uma mão"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Fechar"</string>
<string name="back_button_text" msgid="1469718707134137085">"Voltar"</string>
<string name="handle_text" msgid="1766582106752184456">"Alça"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Ícone do app"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Tela cheia"</string>
<string name="desktop_text" msgid="1077633567027630454">"Modo área de trabalho"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Tela dividida"</string>
<string name="more_button_text" msgid="3655388105592893530">"Mais"</string>
<string name="float_button_text" msgid="9221657008391364581">"Ponto flutuante"</string>
+ <string name="select_text" msgid="5139083974039906583">"Selecionar"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Captura de tela"</string>
+ <string name="close_text" msgid="4986518933445178928">"Fechar"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Fechar menu"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
index b2d8e0809b99..7413a5b61d9a 100644
--- a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"50% no ecrã superior"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"30% no ecrã superior"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Ecrã inferior inteiro"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Divisão à esquerda"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Divisão à direita"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Divisão na parte superior"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Divisão na parte inferior"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Utilize o modo para uma mão"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Para sair, deslize rapidamente para cima a partir da parte inferior do ecrã ou toque em qualquer ponto acima da app."</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Iniciar o modo para uma mão"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Fechar"</string>
<string name="back_button_text" msgid="1469718707134137085">"Anterior"</string>
<string name="handle_text" msgid="1766582106752184456">"Indicador"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Ícone da app"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Ecrã inteiro"</string>
<string name="desktop_text" msgid="1077633567027630454">"Modo de ambiente de trabalho"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Ecrã dividido"</string>
<string name="more_button_text" msgid="3655388105592893530">"Mais"</string>
<string name="float_button_text" msgid="9221657008391364581">"Flutuar"</string>
+ <string name="select_text" msgid="5139083974039906583">"Selecionar"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Captura de ecrã"</string>
+ <string name="close_text" msgid="4986518933445178928">"Fechar"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Fechar menu"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-pt/strings.xml b/libs/WindowManager/Shell/res/values-pt/strings.xml
index 1a29af24587a..a46493c829a9 100644
--- a/libs/WindowManager/Shell/res/values-pt/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Parte superior a 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Parte superior a 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Parte inferior em tela cheia"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Dividir para a esquerda"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Dividir para a direita"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Dividir para cima"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Dividir para baixo"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Como usar o modo para uma mão"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Para sair, deslize de baixo para cima na tela ou toque em qualquer lugar acima do app"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Iniciar o modo para uma mão"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Fechar"</string>
<string name="back_button_text" msgid="1469718707134137085">"Voltar"</string>
<string name="handle_text" msgid="1766582106752184456">"Alça"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Ícone do app"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Tela cheia"</string>
<string name="desktop_text" msgid="1077633567027630454">"Modo área de trabalho"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Tela dividida"</string>
<string name="more_button_text" msgid="3655388105592893530">"Mais"</string>
<string name="float_button_text" msgid="9221657008391364581">"Ponto flutuante"</string>
+ <string name="select_text" msgid="5139083974039906583">"Selecionar"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Captura de tela"</string>
+ <string name="close_text" msgid="4986518933445178928">"Fechar"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Fechar menu"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ro/strings.xml b/libs/WindowManager/Shell/res/values-ro/strings.xml
index 8f609791f20b..0d30257600a1 100644
--- a/libs/WindowManager/Shell/res/values-ro/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ro/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Partea de sus: 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Partea de sus: 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Partea de jos pe ecran complet"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Împarte în stânga"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Împarte în dreapta"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Împarte în sus"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Împarte în jos"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Folosirea modului cu o mână"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Pentru a ieși, glisează în sus din partea de jos a ecranului sau atinge oriunde deasupra ferestrei aplicației"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Activează modul cu o mână"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Închide"</string>
<string name="back_button_text" msgid="1469718707134137085">"Înapoi"</string>
<string name="handle_text" msgid="1766582106752184456">"Ghidaj"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Pictograma aplicației"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Ecran complet"</string>
<string name="desktop_text" msgid="1077633567027630454">"Modul desktop"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Ecran împărțit"</string>
<string name="more_button_text" msgid="3655388105592893530">"Mai multe"</string>
<string name="float_button_text" msgid="9221657008391364581">"Flotantă"</string>
+ <string name="select_text" msgid="5139083974039906583">"Selectează"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Captură de ecran"</string>
+ <string name="close_text" msgid="4986518933445178928">"Închide"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Închide meniul"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ru/strings.xml b/libs/WindowManager/Shell/res/values-ru/strings.xml
index 0c1e4a9ad351..f632f03b19d9 100644
--- a/libs/WindowManager/Shell/res/values-ru/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ru/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Верхний на 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Верхний на 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Нижний во весь экран"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Приложение слева"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Приложение справа"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Приложение сверху"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Приложение снизу"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Использование режима управления одной рукой"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Чтобы выйти, проведите по экрану снизу вверх или коснитесь области за пределами приложения."</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Запустить режим управления одной рукой"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Закрыть"</string>
<string name="back_button_text" msgid="1469718707134137085">"Назад"</string>
<string name="handle_text" msgid="1766582106752184456">"Маркер"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Значок приложения"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Полноэкранный режим"</string>
<string name="desktop_text" msgid="1077633567027630454">"Режим компьютера"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Разделить экран"</string>
<string name="more_button_text" msgid="3655388105592893530">"Ещё"</string>
<string name="float_button_text" msgid="9221657008391364581">"Плавающее окно"</string>
+ <string name="select_text" msgid="5139083974039906583">"Выбрать"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Скриншот"</string>
+ <string name="close_text" msgid="4986518933445178928">"Закрыть"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Закрыть меню"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-si/strings.xml b/libs/WindowManager/Shell/res/values-si/strings.xml
index 13ac51823937..7825432bbf40 100644
--- a/libs/WindowManager/Shell/res/values-si/strings.xml
+++ b/libs/WindowManager/Shell/res/values-si/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"ඉහළම 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"ඉහළම 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"පහළ පූර්ණ තිරය"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"වම බෙදන්න"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"දකුණ බෙදන්න"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"ඉහළ බෙදන්න"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"පහළ බෙදන්න"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"තනි-අත් ප්‍රකාරය භාවිත කරමින්"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"පිටවීමට, තිරයේ පහළ සිට ඉහළට ස්වයිප් කරන්න හෝ යෙදුමට ඉහළින් ඕනෑම තැනක තට්ටු කරන්න"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"තනි අත් ප්‍රකාරය ආරම්භ කරන්න"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"වසන්න"</string>
<string name="back_button_text" msgid="1469718707134137085">"ආපසු"</string>
<string name="handle_text" msgid="1766582106752184456">"හැඬලය"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"යෙදුම් නිරූපකය"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"පූර්ණ තිරය"</string>
<string name="desktop_text" msgid="1077633567027630454">"ඩෙස්ක්ටොප් ප්‍රකාරය"</string>
<string name="split_screen_text" msgid="1396336058129570886">"බෙදුම් තිරය"</string>
<string name="more_button_text" msgid="3655388105592893530">"තව"</string>
<string name="float_button_text" msgid="9221657008391364581">"පාවෙන"</string>
+ <string name="select_text" msgid="5139083974039906583">"තෝරන්න"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"තිර රුව"</string>
+ <string name="close_text" msgid="4986518933445178928">"වසන්න"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"මෙනුව වසන්න"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-sk/strings.xml b/libs/WindowManager/Shell/res/values-sk/strings.xml
index c91856c7e383..21641e57cfe0 100644
--- a/libs/WindowManager/Shell/res/values-sk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sk/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Horná – 50 %"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Horná – 30 %"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Dolná – na celú obrazovku"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Rozdeliť vľavo"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Rozdeliť vpravo"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Rozdeliť hore"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Rozdeliť dole"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Používanie režimu jednej ruky"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Ukončíte potiahnutím z dolnej časti obrazovky nahor alebo klepnutím kdekoľvek nad aplikáciu"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Spustiť režim jednej ruky"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Zavrieť"</string>
<string name="back_button_text" msgid="1469718707134137085">"Späť"</string>
<string name="handle_text" msgid="1766582106752184456">"Rukoväť"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Ikona aplikácie"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Celá obrazovka"</string>
<string name="desktop_text" msgid="1077633567027630454">"Režim počítača"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Rozdelená obrazovka"</string>
<string name="more_button_text" msgid="3655388105592893530">"Viac"</string>
<string name="float_button_text" msgid="9221657008391364581">"Plávajúce"</string>
+ <string name="select_text" msgid="5139083974039906583">"Vybrať"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Snímka obrazovky"</string>
+ <string name="close_text" msgid="4986518933445178928">"Zavrieť"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Zavrieť ponuku"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-sl/strings.xml b/libs/WindowManager/Shell/res/values-sl/strings.xml
index 744492ca2ea2..444a3c88b433 100644
--- a/libs/WindowManager/Shell/res/values-sl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sl/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Zgornji 50 %"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Zgornji 30 %"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Spodnji v celozaslonski način"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Delitev levo"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Delitev desno"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Delitev zgoraj"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Delitev spodaj"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Uporaba enoročnega načina"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Za izhod povlecite z dna zaslona navzgor ali se dotaknite na poljubnem mestu nad aplikacijo"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Zagon enoročnega načina"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Zapri"</string>
<string name="back_button_text" msgid="1469718707134137085">"Nazaj"</string>
<string name="handle_text" msgid="1766582106752184456">"Ročica"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Ikona aplikacije"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Celozaslonsko"</string>
<string name="desktop_text" msgid="1077633567027630454">"Namizni način"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Razdeljen zaslon"</string>
<string name="more_button_text" msgid="3655388105592893530">"Več"</string>
<string name="float_button_text" msgid="9221657008391364581">"Lebdeče"</string>
+ <string name="select_text" msgid="5139083974039906583">"Izberi"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Posnetek zaslona"</string>
+ <string name="close_text" msgid="4986518933445178928">"Zapri"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Zapri meni"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-sq/strings.xml b/libs/WindowManager/Shell/res/values-sq/strings.xml
index 9afbbbacb6a3..07bc2a33ff5e 100644
--- a/libs/WindowManager/Shell/res/values-sq/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sq/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Lart 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Lart 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Ekrani i plotë poshtë"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Ndaj majtas"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Ndaj djathtas"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Ndaj lart"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Ndaj në fund"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Po përdor modalitetin e përdorimit me një dorë"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Për të dalë, rrëshqit lart nga fundi i ekranit ose trokit diku mbi aplikacion"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Modaliteti i përdorimit me një dorë"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Mbyll"</string>
<string name="back_button_text" msgid="1469718707134137085">"Pas"</string>
<string name="handle_text" msgid="1766582106752184456">"Emërtimi"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Ikona e aplikacionit"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Ekrani i plotë"</string>
<string name="desktop_text" msgid="1077633567027630454">"Modaliteti i desktopit"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Ekrani i ndarë"</string>
<string name="more_button_text" msgid="3655388105592893530">"Më shumë"</string>
<string name="float_button_text" msgid="9221657008391364581">"Pluskuese"</string>
+ <string name="select_text" msgid="5139083974039906583">"Zgjidh"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Pamja e ekranit"</string>
+ <string name="close_text" msgid="4986518933445178928">"Mbyll"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Mbyll menynë"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-sr/strings.xml b/libs/WindowManager/Shell/res/values-sr/strings.xml
index c252fd7d8962..4d75626f99b8 100644
--- a/libs/WindowManager/Shell/res/values-sr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sr/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Горњи екран 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Горњи екран 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Режим целог екрана за доњи екран"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Поделите лево"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Поделите десно"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Поделите у врху"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Поделите у дну"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Коришћење режима једном руком"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Да бисте изашли, превуците нагоре од дна екрана или додирните било где изнад апликације"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Покрените режим једном руком"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Затворите"</string>
<string name="back_button_text" msgid="1469718707134137085">"Назад"</string>
<string name="handle_text" msgid="1766582106752184456">"Идентификатор"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Икона апликације"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Преко целог екрана"</string>
<string name="desktop_text" msgid="1077633567027630454">"Режим за рачунаре"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Подељени екран"</string>
<string name="more_button_text" msgid="3655388105592893530">"Још"</string>
<string name="float_button_text" msgid="9221657008391364581">"Плутајуће"</string>
+ <string name="select_text" msgid="5139083974039906583">"Изаберите"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Снимак екрана"</string>
+ <string name="close_text" msgid="4986518933445178928">"Затворите"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Затворите мени"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-sv/strings.xml b/libs/WindowManager/Shell/res/values-sv/strings.xml
index 92622cb92a70..9988e4777e2f 100644
--- a/libs/WindowManager/Shell/res/values-sv/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sv/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Övre 50 %"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Övre 30 %"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Helskärm på nedre skärm"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Till vänster på delad skärm"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Till höger på delad skärm"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Upptill på delad skärm"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Nedtill på delad skärm"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Använda enhandsläge"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Avsluta genom att svepa uppåt från skärmens nederkant eller trycka ovanför appen"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Starta enhandsläge"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Stäng"</string>
<string name="back_button_text" msgid="1469718707134137085">"Tillbaka"</string>
<string name="handle_text" msgid="1766582106752184456">"Handtag"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Appikon"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Helskärm"</string>
<string name="desktop_text" msgid="1077633567027630454">"Datorläge"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Delad skärm"</string>
<string name="more_button_text" msgid="3655388105592893530">"Mer"</string>
<string name="float_button_text" msgid="9221657008391364581">"Svävande"</string>
+ <string name="select_text" msgid="5139083974039906583">"Välj"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Skärmbild"</string>
+ <string name="close_text" msgid="4986518933445178928">"Stäng"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Stäng menyn"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-sw/strings.xml b/libs/WindowManager/Shell/res/values-sw/strings.xml
index 6d92040b7933..4937464a49fe 100644
--- a/libs/WindowManager/Shell/res/values-sw/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sw/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Juu 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Juu 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Skrini nzima ya chini"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Gawanya sehemu ya kushoto"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Gawanya sehemu ya kulia"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Gawanya sehemu ya juu"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Gawanya sehemu ya chini"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Kutumia hali ya kutumia kwa mkono mmoja"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Ili ufunge, telezesha kidole juu kutoka sehemu ya chini ya skrini au uguse mahali popote juu ya programu"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Anzisha hali ya kutumia kwa mkono mmoja"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Funga"</string>
<string name="back_button_text" msgid="1469718707134137085">"Rudi nyuma"</string>
<string name="handle_text" msgid="1766582106752184456">"Ncha"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Aikoni ya Programu"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Skrini nzima"</string>
<string name="desktop_text" msgid="1077633567027630454">"Hali ya Kompyuta ya mezani"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Gawa Skrini"</string>
<string name="more_button_text" msgid="3655388105592893530">"Zaidi"</string>
<string name="float_button_text" msgid="9221657008391364581">"Inayoelea"</string>
+ <string name="select_text" msgid="5139083974039906583">"Chagua"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Picha ya skrini"</string>
+ <string name="close_text" msgid="4986518933445178928">"Funga"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Funga Menyu"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ta/strings.xml b/libs/WindowManager/Shell/res/values-ta/strings.xml
index 8cf631b5355d..edadfb4916b3 100644
--- a/libs/WindowManager/Shell/res/values-ta/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ta/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"மேலே 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"மேலே 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"கீழ்ப்புறம் முழுத் திரை"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"இடதுபுறமாகப் பிரிக்கும்"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"வலதுபுறமாகப் பிரிக்கும்"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"மேற்புறமாகப் பிரிக்கும்"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"கீழ்புறமாகப் பிரிக்கும்"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"ஒற்றைக் கைப் பயன்முறையைப் பயன்படுத்துதல்"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"வெளியேற, திரையின் கீழிருந்து மேல்நோக்கி ஸ்வைப் செய்யவும் அல்லது ஆப்ஸுக்கு மேலே ஏதேனும் ஓர் இடத்தில் தட்டவும்"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"ஒற்றைக் கைப் பயன்முறையைத் தொடங்கும்"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"மூடும்"</string>
<string name="back_button_text" msgid="1469718707134137085">"பின்செல்லும்"</string>
<string name="handle_text" msgid="1766582106752184456">"ஹேண்டில்"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"ஆப்ஸ் ஐகான்"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"முழுத்திரை"</string>
<string name="desktop_text" msgid="1077633567027630454">"டெஸ்க்டாப் பயன்முறை"</string>
<string name="split_screen_text" msgid="1396336058129570886">"திரையைப் பிரிக்கும்"</string>
<string name="more_button_text" msgid="3655388105592893530">"கூடுதல் விருப்பத்தேர்வுகள்"</string>
<string name="float_button_text" msgid="9221657008391364581">"மிதக்கும் சாளரம்"</string>
+ <string name="select_text" msgid="5139083974039906583">"தேர்ந்தெடுக்கும்"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"ஸ்கிரீன்ஷாட்"</string>
+ <string name="close_text" msgid="4986518933445178928">"மூடும்"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"மெனுவை மூடும்"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-te/strings.xml b/libs/WindowManager/Shell/res/values-te/strings.xml
index a4dcd950f321..66b20518279c 100644
--- a/libs/WindowManager/Shell/res/values-te/strings.xml
+++ b/libs/WindowManager/Shell/res/values-te/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"ఎగువ 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"ఎగువ 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"దిగువ ఫుల్-స్క్రీన్‌"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"ఎడమ వైపున్న భాగంలో విభజించండి"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"కుడి వైపున్న భాగంలో విభజించండి"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"ఎగువ భాగంలో విభజించండి"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"దిగువ భాగంలో విభజించండి"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"వన్-హ్యాండెడ్ మోడ్‌ను ఉపయోగించడం"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"నిష్క్రమించడానికి, స్క్రీన్ కింది భాగం నుండి పైకి స్వైప్ చేయండి లేదా యాప్ పైన ఎక్కడైనా ట్యాప్ చేయండి"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"వన్-హ్యాండెడ్ మోడ్‌ను ప్రారంభిస్తుంది"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"మూసివేయండి"</string>
<string name="back_button_text" msgid="1469718707134137085">"వెనుకకు"</string>
<string name="handle_text" msgid="1766582106752184456">"హ్యాండిల్"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"యాప్ చిహ్నం"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"ఫుల్-స్క్రీన్"</string>
<string name="desktop_text" msgid="1077633567027630454">"డెస్క్‌టాప్ మోడ్"</string>
<string name="split_screen_text" msgid="1396336058129570886">"స్ప్లిట్ స్క్రీన్"</string>
<string name="more_button_text" msgid="3655388105592893530">"మరిన్ని"</string>
<string name="float_button_text" msgid="9221657008391364581">"ఫ్లోట్"</string>
+ <string name="select_text" msgid="5139083974039906583">"ఎంచుకోండి"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"స్క్రీన్‌షాట్"</string>
+ <string name="close_text" msgid="4986518933445178928">"మూసివేయండి"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"మెనూను మూసివేయండి"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-th/strings.xml b/libs/WindowManager/Shell/res/values-th/strings.xml
index 1e900d8ad81f..67ae9b7c9105 100644
--- a/libs/WindowManager/Shell/res/values-th/strings.xml
+++ b/libs/WindowManager/Shell/res/values-th/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"ด้านบน 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"ด้านบน 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"เต็มหน้าจอด้านล่าง"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"แยกไปทางซ้าย"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"แยกไปทางขวา"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"แยกไปด้านบน"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"แยกไปด้านล่าง"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"การใช้โหมดมือเดียว"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"หากต้องการออก ให้เลื่อนขึ้นจากด้านล่างของหน้าจอหรือแตะที่ใดก็ได้เหนือแอป"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"เริ่มโหมดมือเดียว"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"ปิด"</string>
<string name="back_button_text" msgid="1469718707134137085">"กลับ"</string>
<string name="handle_text" msgid="1766582106752184456">"แฮนเดิล"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"ไอคอนแอป"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"เต็มหน้าจอ"</string>
<string name="desktop_text" msgid="1077633567027630454">"โหมดเดสก์ท็อป"</string>
<string name="split_screen_text" msgid="1396336058129570886">"แยกหน้าจอ"</string>
<string name="more_button_text" msgid="3655388105592893530">"เพิ่มเติม"</string>
<string name="float_button_text" msgid="9221657008391364581">"ล่องลอย"</string>
+ <string name="select_text" msgid="5139083974039906583">"เลือก"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"ภาพหน้าจอ"</string>
+ <string name="close_text" msgid="4986518933445178928">"ปิด"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"ปิดเมนู"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-tl/strings.xml b/libs/WindowManager/Shell/res/values-tl/strings.xml
index 8d5d0ed7b8da..1275dd6095a2 100644
--- a/libs/WindowManager/Shell/res/values-tl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-tl/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Gawing 50% ang nasa itaas"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Gawing 30% ang nasa itaas"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"I-full screen ang nasa ibaba"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Hatiin sa kaliwa"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Hatiin sa kanan"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Hatiin sa itaas"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Hatiin sa ilalim"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Paggamit ng one-hand mode"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Para lumabas, mag-swipe pataas mula sa ibaba ng screen o mag-tap kahit saan sa itaas ng app"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Simulan ang one-hand mode"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Isara"</string>
<string name="back_button_text" msgid="1469718707134137085">"Bumalik"</string>
<string name="handle_text" msgid="1766582106752184456">"Handle"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Icon ng App"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Fullscreen"</string>
<string name="desktop_text" msgid="1077633567027630454">"Desktop Mode"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Split Screen"</string>
<string name="more_button_text" msgid="3655388105592893530">"Higit pa"</string>
<string name="float_button_text" msgid="9221657008391364581">"Float"</string>
+ <string name="select_text" msgid="5139083974039906583">"Piliin"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Screenshot"</string>
+ <string name="close_text" msgid="4986518933445178928">"Isara"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Isara ang Menu"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-tr/strings.xml b/libs/WindowManager/Shell/res/values-tr/strings.xml
index 341d8f113943..74a457f02e22 100644
--- a/libs/WindowManager/Shell/res/values-tr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-tr/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Üstte %50"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Üstte %30"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Altta tam ekran"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Sol tarafta böl"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Sağ tarafta böl"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Üst tarafta böl"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Alt tarafta böl"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Tek el modunu kullanma"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Çıkmak için ekranın alt kısmından yukarı kaydırın veya uygulamanın üzerinde herhangi bir yere dokunun"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Tek el modunu başlat"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Kapat"</string>
<string name="back_button_text" msgid="1469718707134137085">"Geri"</string>
<string name="handle_text" msgid="1766582106752184456">"Herkese açık kullanıcı adı"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Uygulama Simgesi"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Tam Ekran"</string>
<string name="desktop_text" msgid="1077633567027630454">"Masaüstü Modu"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Bölünmüş Ekran"</string>
<string name="more_button_text" msgid="3655388105592893530">"Daha Fazla"</string>
<string name="float_button_text" msgid="9221657008391364581">"Havada Süzülen"</string>
+ <string name="select_text" msgid="5139083974039906583">"Seç"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Ekran görüntüsü"</string>
+ <string name="close_text" msgid="4986518933445178928">"Kapat"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Menüyü kapat"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-uk/strings.xml b/libs/WindowManager/Shell/res/values-uk/strings.xml
index 5b017c653e4a..b1e29f464b89 100644
--- a/libs/WindowManager/Shell/res/values-uk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-uk/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Верхнє вікно на 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Верхнє вікно на 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Нижнє вікно на весь екран"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Розділити зліва"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Розділити справа"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Розділити вгорі"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Розділити внизу"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Як користуватися режимом керування однією рукою"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Щоб вийти, проведіть пальцем по екрану знизу вгору або торкніться екрана над додатком"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Увімкнути режим керування однією рукою"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Закрити"</string>
<string name="back_button_text" msgid="1469718707134137085">"Назад"</string>
<string name="handle_text" msgid="1766582106752184456">"Маркер"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Значок додатка"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"На весь екран"</string>
<string name="desktop_text" msgid="1077633567027630454">"Режим комп’ютера"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Розділити екран"</string>
<string name="more_button_text" msgid="3655388105592893530">"Більше"</string>
<string name="float_button_text" msgid="9221657008391364581">"Плаваюче вікно"</string>
+ <string name="select_text" msgid="5139083974039906583">"Вибрати"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Знімок екрана"</string>
+ <string name="close_text" msgid="4986518933445178928">"Закрити"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Закрити меню"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-ur/strings.xml b/libs/WindowManager/Shell/res/values-ur/strings.xml
index 649356951189..88240cbc08d7 100644
--- a/libs/WindowManager/Shell/res/values-ur/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ur/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"اوپر %50"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"اوپر %30"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"نچلی فل اسکرین"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"دائیں طرف تقسیم کریں"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"بائیں طرف تقسیم کریں"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"اوپر کی طرف تقسیم کریں"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"نیچے کی طرف تقسیم کریں"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"ایک ہاتھ کی وضع کا استعمال کرنا"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"باہر نکلنے کیلئے، اسکرین کے نیچے سے اوپر کی طرف سوائپ کریں یا ایپ کے اوپر کہیں بھی تھپتھپائیں"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"ایک ہاتھ کی وضع شروع کریں"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"بند کریں"</string>
<string name="back_button_text" msgid="1469718707134137085">"پیچھے"</string>
<string name="handle_text" msgid="1766582106752184456">"ہینڈل"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"ایپ کا آئیکن"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"مکمل اسکرین"</string>
<string name="desktop_text" msgid="1077633567027630454">"ڈیسک ٹاپ موڈ"</string>
<string name="split_screen_text" msgid="1396336058129570886">"اسپلٹ اسکرین"</string>
<string name="more_button_text" msgid="3655388105592893530">"مزید"</string>
<string name="float_button_text" msgid="9221657008391364581">"فلوٹ"</string>
+ <string name="select_text" msgid="5139083974039906583">"منتخب کریں"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"اسکرین شاٹ"</string>
+ <string name="close_text" msgid="4986518933445178928">"بند کریں"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"مینو بند کریں"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-uz/strings.xml b/libs/WindowManager/Shell/res/values-uz/strings.xml
index fdca0d61e2c4..38f3a0dd1091 100644
--- a/libs/WindowManager/Shell/res/values-uz/strings.xml
+++ b/libs/WindowManager/Shell/res/values-uz/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Tepada 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Tepada 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Pastda to‘liq ekran"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Chapga ajratish"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Oʻngga ajratish"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Yuqoriga ajratish"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Pastga ajratish"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Ixcham rejimdan foydalanish"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Chiqish uchun ekran pastidan tepaga suring yoki ilovaning tepasidagi istalgan joyga bosing."</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Ixcham rejimni ishga tushirish"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Yopish"</string>
<string name="back_button_text" msgid="1469718707134137085">"Orqaga"</string>
<string name="handle_text" msgid="1766582106752184456">"Identifikator"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Ilova belgisi"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Butun ekran"</string>
<string name="desktop_text" msgid="1077633567027630454">"Desktop rejimi"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Ekranni ikkiga ajratish"</string>
<string name="more_button_text" msgid="3655388105592893530">"Yana"</string>
<string name="float_button_text" msgid="9221657008391364581">"Pufakli"</string>
+ <string name="select_text" msgid="5139083974039906583">"Tanlash"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Skrinshot"</string>
+ <string name="close_text" msgid="4986518933445178928">"Yopish"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Menyuni yopish"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-vi/strings.xml b/libs/WindowManager/Shell/res/values-vi/strings.xml
index 8fd25514b115..576bd5b12465 100644
--- a/libs/WindowManager/Shell/res/values-vi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-vi/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Trên 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Trên 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Toàn màn hình phía dưới"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Chia đôi màn hình về bên trái"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Chia đôi màn hình về bên phải"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Chia đôi màn hình lên trên cùng"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Chia đôi màn hình xuống dưới cùng"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Cách dùng chế độ một tay"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Để thoát, hãy vuốt lên từ cuối màn hình hoặc nhấn vào vị trí bất kỳ phía trên ứng dụng"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Bắt đầu chế độ một tay"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Đóng"</string>
<string name="back_button_text" msgid="1469718707134137085">"Quay lại"</string>
<string name="handle_text" msgid="1766582106752184456">"Xử lý"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Biểu tượng ứng dụng"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Toàn màn hình"</string>
<string name="desktop_text" msgid="1077633567027630454">"Chế độ máy tính"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Chia đôi màn hình"</string>
<string name="more_button_text" msgid="3655388105592893530">"Tuỳ chọn khác"</string>
<string name="float_button_text" msgid="9221657008391364581">"Nổi"</string>
+ <string name="select_text" msgid="5139083974039906583">"Chọn"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Ảnh chụp màn hình"</string>
+ <string name="close_text" msgid="4986518933445178928">"Đóng"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Đóng trình đơn"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
index ba78d1b8db11..a6c6ac449bf2 100644
--- a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"顶部 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"顶部 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"底部全屏"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"左分屏"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"右分屏"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"上分屏"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"下分屏"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"使用单手模式"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"如需退出,请从屏幕底部向上滑动,或点按应用上方的任意位置"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"启动单手模式"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"关闭"</string>
<string name="back_button_text" msgid="1469718707134137085">"返回"</string>
<string name="handle_text" msgid="1766582106752184456">"处理"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"应用图标"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"全屏"</string>
<string name="desktop_text" msgid="1077633567027630454">"桌面模式"</string>
<string name="split_screen_text" msgid="1396336058129570886">"分屏"</string>
<string name="more_button_text" msgid="3655388105592893530">"更多"</string>
<string name="float_button_text" msgid="9221657008391364581">"悬浮"</string>
+ <string name="select_text" msgid="5139083974039906583">"选择"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"屏幕截图"</string>
+ <string name="close_text" msgid="4986518933445178928">"关闭"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"关闭菜单"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
index b3bc5b694f50..d6df8c1e342c 100644
--- a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"頂部 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"頂部 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"底部全螢幕"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"分割左側區域"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"分割右側區域"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"分割上方區域"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"分割下方區域"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"使用單手模式"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"如要退出,請從螢幕底部向上滑動,或輕按應用程式上方的任何位置"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"開始單手模式"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"關閉"</string>
<string name="back_button_text" msgid="1469718707134137085">"返去"</string>
<string name="handle_text" msgid="1766582106752184456">"控點"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"應用程式圖示"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"全螢幕"</string>
<string name="desktop_text" msgid="1077633567027630454">"桌面模式"</string>
<string name="split_screen_text" msgid="1396336058129570886">"分割螢幕"</string>
<string name="more_button_text" msgid="3655388105592893530">"更多"</string>
<string name="float_button_text" msgid="9221657008391364581">"浮動"</string>
+ <string name="select_text" msgid="5139083974039906583">"選取"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"螢幕截圖"</string>
+ <string name="close_text" msgid="4986518933445178928">"關閉"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"關閉選單"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
index e7444614a4b0..64980c036d0b 100644
--- a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"以 50% 的螢幕空間顯示頂端畫面"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"以 30% 的螢幕空間顯示頂端畫面"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"以全螢幕顯示底部畫面"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"分割左側區域"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"分割右側區域"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"分割上方區域"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"分割下方區域"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"使用單手模式"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"如要退出,請從螢幕底部向上滑動,或輕觸應用程式上方的任何位置"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"啟動單手模式"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"關閉"</string>
<string name="back_button_text" msgid="1469718707134137085">"返回"</string>
<string name="handle_text" msgid="1766582106752184456">"控點"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"應用程式圖示"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"全螢幕"</string>
<string name="desktop_text" msgid="1077633567027630454">"電腦模式"</string>
<string name="split_screen_text" msgid="1396336058129570886">"分割畫面"</string>
<string name="more_button_text" msgid="3655388105592893530">"更多"</string>
<string name="float_button_text" msgid="9221657008391364581">"浮動"</string>
+ <string name="select_text" msgid="5139083974039906583">"選取"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"螢幕截圖"</string>
+ <string name="close_text" msgid="4986518933445178928">"關閉"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"關閉選單"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values-zu/strings.xml b/libs/WindowManager/Shell/res/values-zu/strings.xml
index 913e68f95cb4..abbec335312c 100644
--- a/libs/WindowManager/Shell/res/values-zu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zu/strings.xml
@@ -49,14 +49,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Okuphezulu okungu-50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Okuphezulu okungu-30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Ngaphansi kwesikrini esigcwele"</string>
- <!-- no translation found for accessibility_split_left (1713683765575562458) -->
- <skip />
- <!-- no translation found for accessibility_split_right (8441001008181296837) -->
- <skip />
- <!-- no translation found for accessibility_split_top (2789329702027147146) -->
- <skip />
- <!-- no translation found for accessibility_split_bottom (8694551025220868191) -->
- <skip />
+ <string name="accessibility_split_left" msgid="1713683765575562458">"Hlukanisa ngakwesobunxele"</string>
+ <string name="accessibility_split_right" msgid="8441001008181296837">"Hlukanisa ngakwesokudla"</string>
+ <string name="accessibility_split_top" msgid="2789329702027147146">"Hlukanisa phezulu"</string>
+ <string name="accessibility_split_bottom" msgid="8694551025220868191">"Hlukanisa phansi"</string>
<string name="one_handed_tutorial_title" msgid="4583241688067426350">"Ukusebenzisa imodi yesandla esisodwa"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Ukuze uphume, swayipha ngaphezulu kusuka ngezansi kwesikrini noma thepha noma kuphi ngenhla kohlelo lokusebenza"</string>
<string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Qalisa imodi yesandla esisodwa"</string>
@@ -102,9 +98,14 @@
<string name="close_button_text" msgid="2913281996024033299">"Vala"</string>
<string name="back_button_text" msgid="1469718707134137085">"Emuva"</string>
<string name="handle_text" msgid="1766582106752184456">"Isibambo"</string>
+ <string name="app_icon_text" msgid="2823268023931811747">"Isithonjana Se-app"</string>
<string name="fullscreen_text" msgid="1162316685217676079">"Isikrini esigcwele"</string>
<string name="desktop_text" msgid="1077633567027630454">"Imodi Yedeskithophu"</string>
<string name="split_screen_text" msgid="1396336058129570886">"Hlukanisa isikrini"</string>
<string name="more_button_text" msgid="3655388105592893530">"Okwengeziwe"</string>
<string name="float_button_text" msgid="9221657008391364581">"Iflowuthi"</string>
+ <string name="select_text" msgid="5139083974039906583">"Khetha"</string>
+ <string name="screenshot_text" msgid="1477704010087786671">"Isithombe-skrini"</string>
+ <string name="close_text" msgid="4986518933445178928">"Vala"</string>
+ <string name="collapse_menu_text" msgid="7515008122450342029">"Vala Imenyu"</string>
</resources>
diff --git a/libs/WindowManager/Shell/res/values/colors.xml b/libs/WindowManager/Shell/res/values/colors.xml
index 6e750a3d5e34..6fb70006e67f 100644
--- a/libs/WindowManager/Shell/res/values/colors.xml
+++ b/libs/WindowManager/Shell/res/values/colors.xml
@@ -17,7 +17,8 @@
*/
-->
<resources>
- <color name="docked_divider_handle">#ffffff</color>
+ <color name="docked_divider_handle">#000000</color>
+ <color name="split_divider_background">@color/taskbar_background</color>
<drawable name="forced_resizable_background">#59000000</drawable>
<color name="minimize_dock_shadow_start">#60000000</color>
<color name="minimize_dock_shadow_end">#00000000</color>
@@ -41,6 +42,9 @@
<color name="letterbox_education_accent_primary">@android:color/system_accent1_100</color>
<color name="letterbox_education_text_secondary">@android:color/system_neutral2_200</color>
+ <!-- Letterbox Dialog -->
+ <color name="letterbox_dialog_background">@android:color/system_neutral1_900</color>
+
<!-- GM2 colors -->
<color name="GM2_grey_200">#E8EAED</color>
<color name="GM2_grey_700">#5F6368</color>
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index 1f9b6cf6c64f..680ad5101366 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -273,6 +273,18 @@
<!-- The space between two actions in the letterbox education dialog -->
<dimen name="letterbox_education_dialog_space_between_actions">24dp</dimen>
+ <!-- The corner radius of the buttons in the letterbox education dialog -->
+ <dimen name="letterbox_education_dialog_button_radius">12dp</dimen>
+
+ <!-- The horizontal padding for the buttons in the letterbox education dialog -->
+ <dimen name="letterbox_education_dialog_horizontal_padding">16dp</dimen>
+
+ <!-- The vertical padding for the buttons in the letterbox education dialog -->
+ <dimen name="letterbox_education_dialog_vertical_padding">8dp</dimen>
+
+ <!-- The insets for the buttons in the letterbox education dialog -->
+ <dimen name="letterbox_education_dialog_vertical_inset">6dp</dimen>
+
<!-- The margin between the dialog container and its parent. -->
<dimen name="letterbox_restart_dialog_margin">24dp</dimen>
@@ -306,6 +318,15 @@
<!-- The corner radius of the buttons in the restart dialog -->
<dimen name="letterbox_restart_dialog_button_radius">18dp</dimen>
+ <!-- The insets for the buttons in the letterbox restart dialog -->
+ <dimen name="letterbox_restart_dialog_vertical_inset">6dp</dimen>
+
+ <!-- The horizontal padding for the buttons in the letterbox restart dialog -->
+ <dimen name="letterbox_restart_dialog_horizontal_padding">16dp</dimen>
+
+ <!-- The vertical padding for the buttons in the letterbox restart dialog -->
+ <dimen name="letterbox_restart_dialog_vertical_padding">8dp</dimen>
+
<!-- The width of the brand image on staring surface. -->
<dimen name="starting_surface_brand_image_width">200dp</dimen>
@@ -349,6 +370,10 @@
<dimen name="freeform_resize_corner">44dp</dimen>
- <dimen name="caption_menu_elevation">4dp</dimen>
+ <!-- The radius of the caption menu shadow. -->
+ <dimen name="caption_menu_shadow_radius">4dp</dimen>
+
+ <!-- The radius of the caption menu corners. -->
+ <dimen name="caption_menu_corner_radius">20dp</dimen>
</resources>
diff --git a/libs/WindowManager/Shell/res/values/styles.xml b/libs/WindowManager/Shell/res/values/styles.xml
index bae009a0526f..bc2e71d1c013 100644
--- a/libs/WindowManager/Shell/res/values/styles.xml
+++ b/libs/WindowManager/Shell/res/values/styles.xml
@@ -38,11 +38,9 @@
</style>
<style name="CaptionWindowingButtonStyle">
- <item name="android:layout_width">32dp</item>
- <item name="android:layout_height">32dp</item>
+ <item name="android:layout_width">40dp</item>
+ <item name="android:layout_height">40dp</item>
<item name="android:padding">4dp</item>
- <item name="android:layout_marginTop">5dp</item>
- <item name="android:layout_marginBottom">5dp</item>
</style>
<style name="CaptionMenuButtonStyle" parent="@style/Widget.AppCompat.Button.Borderless">
@@ -80,6 +78,12 @@
<item name="android:textColor">@color/tv_pip_edu_text</item>
</style>
+ <style name="LetterboxDialog" parent="@android:style/Theme.Holo">
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:background">@color/letterbox_dialog_background</item>
+ </style>
+
<style name="RestartDialogTitleText">
<item name="android:textSize">24sp</item>
<item name="android:textColor">?android:attr/textColorPrimary</item>
@@ -87,6 +91,9 @@
<item name="android:textAppearance">
@*android:style/TextAppearance.DeviceDefault.Headline
</item>
+ <item name="android:fontFamily">
+ @*android:string/config_bodyFontFamilyMedium
+ </item>
</style>
<style name="RestartDialogBodyText">
@@ -97,24 +104,44 @@
<item name="android:textAppearance">
@*android:style/TextAppearance.DeviceDefault.Body2
</item>
+ <item name="android:fontFamily">
+ @*android:string/config_bodyFontFamily
+ </item>
</style>
<style name="RestartDialogCheckboxText">
<item name="android:textSize">16sp</item>
<item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="android:lineSpacingExtra">4sp</item>
- <item name="android:textAppearance">@*android:style/TextAppearance.DeviceDefault</item>
+ <item name="android:textAppearance">
+ @*android:style/TextAppearance.DeviceDefault.Headline
+ </item>
+ <item name="android:fontFamily">
+ @*android:string/config_bodyFontFamilyMedium
+ </item>
</style>
<style name="RestartDialogDismissButton">
<item name="android:lineSpacingExtra">2sp</item>
<item name="android:textSize">14sp</item>
<item name="android:textColor">?android:attr/textColorPrimary</item>
+ <item name="android:textAppearance">
+ @*android:style/TextAppearance.DeviceDefault.Body2
+ </item>
+ <item name="android:fontFamily">
+ @*android:string/config_bodyFontFamily
+ </item>
</style>
<style name="RestartDialogConfirmButton">
<item name="android:lineSpacingExtra">2sp</item>
<item name="android:textSize">14sp</item>
<item name="android:textColor">?android:attr/textColorPrimaryInverse</item>
+ <item name="android:textAppearance">
+ @*android:style/TextAppearance.DeviceDefault.Body2
+ </item>
+ <item name="android:fontFamily">
+ @*android:string/config_bodyFontFamily
+ </item>
</style>
</resources>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ProtoLogController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ProtoLogController.java
index e2012b4e36dc..88525aabe53b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ProtoLogController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ProtoLogController.java
@@ -16,8 +16,6 @@
package com.android.wm.shell;
-import android.os.Build;
-
import com.android.wm.shell.protolog.ShellProtoLogImpl;
import com.android.wm.shell.sysui.ShellCommandHandler;
import com.android.wm.shell.sysui.ShellInit;
@@ -43,9 +41,6 @@ public class ProtoLogController implements ShellCommandHandler.ShellCommandActio
void onInit() {
mShellCommandHandler.addCommandCallback("protolog", this, this);
- if (Build.IS_DEBUGGABLE) {
- mShellProtoLog.startProtoLog(null /* PrintWriter */);
- }
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index b6fd0bbafc71..585f81c81a36 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -428,9 +428,9 @@ public class ShellTaskOrganizer extends TaskOrganizer implements
}
@Override
- public void addStartingWindow(StartingWindowInfo info) {
+ public void addStartingWindow(StartingWindowInfo info, IBinder appToken) {
if (mStartingWindow != null) {
- mStartingWindow.addStartingWindow(info);
+ mStartingWindow.addStartingWindow(info, appToken);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskViewTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskViewTransitions.java
index 04bff97bc4ce..306d6196c553 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskViewTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskViewTransitions.java
@@ -32,6 +32,7 @@ import android.window.TransitionRequestInfo;
import android.window.WindowContainerTransaction;
import com.android.wm.shell.transition.Transitions;
+import com.android.wm.shell.util.TransitionUtil;
import java.util.ArrayList;
@@ -115,7 +116,7 @@ public class TaskViewTransitions implements Transitions.TransitionHandler {
boolean latest) {
for (int i = mPending.size() - 1; i >= 0; --i) {
if (mPending.get(i).mTaskView != taskView) continue;
- if (Transitions.isClosingType(mPending.get(i).mType) == closing) {
+ if (TransitionUtil.isClosingType(mPending.get(i).mType) == closing) {
return mPending.get(i);
}
if (latest) {
@@ -148,7 +149,7 @@ public class TaskViewTransitions implements Transitions.TransitionHandler {
final TaskViewTaskController taskView = findTaskView(triggerTask);
if (taskView == null) return null;
// Opening types should all be initiated by shell
- if (!Transitions.isClosingType(request.getType())) return null;
+ if (!TransitionUtil.isClosingType(request.getType())) return null;
PendingTransition pending = findPending(taskView, true /* closing */, false /* latest */);
if (pending == null) {
pending = new PendingTransition(request.getType(), null, taskView, null /* cookie */);
@@ -238,7 +239,7 @@ public class TaskViewTransitions implements Transitions.TransitionHandler {
for (int i = 0; i < info.getChanges().size(); ++i) {
final TransitionInfo.Change chg = info.getChanges().get(i);
if (chg.getTaskInfo() == null) continue;
- if (Transitions.isClosingType(chg.getMode())) {
+ if (TransitionUtil.isClosingType(chg.getMode())) {
final boolean isHide = chg.getMode() == TRANSIT_TO_BACK;
TaskViewTaskController tv = findTaskView(chg.getTaskInfo());
if (tv == null) {
@@ -255,7 +256,7 @@ public class TaskViewTransitions implements Transitions.TransitionHandler {
tv.prepareCloseAnimation();
}
changesHandled++;
- } else if (Transitions.isOpeningType(chg.getMode())) {
+ } else if (TransitionUtil.isOpeningType(chg.getMode())) {
final boolean taskIsNew = chg.getMode() == TRANSIT_OPEN;
final TaskViewTaskController tv;
if (taskIsNew) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java
index 579f7aae9321..c767376d4f29 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java
@@ -29,7 +29,7 @@ import android.window.TransitionInfo;
import androidx.annotation.NonNull;
-import com.android.wm.shell.transition.Transitions;
+import com.android.wm.shell.util.TransitionUtil;
/**
* Wrapper to handle the ActivityEmbedding animation update in one
@@ -90,7 +90,7 @@ class ActivityEmbeddingAnimationAdapter {
mChange = change;
mLeash = leash;
mWholeAnimationBounds.set(wholeAnimationBounds);
- if (Transitions.isClosingType(change.getMode())) {
+ if (TransitionUtil.isClosingType(change.getMode())) {
// When it is closing, we want to show the content at the start position in case the
// window is resizing as well. For example, when the activities is changing from split
// to stack, the bottom TaskFragment will be resized to fullscreen when hiding.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java
index fe3c4ea3fee9..1df6ecda78c3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java
@@ -43,7 +43,7 @@ import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
import com.android.wm.shell.common.ScreenshotUtils;
-import com.android.wm.shell.transition.Transitions;
+import com.android.wm.shell.util.TransitionUtil;
import java.util.ArrayList;
import java.util.List;
@@ -184,7 +184,7 @@ class ActivityEmbeddingAnimationRunner {
if (isChangeTransition) {
return createChangeAnimationAdapters(info, startTransaction);
}
- if (Transitions.isClosingType(info.getType())) {
+ if (TransitionUtil.isClosingType(info.getType())) {
return createCloseAnimationAdapters(info);
}
return createOpenAnimationAdapters(info);
@@ -219,7 +219,7 @@ class ActivityEmbeddingAnimationRunner {
final Rect openingWholeScreenBounds = new Rect();
final Rect closingWholeScreenBounds = new Rect();
for (TransitionInfo.Change change : info.getChanges()) {
- if (Transitions.isOpeningType(change.getMode())) {
+ if (TransitionUtil.isOpeningType(change.getMode())) {
openingChanges.add(change);
openingWholeScreenBounds.union(change.getEndAbsBounds());
} else {
@@ -271,7 +271,7 @@ class ActivityEmbeddingAnimationRunner {
continue;
}
final TransitionInfo.Change change = adapter.mChange;
- if (Transitions.isOpeningType(adapter.mChange.getMode())) {
+ if (TransitionUtil.isOpeningType(adapter.mChange.getMode())) {
// Need to screenshot after startTransaction is applied otherwise activity
// may not be visible or ready yet.
postStartTransactionCallbacks.add(
@@ -343,7 +343,7 @@ class ActivityEmbeddingAnimationRunner {
// When the parent window is also included in the transition as an opening window,
// we would like to animate the parent window instead.
final TransitionInfo.Change parentChange = info.getChange(parentToken);
- if (parentChange != null && Transitions.isOpeningType(parentChange.getMode())) {
+ if (parentChange != null && TransitionUtil.isOpeningType(parentChange.getMode())) {
// We won't create a separate animation for the parent, but to animate the
// parent for the child resizing.
handledChanges.add(parentChange);
@@ -404,7 +404,7 @@ class ActivityEmbeddingAnimationRunner {
// No-op if it will be covered by the changing parent window, or it is a changing
// window without bounds change.
animation = ActivityEmbeddingAnimationSpec.createNoopAnimation(change);
- } else if (Transitions.isClosingType(change.getMode())) {
+ } else if (TransitionUtil.isClosingType(change.getMode())) {
animation = mAnimationSpec.createChangeBoundsCloseAnimation(change, parentBounds);
shouldShouldBackgroundColor = false;
} else {
@@ -469,7 +469,7 @@ class ActivityEmbeddingAnimationRunner {
// When the parent window is also included in the transition as an opening window,
// we would like to animate the parent window instead.
final TransitionInfo.Change parentChange = info.getChange(parentToken);
- if (parentChange != null && Transitions.isOpeningType(parentChange.getMode())) {
+ if (parentChange != null && TransitionUtil.isOpeningType(parentChange.getMode())) {
changingChanges.add(parentChange);
}
}
@@ -491,8 +491,8 @@ class ActivityEmbeddingAnimationRunner {
// No-op if it will be covered by the changing parent window.
continue;
}
- hasOpeningWindow |= Transitions.isOpeningType(change.getMode());
- hasClosingWindow |= Transitions.isClosingType(change.getMode());
+ hasOpeningWindow |= TransitionUtil.isOpeningType(change.getMode());
+ hasClosingWindow |= TransitionUtil.isClosingType(change.getMode());
}
return hasOpeningWindow && hasClosingWindow;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java
index d10a6744b5f1..cb8342a10a6a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java
@@ -36,7 +36,7 @@ import android.window.TransitionInfo;
import androidx.annotation.NonNull;
import com.android.internal.policy.TransitionAnimation;
-import com.android.wm.shell.transition.Transitions;
+import com.android.wm.shell.util.TransitionUtil;
/** Animation spec for ActivityEmbedding transition. */
// TODO(b/206557124): provide an easier way to customize animation
@@ -73,7 +73,7 @@ class ActivityEmbeddingAnimationSpec {
@NonNull
static Animation createNoopAnimation(@NonNull TransitionInfo.Change change) {
// Noop but just keep the window showing/hiding.
- final float alpha = Transitions.isClosingType(change.getMode()) ? 0f : 1f;
+ final float alpha = TransitionUtil.isClosingType(change.getMode()) ? 0f : 1f;
return new AlphaAnimation(alpha, alpha);
}
@@ -198,7 +198,7 @@ class ActivityEmbeddingAnimationSpec {
@NonNull
Animation loadOpenAnimation(@NonNull TransitionInfo info,
@NonNull TransitionInfo.Change change, @NonNull Rect wholeAnimationBounds) {
- final boolean isEnter = Transitions.isOpeningType(change.getMode());
+ final boolean isEnter = TransitionUtil.isOpeningType(change.getMode());
final Animation animation;
if (shouldShowBackdrop(info, change)) {
animation = mTransitionAnimation.loadDefaultAnimationRes(isEnter
@@ -222,7 +222,7 @@ class ActivityEmbeddingAnimationSpec {
@NonNull
Animation loadCloseAnimation(@NonNull TransitionInfo info,
@NonNull TransitionInfo.Change change, @NonNull Rect wholeAnimationBounds) {
- final boolean isEnter = Transitions.isOpeningType(change.getMode());
+ final boolean isEnter = TransitionUtil.isOpeningType(change.getMode());
final Animation animation;
if (shouldShowBackdrop(info, change)) {
animation = mTransitionAnimation.loadDefaultAnimationRes(isEnter
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
index ee5d205498c3..0b8759890359 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
@@ -29,8 +29,9 @@ import android.content.Context;
import android.database.ContentObserver;
import android.hardware.input.InputManager;
import android.net.Uri;
+import android.os.Bundle;
import android.os.Handler;
-import android.os.IBinder;
+import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemProperties;
@@ -39,7 +40,6 @@ import android.provider.Settings.Global;
import android.util.Log;
import android.util.SparseArray;
import android.view.IRemoteAnimationRunner;
-import android.view.IWindowFocusObserver;
import android.view.InputDevice;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
@@ -121,23 +121,22 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
private IOnBackInvokedCallback mActiveCallback;
@VisibleForTesting
- final IWindowFocusObserver mFocusObserver = new IWindowFocusObserver.Stub() {
- @Override
- public void focusGained(IBinder inputToken) { }
- @Override
- public void focusLost(IBinder inputToken) {
- mShellExecutor.execute(() -> {
- if (!mBackGestureStarted || mPostCommitAnimationInProgress) {
- // If an uninterruptible animation is already in progress, we should ignore
- // this due to it may cause focus lost. (alpha = 0)
- return;
+ final RemoteCallback mNavigationObserver = new RemoteCallback(
+ new RemoteCallback.OnResultListener() {
+ @Override
+ public void onResult(@Nullable Bundle result) {
+ mShellExecutor.execute(() -> {
+ if (!mBackGestureStarted || mPostCommitAnimationInProgress) {
+ // If an uninterruptible animation is already in progress, we should
+ // ignore this due to it may cause focus lost. (alpha = 0)
+ return;
+ }
+ ProtoLog.i(WM_SHELL_BACK_PREVIEW, "Navigation window gone.");
+ setTriggerBack(false);
+ onGestureFinished(false);
+ });
}
- ProtoLog.i(WM_SHELL_BACK_PREVIEW, "Target window lost focus.");
- setTriggerBack(false);
- onGestureFinished(false);
});
- }
- };
private final BackAnimationBackground mAnimationBackground;
@@ -351,7 +350,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
try {
mBackNavigationInfo = mActivityTaskManager.startBackNavigation(
- mFocusObserver, mEnableAnimations.get() ? mBackAnimationAdapter : null);
+ mNavigationObserver, mEnableAnimations.get() ? mBackAnimationAdapter : null);
onBackNavigationInfoReceived(mBackNavigationInfo);
} catch (RemoteException remoteException) {
Log.e(TAG, "Failed to initAnimation", remoteException);
@@ -403,7 +402,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
InputDevice.SOURCE_KEYBOARD);
ev.setDisplayId(mContext.getDisplay().getDisplayId());
- if (!InputManager.getInstance()
+ if (!mContext.getSystemService(InputManager.class)
.injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC)) {
Log.e(TAG, "Inject input event fail");
}
@@ -553,6 +552,9 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
if (runner.isWaitingAnimation()) {
ProtoLog.w(WM_SHELL_BACK_PREVIEW, "Gesture released, but animation didn't ready.");
return;
+ } else if (runner.isAnimationCancelled()) {
+ invokeOrCancelBack();
+ return;
}
startPostCommitAnimation();
}
@@ -654,7 +656,19 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
}
@Override
- public void onAnimationCancelled() { }
+ public void onAnimationCancelled() {
+ mShellExecutor.execute(() -> {
+ final BackAnimationRunner runner = mAnimationDefinition.get(
+ mBackNavigationInfo.getType());
+ if (runner == null) {
+ return;
+ }
+ runner.cancelAnimation();
+ if (!mBackGestureStarted) {
+ invokeOrCancelBack();
+ }
+ });
+ }
};
mBackAnimationAdapter = new BackAnimationAdapter(runner);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java
index d70b8f53a911..82c523f337db 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java
@@ -41,6 +41,9 @@ class BackAnimationRunner {
// Whether we are waiting to receive onAnimationStart
private boolean mWaitingAnimation;
+ /** True when the back animation is cancelled */
+ private boolean mAnimationCancelled;
+
BackAnimationRunner(@NonNull IOnBackInvokedCallback callback,
@NonNull IRemoteAnimationRunner runner) {
mCallback = callback;
@@ -81,9 +84,19 @@ class BackAnimationRunner {
void startGesture() {
mWaitingAnimation = true;
+ mAnimationCancelled = false;
}
boolean isWaitingAnimation() {
return mWaitingAnimation;
}
+
+ void cancelAnimation() {
+ mWaitingAnimation = false;
+ mAnimationCancelled = true;
+ }
+
+ boolean isAnimationCancelled() {
+ return mAnimationCancelled;
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
index 57c7731e69ed..ecddbda0fff4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
@@ -16,6 +16,7 @@
package com.android.wm.shell.bubbles;
+import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
@@ -226,6 +227,8 @@ public class BubbleExpandedView extends LinearLayout {
try {
options.setTaskAlwaysOnTop(true);
options.setLaunchedFromBubble(true);
+ options.setPendingIntentBackgroundActivityStartMode(
+ MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
Intent fillInIntent = new Intent();
// Apply flags to make behaviour match documentLaunchMode=always.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblesNavBarGestureTracker.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblesNavBarGestureTracker.java
index e7beeeb06534..3a3a378e00d3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblesNavBarGestureTracker.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblesNavBarGestureTracker.java
@@ -64,8 +64,8 @@ class BubblesNavBarGestureTracker {
stopInternal();
- mInputMonitor = InputManager.getInstance().monitorGestureInput(GESTURE_MONITOR,
- mContext.getDisplayId());
+ mInputMonitor = mContext.getSystemService(InputManager.class)
+ .monitorGestureInput(GESTURE_MONITOR, mContext.getDisplayId());
InputChannel inputChannel = mInputMonitor.getInputChannel();
BubblesNavBarMotionEventHandler motionEventHandler =
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
index 5933ac22dd83..69f0bad4fb45 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
@@ -59,9 +59,6 @@ public class DividerView extends FrameLayout implements View.OnTouchListener {
public static final long TOUCH_ANIMATION_DURATION = 150;
public static final long TOUCH_RELEASE_ANIMATION_DURATION = 200;
- /** The task bar expanded height. Used to determine whether to insets divider bounds or not. */
- private float mExpandedTaskBarHeight;
-
private final int mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
private SplitLayout mSplitLayout;
@@ -216,17 +213,19 @@ public class DividerView extends FrameLayout implements View.OnTouchListener {
void onInsetsChanged(InsetsState insetsState, boolean animate) {
mSplitLayout.getDividerBounds(mTempRect);
- final InsetsSource taskBarInsetsSource =
- insetsState.peekSource(InsetsState.ITYPE_EXTRA_NAVIGATION_BAR);
// Only insets the divider bar with task bar when it's expanded so that the rounded corners
// will be drawn against task bar.
// But there is no need to do it when IME showing because there are no rounded corners at
// the bottom. This also avoids the problem of task bar height not changing when IME
// floating.
- if (!insetsState.isSourceOrDefaultVisible(InsetsSource.ID_IME, WindowInsets.Type.ime())
- && taskBarInsetsSource != null
- && taskBarInsetsSource.getFrame().height() >= mExpandedTaskBarHeight) {
- mTempRect.inset(taskBarInsetsSource.calculateVisibleInsets(mTempRect));
+ if (!insetsState.isSourceOrDefaultVisible(InsetsSource.ID_IME, WindowInsets.Type.ime())) {
+ for (int i = insetsState.sourceSize() - 1; i >= 0; i--) {
+ final InsetsSource source = insetsState.sourceAt(i);
+ if (source.getType() == WindowInsets.Type.navigationBars()
+ && source.insetsRoundedCornerFrame()) {
+ mTempRect.inset(source.calculateVisibleInsets(mTempRect));
+ }
+ }
}
if (!mTempRect.equals(mDividerBounds)) {
@@ -251,8 +250,6 @@ public class DividerView extends FrameLayout implements View.OnTouchListener {
mDividerBar = findViewById(R.id.divider_bar);
mHandle = findViewById(R.id.docked_divider_handle);
mBackground = findViewById(R.id.docked_divider_background);
- mExpandedTaskBarHeight = getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.taskbar_frame_height);
mTouchElevation = getResources().getDimensionPixelSize(
R.dimen.docked_stack_divider_lift_elevation);
mDoubleTapDetector = new GestureDetector(getContext(), new DoubleTapListener());
@@ -374,7 +371,14 @@ public class DividerView extends FrameLayout implements View.OnTouchListener {
mViewHost.relayout(lp);
}
- void setInteractive(boolean interactive, String from) {
+ /**
+ * Set divider should interactive to user or not.
+ *
+ * @param interactive divider interactive.
+ * @param hideHandle divider handle hidden or not, only work when interactive is false.
+ * @param from caller from where.
+ */
+ void setInteractive(boolean interactive, boolean hideHandle, String from) {
if (interactive == mInteractive) return;
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN,
"Set divider bar %s from %s", interactive ? "interactive" : "non-interactive",
@@ -390,7 +394,7 @@ public class DividerView extends FrameLayout implements View.OnTouchListener {
mMoving = false;
}
releaseTouching();
- mHandle.setVisibility(mInteractive ? View.VISIBLE : View.INVISIBLE);
+ mHandle.setVisibility(!mInteractive && hideHandle ? View.INVISIBLE : View.VISIBLE);
}
private boolean isLandscape() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index f616e6f64750..b447a543989e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -120,6 +120,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
private int mOrientation;
private int mRotation;
private int mDensity;
+ private int mUiMode;
private final boolean mDimNonImeSide;
private ValueAnimator mDividerFlingAnimator;
@@ -295,10 +296,12 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
final Rect rootBounds = configuration.windowConfiguration.getBounds();
final int orientation = configuration.orientation;
final int density = configuration.densityDpi;
+ final int uiMode = configuration.uiMode;
if (mOrientation == orientation
&& mRotation == rotation
&& mDensity == density
+ && mUiMode == uiMode
&& mRootBounds.equals(rootBounds)) {
return false;
}
@@ -310,6 +313,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
mRootBounds.set(rootBounds);
mRotation = rotation;
mDensity = density;
+ mUiMode = uiMode;
mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds, null);
updateDividerConfig(mContext);
initDividerPosition(mTempRect);
@@ -486,6 +490,17 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
}
/**
+ * Set divider should interactive to user or not.
+ *
+ * @param interactive divider interactive.
+ * @param hideHandle divider handle hidden or not, only work when interactive is false.
+ * @param from caller from where.
+ */
+ public void setDividerInteractive(boolean interactive, boolean hideHandle, String from) {
+ mSplitWindowManager.setInteractive(interactive, hideHandle, from);
+ }
+
+ /**
* Sets new divide position and updates bounds correspondingly. Notifies listener if the new
* target indicates dismissing split.
*/
@@ -735,21 +750,28 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
}
}
- /** Apply recorded task layout to the {@link WindowContainerTransaction}. */
- public void applyTaskChanges(WindowContainerTransaction wct,
+ /** Apply recorded task layout to the {@link WindowContainerTransaction}.
+ *
+ * @return true if stage bounds actually update.
+ */
+ public boolean applyTaskChanges(WindowContainerTransaction wct,
ActivityManager.RunningTaskInfo task1, ActivityManager.RunningTaskInfo task2) {
+ boolean boundsChanged = false;
if (!mBounds1.equals(mWinBounds1) || !task1.token.equals(mWinToken1)) {
wct.setBounds(task1.token, mBounds1);
wct.setSmallestScreenWidthDp(task1.token, getSmallestWidthDp(mBounds1));
mWinBounds1.set(mBounds1);
mWinToken1 = task1.token;
+ boundsChanged = true;
}
if (!mBounds2.equals(mWinBounds2) || !task2.token.equals(mWinToken2)) {
wct.setBounds(task2.token, mBounds2);
wct.setSmallestScreenWidthDp(task2.token, getSmallestWidthDp(mBounds2));
mWinBounds2.set(mBounds2);
mWinToken2 = task2.token;
+ boundsChanged = true;
}
+ return boundsChanged;
}
private int getSmallestWidthDp(Rect bounds) {
@@ -1091,7 +1113,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
// ImePositionProcessor#onImeVisibilityChanged directly in DividerView is not enough
// because DividerView won't receive onImeVisibilityChanged callback after it being
// re-inflated.
- mSplitWindowManager.setInteractive(!mImeShown || !mHasImeFocus,
+ setDividerInteractive(!mImeShown || !mHasImeFocus || isFloating, true,
"onImeStartPositioning");
return needOffset ? IME_ANIMATION_NO_ALPHA : 0;
@@ -1118,7 +1140,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
// Restore the split layout when wm-shell is not controlling IME insets anymore.
if (!controlling && mImeShown) {
reset();
- mSplitWindowManager.setInteractive(true, "onImeControlTargetChanged");
+ setDividerInteractive(true, true, "onImeControlTargetChanged");
mSplitLayoutHandler.setLayoutOffsetTarget(0, 0, SplitLayout.this);
mSplitLayoutHandler.onLayoutPositionChanging(SplitLayout.this);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
index eb3c1df0ae73..00361d9dd9cf 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
@@ -168,9 +168,16 @@ public final class SplitWindowManager extends WindowlessWindowManager {
}
}
- void setInteractive(boolean interactive, String from) {
+ /**
+ * Set divider should interactive to user or not.
+ *
+ * @param interactive divider interactive.
+ * @param hideHandle divider handle hidden or not, only work when interactive is false.
+ * @param from caller from where.
+ */
+ void setInteractive(boolean interactive, boolean hideHandle, String from) {
if (mDividerView == null) return;
- mDividerView.setInteractive(interactive, from);
+ mDividerView.setInteractive(interactive, hideHandle, from);
}
View getDividerView() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
index 3b2db5127316..76d9152fdfbc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
@@ -126,14 +126,12 @@ public class CompatUIController implements OnDisplaysChangedListener,
private final Lazy<Transitions> mTransitionsLazy;
private final DockStateReader mDockStateReader;
private final CompatUIConfiguration mCompatUIConfiguration;
-
- private CompatUICallback mCallback;
-
// Only show each hint once automatically in the process life.
private final CompatUIHintsState mCompatUIHintsState;
-
private final CompatUIShellCommandHandler mCompatUIShellCommandHandler;
+ private CompatUICallback mCallback;
+
// Indicates if the keyguard is currently showing, in which case compat UIs shouldn't
// be shown.
private boolean mKeyguardShowing;
@@ -372,19 +370,20 @@ public class CompatUIController implements OnDisplaysChangedListener,
RestartDialogWindowManager layout =
mTaskIdToRestartDialogWindowManagerMap.get(taskInfo.taskId);
if (layout != null) {
- // TODO(b/266262111) Handle theme change when taskListener changes
- if (layout.getTaskListener() != taskListener) {
- mSetOfTaskIdsShowingRestartDialog.remove(taskInfo.taskId);
- }
- layout.setRequestRestartDialog(
- mSetOfTaskIdsShowingRestartDialog.contains(taskInfo.taskId));
- // UI already exists, update the UI layout.
- if (!layout.updateCompatInfo(taskInfo, taskListener,
- showOnDisplay(layout.getDisplayId()))) {
- // The layout is no longer eligible to be shown, remove from active layouts.
+ if (layout.needsToBeRecreated(taskInfo, taskListener)) {
mTaskIdToRestartDialogWindowManagerMap.remove(taskInfo.taskId);
+ layout.release();
+ } else {
+ layout.setRequestRestartDialog(
+ mSetOfTaskIdsShowingRestartDialog.contains(taskInfo.taskId));
+ // UI already exists, update the UI layout.
+ if (!layout.updateCompatInfo(taskInfo, taskListener,
+ showOnDisplay(layout.getDisplayId()))) {
+ // The layout is no longer eligible to be shown, remove from active layouts.
+ mTaskIdToRestartDialogWindowManagerMap.remove(taskInfo.taskId);
+ }
+ return;
}
- return;
}
// Create a new UI layout.
final Context context = getOrCreateDisplayContext(taskInfo.displayId);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java
index efd459498adb..b22c9c7e7529 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java
@@ -151,7 +151,6 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana
@Override
public void setConfiguration(Configuration configuration) {
super.setConfiguration(configuration);
- // TODO(b/266262111): Investigate loss of theme configuration when switching TaskListener
mContext = mContext.createConfigurationContext(configuration);
}
@@ -210,7 +209,8 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana
}
View layout = getLayout();
- if (layout == null || prevTaskListener != taskListener) {
+ if (layout == null || prevTaskListener != taskListener
+ || mTaskConfig.uiMode != prevTaskConfig.uiMode) {
// Layout wasn't created yet or TaskListener changed, recreate the layout for new
// surface parent.
release();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java
index 10f25d0eef11..2440838844c4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java
@@ -155,6 +155,11 @@ class RestartDialogWindowManager extends CompatUIWindowManagerAbstract {
return super.updateCompatInfo(taskInfo, taskListener, canShow);
}
+ boolean needsToBeRecreated(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener) {
+ return taskInfo.configuration.uiMode != mTaskInfo.configuration.uiMode
+ || !getTaskListener().equals(taskListener);
+ }
+
private void updateDialogMargins() {
if (mLayout == null) {
return;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index d1f439894c47..948bf2d100f9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -196,7 +196,8 @@ public abstract class WMShellModule {
DisplayController displayController,
SyncTransactionQueue syncQueue,
Optional<DesktopModeController> desktopModeController,
- Optional<DesktopTasksController> desktopTasksController) {
+ Optional<DesktopTasksController> desktopTasksController,
+ Optional<SplitScreenController> splitScreenController) {
if (DesktopModeStatus.isAnyEnabled()) {
return new DesktopModeWindowDecorViewModel(
context,
@@ -206,7 +207,8 @@ public abstract class WMShellModule {
displayController,
syncQueue,
desktopModeController,
- desktopTasksController);
+ desktopTasksController,
+ splitScreenController);
}
return new CaptionWindowDecorViewModel(
context,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
index fce013837f01..73a740381090 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
@@ -85,7 +85,7 @@ class DesktopTasksController(
fun showDesktopApps() {
ProtoLog.v(WM_SHELL_DESKTOP_MODE, "showDesktopApps")
val wct = WindowContainerTransaction()
- bringDesktopAppsToFront(wct, force = true)
+ bringDesktopAppsToFront(wct)
// Execute transaction if there are pending operations
if (!wct.isEmpty) {
@@ -156,19 +156,9 @@ class DesktopTasksController(
?: WINDOWING_MODE_UNDEFINED
}
- private fun bringDesktopAppsToFront(wct: WindowContainerTransaction, force: Boolean = false) {
- val activeTasks = desktopModeTaskRepository.getActiveTasks()
-
- // Skip if all tasks are already visible
- if (!force && activeTasks.all(desktopModeTaskRepository::isVisibleTask)) {
- ProtoLog.d(
- WM_SHELL_DESKTOP_MODE,
- "bringDesktopAppsToFront: active tasks are already in front, skipping."
- )
- return
- }
-
+ private fun bringDesktopAppsToFront(wct: WindowContainerTransaction) {
ProtoLog.v(WM_SHELL_DESKTOP_MODE, "bringDesktopAppsToFront")
+ val activeTasks = desktopModeTaskRepository.getActiveTasks()
// First move home to front and then other tasks on top of it
moveHomeTaskToFront(wct)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
index b59fe1818780..4cfaae6e51c7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
@@ -36,6 +36,7 @@ import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_U
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import android.content.ClipDescription;
+import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
@@ -58,9 +59,9 @@ import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.R;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.common.annotations.ExternalMainThread;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.splitscreen.SplitScreenController;
-import com.android.wm.shell.sysui.ConfigurationChangeListener;
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
@@ -70,7 +71,7 @@ import java.util.ArrayList;
* Handles the global drag and drop handling for the Shell.
*/
public class DragAndDropController implements DisplayController.OnDisplaysChangedListener,
- View.OnDragListener, ConfigurationChangeListener {
+ View.OnDragListener, ComponentCallbacks2 {
private static final String TAG = DragAndDropController.class.getSimpleName();
@@ -119,7 +120,6 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange
mMainExecutor.executeDelayed(() -> {
mDisplayController.addDisplayWindowListener(this);
}, 0);
- mShellController.addConfigurationChangeListener(this);
}
/**
@@ -180,6 +180,7 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange
try {
wm.addView(rootView, layoutParams);
addDisplayDropTarget(displayId, context, wm, rootView, dragLayout);
+ context.registerComponentCallbacks(this);
} catch (WindowManager.InvalidDisplayException e) {
Slog.w(TAG, "Unable to add view for display id: " + displayId);
}
@@ -209,6 +210,7 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange
if (pd == null) {
return;
}
+ pd.context.unregisterComponentCallbacks(this);
pd.wm.removeViewImmediate(pd.rootView);
mDisplayDropTargets.remove(displayId);
}
@@ -328,18 +330,29 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange
return mimeTypes;
}
+ // Note: Component callbacks are always called on the main thread of the process
+ @ExternalMainThread
@Override
- public void onThemeChanged() {
- for (int i = 0; i < mDisplayDropTargets.size(); i++) {
- mDisplayDropTargets.get(i).dragLayout.onThemeChange();
- }
+ public void onConfigurationChanged(Configuration newConfig) {
+ mMainExecutor.execute(() -> {
+ for (int i = 0; i < mDisplayDropTargets.size(); i++) {
+ mDisplayDropTargets.get(i).dragLayout.onConfigChanged(newConfig);
+ }
+ });
}
+ // Note: Component callbacks are always called on the main thread of the process
+ @ExternalMainThread
@Override
- public void onConfigurationChanged(Configuration newConfig) {
- for (int i = 0; i < mDisplayDropTargets.size(); i++) {
- mDisplayDropTargets.get(i).dragLayout.onConfigChanged(newConfig);
- }
+ public void onTrimMemory(int level) {
+ // Do nothing
+ }
+
+ // Note: Component callbacks are always called on the main thread of the process
+ @ExternalMainThread
+ @Override
+ public void onLowMemory() {
+ // Do nothing
}
private static class PerDisplay {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
index 44fd8eec4d06..fe42822ab6a1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
@@ -18,6 +18,8 @@ package com.android.wm.shell.draganddrop;
import static android.app.StatusBarManager.DISABLE_NONE;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.content.pm.ActivityInfo.CONFIG_ASSETS_PATHS;
+import static android.content.pm.ActivityInfo.CONFIG_UI_MODE;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
@@ -72,6 +74,7 @@ public class DragLayout extends LinearLayout {
private final SplitScreenController mSplitScreenController;
private final IconProvider mIconProvider;
private final StatusBarManager mStatusBarManager;
+ private final Configuration mLastConfiguration = new Configuration();
private DragAndDropPolicy.Target mCurrentTarget = null;
private DropZoneView mDropZoneView1;
@@ -92,6 +95,7 @@ public class DragLayout extends LinearLayout {
mIconProvider = iconProvider;
mPolicy = new DragAndDropPolicy(context, splitScreenController);
mStatusBarManager = context.getSystemService(StatusBarManager.class);
+ mLastConfiguration.setTo(context.getResources().getConfiguration());
mDisplayMargin = context.getResources().getDimensionPixelSize(
R.dimen.drop_layout_display_margin);
@@ -132,11 +136,6 @@ public class DragLayout extends LinearLayout {
return super.onApplyWindowInsets(insets);
}
- public void onThemeChange() {
- mDropZoneView1.onThemeChange();
- mDropZoneView2.onThemeChange();
- }
-
public void onConfigChanged(Configuration newConfig) {
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE
&& getOrientation() != HORIZONTAL) {
@@ -147,6 +146,15 @@ public class DragLayout extends LinearLayout {
setOrientation(LinearLayout.VERTICAL);
updateContainerMargins(newConfig.orientation);
}
+
+ final int diff = newConfig.diff(mLastConfiguration);
+ final boolean themeChanged = (diff & CONFIG_ASSETS_PATHS) != 0
+ || (diff & CONFIG_UI_MODE) != 0;
+ if (themeChanged) {
+ mDropZoneView1.onThemeChange();
+ mDropZoneView2.onThemeChange();
+ }
+ mLastConfiguration.setTo(newConfig);
}
private void updateContainerMarginsForSingleTask() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java
index 26f47fcdaa44..d094c229e0f8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java
@@ -108,6 +108,10 @@ public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {
}
if (!createdWindowDecor) {
mSyncQueue.runInSync(t -> {
+ if (!leash.isValid()) {
+ // Task vanished before sync completion
+ return;
+ }
// Reset several properties back to fullscreen (PiP, for example, leaves all these
// properties in a bad state).
t.setWindowCrop(leash, null);
@@ -136,6 +140,10 @@ public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {
final Point positionInParent = state.mTaskInfo.positionInParent;
if (!oldPositionInParent.equals(state.mTaskInfo.positionInParent)) {
mSyncQueue.runInSync(t -> {
+ if (!state.mLeash.isValid()) {
+ // Task vanished before sync completion
+ return;
+ }
t.setPosition(state.mLeash, positionInParent.x, positionInParent.y);
});
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java
index ac13f96585b6..9796e4c29352 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java
@@ -36,6 +36,7 @@ import android.os.IBinder;
import android.view.InsetsSource;
import android.view.InsetsState;
import android.view.SurfaceControl;
+import android.view.WindowInsets;
import android.window.ITaskOrganizerController;
import android.window.TaskAppearedInfo;
import android.window.WindowContainerToken;
@@ -57,7 +58,6 @@ import com.android.wm.shell.unfold.UnfoldAnimationController;
import java.io.PrintWriter;
import java.util.List;
-import java.util.Objects;
import java.util.Optional;
/**
@@ -130,14 +130,34 @@ public class KidsModeTaskOrganizer extends ShellTaskOrganizer {
new DisplayInsetsController.OnInsetsChangedListener() {
@Override
public void insetsChanged(InsetsState insetsState) {
- // Update bounds only when the insets of navigation bar or task bar is changed.
- if (Objects.equals(insetsState.peekSource(InsetsState.ITYPE_NAVIGATION_BAR),
- mInsetsState.peekSource(InsetsState.ITYPE_NAVIGATION_BAR))
- && Objects.equals(insetsState.peekSource(
- InsetsState.ITYPE_EXTRA_NAVIGATION_BAR),
- mInsetsState.peekSource(InsetsState.ITYPE_EXTRA_NAVIGATION_BAR))) {
+ final boolean[] navigationBarChanged = {false};
+ InsetsState.traverse(insetsState, mInsetsState, new InsetsState.OnTraverseCallbacks() {
+ @Override
+ public void onIdMatch(InsetsSource source1, InsetsSource source2) {
+ if (source1.getType() == WindowInsets.Type.navigationBars()
+ && !source1.equals(source2)) {
+ navigationBarChanged[0] = true;
+ }
+ }
+
+ @Override
+ public void onIdNotFoundInState1(int index2, InsetsSource source2) {
+ if (source2.getType() == WindowInsets.Type.navigationBars()) {
+ navigationBarChanged[0] = true;
+ }
+ }
+
+ @Override
+ public void onIdNotFoundInState2(int index1, InsetsSource source1) {
+ if (source1.getType() == WindowInsets.Type.navigationBars()) {
+ navigationBarChanged[0] = true;
+ }
+ }
+ });
+ if (!navigationBarChanged[0]) {
return;
}
+ // Update bounds only when the insets of navigation bar or task bar is changed.
mInsetsState.set(insetsState);
updateBounds();
}
@@ -344,16 +364,8 @@ public class KidsModeTaskOrganizer extends ShellTaskOrganizer {
private Rect calculateBounds() {
final Rect bounds = new Rect(0, 0, mDisplayWidth, mDisplayHeight);
- final InsetsSource navBarSource = mInsetsState.peekSource(InsetsState.ITYPE_NAVIGATION_BAR);
- final InsetsSource taskBarSource = mInsetsState.peekSource(
- InsetsState.ITYPE_EXTRA_NAVIGATION_BAR);
- if (navBarSource != null && !navBarSource.getFrame().isEmpty()) {
- bounds.inset(navBarSource.calculateInsets(bounds, false /* ignoreVisibility */));
- } else if (taskBarSource != null && !taskBarSource.getFrame().isEmpty()) {
- bounds.inset(taskBarSource.calculateInsets(bounds, false /* ignoreVisibility */));
- } else {
- bounds.setEmpty();
- }
+ bounds.inset(mInsetsState.calculateInsets(
+ bounds, WindowInsets.Type.navigationBars(), false /* ignoreVisibility */));
return bounds;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
index e5c0570841f4..6b0337d3fb4a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
@@ -40,7 +40,6 @@ import static com.android.wm.shell.pip.PipTransitionState.ENTERED_PIP;
import static com.android.wm.shell.transition.Transitions.TRANSIT_EXIT_PIP;
import static com.android.wm.shell.transition.Transitions.TRANSIT_EXIT_PIP_TO_SPLIT;
import static com.android.wm.shell.transition.Transitions.TRANSIT_REMOVE_PIP;
-import static com.android.wm.shell.transition.Transitions.isOpeningType;
import android.animation.Animator;
import android.app.ActivityManager;
@@ -72,6 +71,7 @@ import com.android.wm.shell.splitscreen.SplitScreenController;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.transition.CounterRotatorHelper;
import com.android.wm.shell.transition.Transitions;
+import com.android.wm.shell.util.TransitionUtil;
import java.util.Optional;
@@ -702,7 +702,7 @@ public class PipTransition extends PipTransitionController {
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
final TransitionInfo.Change change = info.getChanges().get(i);
if (change == enterPip) continue;
- if (isOpeningType(change.getMode())) {
+ if (TransitionUtil.isOpeningType(change.getMode())) {
final SurfaceControl leash = change.getLeash();
startTransaction.show(leash).setAlpha(leash, 1.f);
}
@@ -873,7 +873,7 @@ public class PipTransition extends PipTransitionController {
continue;
}
- if (isOpeningType(mode) && change.getParent() == null) {
+ if (TransitionUtil.isOpeningType(mode) && change.getParent() == null) {
final SurfaceControl leash = change.getLeash();
final Rect endBounds = change.getEndAbsBounds();
startTransaction
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java
index 7619646804ad..9729a4007bac 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java
@@ -235,21 +235,14 @@ public class PipDismissTargetHandler implements ViewTreeObserver.OnPreDrawListen
/** Adds the magnetic target view to the WindowManager so it's ready to be animated in. */
public void createOrUpdateDismissTarget() {
- if (!mTargetViewContainer.isAttachedToWindow()) {
+ if (mTargetViewContainer.getParent() == null) {
mTargetViewContainer.cancelAnimators();
mTargetViewContainer.setVisibility(View.INVISIBLE);
mTargetViewContainer.getViewTreeObserver().removeOnPreDrawListener(this);
mHasDismissTargetSurface = false;
- try {
- mWindowManager.addView(mTargetViewContainer, getDismissTargetLayoutParams());
- } catch (IllegalStateException e) {
- // This shouldn't happen, but if the target is already added, just update its layout
- // params.
- mWindowManager.updateViewLayout(
- mTargetViewContainer, getDismissTargetLayoutParams());
- }
+ mWindowManager.addView(mTargetViewContainer, getDismissTargetLayoutParams());
} else {
mWindowManager.updateViewLayout(mTargetViewContainer, getDismissTargetLayoutParams());
}
@@ -306,7 +299,7 @@ public class PipDismissTargetHandler implements ViewTreeObserver.OnPreDrawListen
* Removes the dismiss target and cancels any pending callbacks to show it.
*/
public void cleanUpDismissTarget() {
- if (mTargetViewContainer.isAttachedToWindow()) {
+ if (mTargetViewContainer.getParent() != null) {
mWindowManager.removeViewImmediate(mTargetViewContainer);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
index 41ff0b35a035..fee9140d0c2c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
@@ -228,7 +228,7 @@ public class PipResizeGestureHandler {
if (mIsEnabled) {
// Register input event receiver
- mInputMonitor = InputManager.getInstance().monitorGestureInput(
+ mInputMonitor = mContext.getSystemService(InputManager.class).monitorGestureInput(
"pip-resize", mDisplayId);
try {
mMainExecutor.executeBlocking(() -> {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java
index 8895fcab0c3d..73123b153382 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java
@@ -25,16 +25,14 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Insets;
-import android.graphics.Matrix;
import android.graphics.Rect;
-import android.graphics.RectF;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.SurfaceControl;
-import android.view.SyncRtSurfaceTransactionApplier;
import android.view.View;
import android.view.ViewRootImpl;
import android.view.WindowManagerGlobal;
+import android.window.SurfaceSyncGroup;
import androidx.annotation.Nullable;
@@ -71,12 +69,6 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis
// exiting the move menu instead of showing the regular button menu.
private boolean mCloseAfterExitMoveMenu;
- private SyncRtSurfaceTransactionApplier mApplier;
- private SyncRtSurfaceTransactionApplier mBackgroundApplier;
- RectF mTmpSourceRectF = new RectF();
- RectF mTmpDestinationRectF = new RectF();
- Matrix mMoveTransform = new Matrix();
-
public TvPipMenuController(Context context, TvPipBoundsState tvPipBoundsState,
SystemWindows systemWindows, Handler mainHandler) {
mContext = context;
@@ -324,44 +316,36 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis
*/
@Override
public void resizePipMenu(@Nullable SurfaceControl pipLeash,
- @Nullable SurfaceControl.Transaction t,
- Rect destinationBounds) {
+ @Nullable SurfaceControl.Transaction pipTx,
+ Rect pipBounds) {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
- "%s: resizePipMenu: %s", TAG, destinationBounds.toShortString());
- if (destinationBounds.isEmpty()) {
+ "%s: resizePipMenu: %s", TAG, pipBounds.toShortString());
+ if (pipBounds.isEmpty()) {
return;
}
- if (!maybeCreateSyncApplier()) {
+ if (!isMenuReadyToMove()) {
return;
}
- final Rect menuBounds = calculateMenuSurfaceBounds(destinationBounds);
final SurfaceControl frontSurface = getSurfaceControl(mPipMenuView);
- final SyncRtSurfaceTransactionApplier.SurfaceParams frontParams =
- new SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(frontSurface)
- .withWindowCrop(menuBounds)
- .build();
-
final SurfaceControl backSurface = getSurfaceControl(mPipBackgroundView);
- final SyncRtSurfaceTransactionApplier.SurfaceParams backParams =
- new SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(backSurface)
- .withWindowCrop(menuBounds)
- .build();
-
- // TODO(b/226580399): switch to using SurfaceSyncer (see b/200284684) to synchronize the
- // animations of the pip surface with the content of the front and back menu surfaces
- mBackgroundApplier.scheduleApply(backParams);
- if (pipLeash != null && t != null) {
- final SyncRtSurfaceTransactionApplier.SurfaceParams
- pipParams = new SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(pipLeash)
- .withMergeTransaction(t)
- .build();
- mApplier.scheduleApply(frontParams, pipParams);
- } else {
- mApplier.scheduleApply(frontParams);
+ final Rect menuBounds = calculateMenuSurfaceBounds(pipBounds);
+ if (pipTx == null) {
+ pipTx = new SurfaceControl.Transaction();
}
+ pipTx.setWindowCrop(frontSurface, menuBounds.width(), menuBounds.height());
+ pipTx.setWindowCrop(backSurface, menuBounds.width(), menuBounds.height());
+
+ // Synchronize drawing the content in the front and back surfaces together with the pip
+ // transaction and the window crop for the front and back surfaces
+ final SurfaceSyncGroup syncGroup = new SurfaceSyncGroup("TvPip");
+ syncGroup.add(mPipMenuView.getRootSurfaceControl(), null);
+ syncGroup.add(mPipBackgroundView.getRootSurfaceControl(), null);
+ updateMenuBounds(pipBounds);
+ syncGroup.addTransaction(pipTx);
+ syncGroup.markSyncReady();
}
private SurfaceControl getSurfaceControl(View v) {
@@ -369,102 +353,66 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis
}
@Override
- public void movePipMenu(SurfaceControl pipLeash, SurfaceControl.Transaction transaction,
- Rect pipDestBounds) {
+ public void movePipMenu(SurfaceControl pipLeash, SurfaceControl.Transaction pipTx,
+ Rect pipBounds) {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
- "%s: movePipMenu: %s", TAG, pipDestBounds.toShortString());
+ "%s: movePipMenu: %s", TAG, pipBounds.toShortString());
- if (pipDestBounds.isEmpty()) {
- if (transaction == null) {
+ if (pipBounds.isEmpty()) {
+ if (pipTx == null) {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: no transaction given", TAG);
}
return;
}
- if (!maybeCreateSyncApplier()) {
+ if (!isMenuReadyToMove()) {
return;
}
- final Rect menuDestBounds = calculateMenuSurfaceBounds(pipDestBounds);
- final Rect tmpSourceBounds = new Rect();
- // If there is no pip leash supplied, that means the PiP leash is already finalized
- // resizing and the PiP menu is also resized. We then want to do a scale from the current
- // new menu bounds.
- if (pipLeash != null && transaction != null) {
- ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
- "%s: tmpSourceBounds based on mPipMenuView.getBoundsOnScreen()", TAG);
- mPipMenuView.getBoundsOnScreen(tmpSourceBounds);
- } else {
- ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
- "%s: tmpSourceBounds based on menu width and height", TAG);
- tmpSourceBounds.set(0, 0, menuDestBounds.width(), menuDestBounds.height());
- }
-
- mTmpSourceRectF.set(tmpSourceBounds);
- mTmpDestinationRectF.set(menuDestBounds);
- mMoveTransform.setTranslate(mTmpDestinationRectF.left, mTmpDestinationRectF.top);
-
final SurfaceControl frontSurface = getSurfaceControl(mPipMenuView);
- final SyncRtSurfaceTransactionApplier.SurfaceParams frontParams =
- new SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(frontSurface)
- .withMatrix(mMoveTransform)
- .build();
-
final SurfaceControl backSurface = getSurfaceControl(mPipBackgroundView);
- final SyncRtSurfaceTransactionApplier.SurfaceParams backParams =
- new SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(backSurface)
- .withMatrix(mMoveTransform)
- .build();
-
- // TODO(b/226580399): switch to using SurfaceSyncer (see b/200284684) to synchronize the
- // animations of the pip surface with the content of the front and back menu surfaces
- mBackgroundApplier.scheduleApply(backParams);
- if (pipLeash != null && transaction != null) {
- final SyncRtSurfaceTransactionApplier.SurfaceParams pipParams =
- new SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(pipLeash)
- .withMergeTransaction(transaction)
- .build();
- mApplier.scheduleApply(frontParams, pipParams);
- } else {
- mApplier.scheduleApply(frontParams);
- }
-
- updateMenuBounds(pipDestBounds);
- }
-
- private boolean maybeCreateSyncApplier() {
- if (mPipMenuView == null || mPipMenuView.getViewRootImpl() == null) {
+ final Rect menuDestBounds = calculateMenuSurfaceBounds(pipBounds);
+ if (pipTx == null) {
+ pipTx = new SurfaceControl.Transaction();
+ }
+ pipTx.setPosition(frontSurface, menuDestBounds.left, menuDestBounds.top);
+ pipTx.setPosition(backSurface, menuDestBounds.left, menuDestBounds.top);
+
+ // Synchronize drawing the content in the front and back surfaces together with the pip
+ // transaction and the position change for the front and back surfaces
+ final SurfaceSyncGroup syncGroup = new SurfaceSyncGroup("TvPip");
+ syncGroup.add(mPipMenuView.getRootSurfaceControl(), null);
+ syncGroup.add(mPipBackgroundView.getRootSurfaceControl(), null);
+ updateMenuBounds(pipBounds);
+ syncGroup.addTransaction(pipTx);
+ syncGroup.markSyncReady();
+ }
+
+ private boolean isMenuReadyToMove() {
+ final boolean ready = mPipMenuView != null && mPipMenuView.getViewRootImpl() != null
+ && mPipBackgroundView != null && mPipBackgroundView.getViewRootImpl() != null;
+ if (!ready) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: Not going to move PiP, either menu or its parent is not created.", TAG);
- return false;
}
-
- if (mApplier == null) {
- mApplier = new SyncRtSurfaceTransactionApplier(mPipMenuView);
- }
- if (mBackgroundApplier == null) {
- mBackgroundApplier = new SyncRtSurfaceTransactionApplier(mPipBackgroundView);
- }
- return true;
+ return ready;
}
private void detachPipMenu() {
if (mPipMenuView != null) {
- mApplier = null;
mSystemWindows.removeView(mPipMenuView);
mPipMenuView = null;
}
if (mPipBackgroundView != null) {
- mBackgroundApplier = null;
mSystemWindows.removeView(mPipBackgroundView);
mPipBackgroundView = null;
}
}
@Override
- public void updateMenuBounds(Rect destinationBounds) {
- final Rect menuBounds = calculateMenuSurfaceBounds(destinationBounds);
+ public void updateMenuBounds(Rect pipBounds) {
+ final Rect menuBounds = calculateMenuSurfaceBounds(pipBounds);
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: updateMenuBounds: %s", TAG, menuBounds.toShortString());
mSystemWindows.updateViewLayout(mPipBackgroundView,
@@ -473,9 +421,8 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis
mSystemWindows.updateViewLayout(mPipMenuView,
getPipMenuLayoutParams(mContext, MENU_WINDOW_TITLE, menuBounds.width(),
menuBounds.height()));
-
if (mPipMenuView != null) {
- mPipMenuView.updateBounds(destinationBounds);
+ mPipMenuView.updateBounds(pipBounds);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogImpl.java
index c59c42dadb9d..93ffb3dc8115 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogImpl.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogImpl.java
@@ -31,7 +31,8 @@ import java.io.PrintWriter;
*/
public class ShellProtoLogImpl extends BaseProtoLogImpl {
private static final String TAG = "ProtoLogImpl";
- private static final int BUFFER_CAPACITY = 128 * 1024;
+ private static final int BUFFER_CAPACITY = 1024 * 1024;
+ // TODO: find a proper location to save the protolog message file
private static final String LOG_FILENAME = "/data/misc/wmtrace/shell_log.winscope";
private static final String VIEWER_CONFIG_FILENAME = "/system_ext/etc/wmshell.protolog.json.gz";
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index c7ad4fdcacf0..94b9e907fa76 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -422,6 +422,11 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
mStageCoordinator.goToFullscreenFromSplit();
}
+ /** Move the specified task to fullscreen, regardless of focus state. */
+ public void moveTaskToFullscreen(int taskId) {
+ mStageCoordinator.moveTaskToFullscreen(taskId);
+ }
+
public boolean isLaunchToSplit(TaskInfo taskInfo) {
return mStageCoordinator.isLaunchToSplit(taskInfo);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
index 520da92fad72..e1c089550c2d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
@@ -53,6 +53,7 @@ import com.android.wm.shell.common.split.SplitDecorManager;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.transition.OneShotRemoteHandler;
import com.android.wm.shell.transition.Transitions;
+import com.android.wm.shell.util.TransitionUtil;
import java.util.ArrayList;
@@ -339,6 +340,12 @@ class SplitScreenTransitions {
IBinder startResizeTransition(WindowContainerTransaction wct,
Transitions.TransitionHandler handler,
@Nullable TransitionFinishedCallback finishCallback) {
+ if (mPendingResize != null) {
+ mPendingResize.cancel(null);
+ mAnimations.clear();
+ onFinish(null /* wct */, null /* wctCB */);
+ }
+
IBinder transition = mTransitions.startTransition(TRANSIT_CHANGE, wct, handler);
setResizeTransition(transition, finishCallback);
return transition;
@@ -531,7 +538,7 @@ class SplitScreenTransitions {
}
private boolean isOpeningTransition(TransitionInfo info) {
- return Transitions.isOpeningType(info.getType())
+ return TransitionUtil.isOpeningType(info.getType())
|| info.getType() == TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE
|| info.getType() == TRANSIT_SPLIT_SCREEN_PAIR_OPEN;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 19d8cfac559a..225258773013 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -20,7 +20,6 @@ import static android.app.ActivityOptions.KEY_LAUNCH_ROOT_TASK_TOKEN;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.ComponentOptions.KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED;
import static android.app.ComponentOptions.KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED_BY_PERMISSION;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
@@ -61,8 +60,8 @@ import static com.android.wm.shell.splitscreen.SplitScreenController.exitReasonT
import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS;
import static com.android.wm.shell.transition.Transitions.TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE;
import static com.android.wm.shell.transition.Transitions.TRANSIT_SPLIT_SCREEN_PAIR_OPEN;
-import static com.android.wm.shell.transition.Transitions.isClosingType;
-import static com.android.wm.shell.transition.Transitions.isOpeningType;
+import static com.android.wm.shell.util.TransitionUtil.isClosingType;
+import static com.android.wm.shell.util.TransitionUtil.isOpeningType;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -135,6 +134,7 @@ import com.android.wm.shell.transition.DefaultMixedHandler;
import com.android.wm.shell.transition.LegacyTransitions;
import com.android.wm.shell.transition.Transitions;
import com.android.wm.shell.util.SplitBounds;
+import com.android.wm.shell.util.TransitionUtil;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -660,6 +660,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
@Nullable Bundle options2, @SplitPosition int splitPosition, float splitRatio,
@Nullable RemoteTransition remoteTransition, InstanceId instanceId) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
+ prepareEvictChildTasksIfSplitActive(wct);
setSideStagePosition(splitPosition, wct);
options1 = options1 != null ? options1 : new Bundle();
addActivityOptions(options1, mSideStage);
@@ -674,6 +675,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
@SplitPosition int splitPosition, float splitRatio,
@Nullable RemoteTransition remoteTransition, InstanceId instanceId) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
+ prepareEvictChildTasksIfSplitActive(wct);
setSideStagePosition(splitPosition, wct);
options1 = options1 != null ? options1 : new Bundle();
addActivityOptions(options1, mSideStage);
@@ -687,6 +689,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
int taskId, @Nullable Bundle options2, @SplitPosition int splitPosition,
float splitRatio, @Nullable RemoteTransition remoteTransition, InstanceId instanceId) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
+ prepareEvictChildTasksIfSplitActive(wct);
setSideStagePosition(splitPosition, wct);
options1 = options1 != null ? options1 : new Bundle();
addActivityOptions(options1, mSideStage);
@@ -705,10 +708,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
private void startWithTask(WindowContainerTransaction wct, int mainTaskId,
@Nullable Bundle mainOptions, float splitRatio,
@Nullable RemoteTransition remoteTransition, InstanceId instanceId) {
- if (mMainStage.isActive()) {
- mMainStage.evictAllChildren(wct);
- mSideStage.evictAllChildren(wct);
- } else {
+ if (!mMainStage.isActive()) {
// Build a request WCT that will launch both apps such that task 0 is on the main stage
// while task 1 is on the side stage.
mMainStage.activate(wct, false /* reparent */);
@@ -936,7 +936,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
new IRemoteAnimationFinishedCallback.Stub() {
@Override
public void onAnimationFinished() throws RemoteException {
- onRemoteAnimationFinishedOrCancelled(false /* cancel */, evictWct);
+ onRemoteAnimationFinishedOrCancelled(evictWct);
finishedCallback.onAnimationFinished();
}
};
@@ -952,7 +952,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
@Override
public void onAnimationCancelled(boolean isKeyguardOccluded) {
- onRemoteAnimationFinishedOrCancelled(true /* cancel */, evictWct);
+ onRemoteAnimationFinishedOrCancelled(evictWct);
try {
adapter.getRunner().onAnimationCancelled(isKeyguardOccluded);
} catch (RemoteException e) {
@@ -973,15 +973,14 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
}
}
- private void onRemoteAnimationFinishedOrCancelled(boolean cancel,
- WindowContainerTransaction evictWct) {
+ private void onRemoteAnimationFinishedOrCancelled(WindowContainerTransaction evictWct) {
mIsSplitEntering = false;
mShouldUpdateRecents = true;
mSplitRequest = null;
// If any stage has no child after animation finished, it means that split will display
// nothing, such status will happen if task and intent is same app but not support
// multi-instance, we should exit split and expand that app as full screen.
- if (!cancel && (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0)) {
+ if (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0) {
mMainExecutor.execute(() ->
exitSplitScreen(mMainStage.getChildCount() == 0
? mSideStage : mMainStage, EXIT_REASON_UNKNOWN));
@@ -1020,6 +1019,13 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mSideStage.evictInvisibleChildren(wct);
}
+ void prepareEvictChildTasksIfSplitActive(WindowContainerTransaction wct) {
+ if (mMainStage.isActive()) {
+ mMainStage.evictAllChildren(wct);
+ mSideStage.evictAllChildren(wct);
+ }
+ }
+
Bundle resolveStartStage(@StageType int stage, @SplitPosition int position,
@Nullable Bundle options, @Nullable WindowContainerTransaction wct) {
switch (stage) {
@@ -1236,8 +1242,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// Notify recents if we are exiting in a way that breaks the pair, and disable further
// updates to splits in the recents until we enter split again
if (shouldBreakPairedTaskInRecents(exitReason) && mShouldUpdateRecents) {
- recentTasks.removeSplitPair(mMainStage.getLastVisibleTaskId());
- recentTasks.removeSplitPair(mSideStage.getLastVisibleTaskId());
+ recentTasks.removeSplitPair(mMainStage.getTopVisibleChildTaskId());
+ recentTasks.removeSplitPair(mSideStage.getTopVisibleChildTaskId());
}
});
mShouldUpdateRecents = false;
@@ -1705,9 +1711,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
}
mSyncQueue.queue(wct);
- mSyncQueue.runInSync(t -> {
- setDividerVisibility(mainStageVisible, t);
- });
+ setDividerVisibility(mainStageVisible, null);
}
private void setDividerVisibility(boolean visible, @Nullable SurfaceControl.Transaction t) {
@@ -1789,6 +1793,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
@Override
public void onAnimationEnd(Animator animation) {
+ if (dividerLeash != null && dividerLeash.isValid()) {
+ transaction.setAlpha(dividerLeash, 1);
+ transaction.apply();
+ }
mTransactionPool.release(transaction);
mDividerFadeInAnimator = null;
}
@@ -1922,10 +1930,14 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
}
final WindowContainerTransaction wct = new WindowContainerTransaction();
- updateWindowBounds(layout, wct);
+ boolean sizeChanged = updateWindowBounds(layout, wct);
+ if (!sizeChanged) return;
+
sendOnBoundsChanged();
if (ENABLE_SHELL_TRANSITIONS) {
- mSplitTransitions.startResizeTransition(wct, this, null /* callback */);
+ mSplitLayout.setDividerInteractive(false, false, "onSplitResizeStart");
+ mSplitTransitions.startResizeTransition(wct, this, (finishWct, t) ->
+ mSplitLayout.setDividerInteractive(true, false, "onSplitResizeFinish"));
} else {
mSyncQueue.queue(wct);
mSyncQueue.runInSync(t -> {
@@ -1944,13 +1956,16 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
/**
* Populates `wct` with operations that match the split windows to the current layout.
* To match relevant surfaces, make sure to call updateSurfaceBounds after `wct` is applied
+ *
+ * @return true if stage bounds actually .
*/
- private void updateWindowBounds(SplitLayout layout, WindowContainerTransaction wct) {
+ private boolean updateWindowBounds(SplitLayout layout, WindowContainerTransaction wct) {
final StageTaskListener topLeftStage =
mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? mSideStage : mMainStage;
final StageTaskListener bottomRightStage =
mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? mMainStage : mSideStage;
- layout.applyTaskChanges(wct, topLeftStage.mRootTaskInfo, bottomRightStage.mRootTaskInfo);
+ return layout.applyTaskChanges(wct, topLeftStage.mRootTaskInfo,
+ bottomRightStage.mRootTaskInfo);
}
void updateSurfaceBounds(@Nullable SplitLayout layout, @NonNull SurfaceControl.Transaction t,
@@ -2151,19 +2166,11 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
}
} else if (isOpening && inFullscreen) {
final int activityType = triggerTask.getActivityType();
- if (activityType == ACTIVITY_TYPE_ASSISTANT) {
- // We don't want assistant panel to dismiss split screen, so do nothing.
- } else if (activityType == ACTIVITY_TYPE_HOME
+ if (activityType == ACTIVITY_TYPE_HOME
|| activityType == ACTIVITY_TYPE_RECENTS) {
// Enter overview panel, so start recent transition.
mSplitTransitions.setRecentTransition(transition, request.getRemoteTransition(),
mRecentTransitionFinishedCallback);
- } else if (mSplitTransitions.mPendingRecent == null) {
- // If split-task is not controlled by recents animation
- // and occluded by the other fullscreen task, dismiss both.
- prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, out);
- mSplitTransitions.setDismissTransition(
- transition, STAGE_TYPE_UNDEFINED, EXIT_REASON_UNKNOWN);
}
}
} else {
@@ -2269,7 +2276,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// Use normal animations.
return false;
- } else if (mMixedHandler != null && Transitions.hasDisplayChange(info)) {
+ } else if (mMixedHandler != null && TransitionUtil.hasDisplayChange(info)) {
// A display-change has been un-expectedly inserted into the transition. Redirect
// handling to the mixed-handler to deal with splitting it up.
if (mMixedHandler.animatePendingSplitWithDisplayChange(transition, info,
@@ -2397,6 +2404,20 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mSplitLayout.flingDividerToDismiss(!leftOrTop, EXIT_REASON_FULLSCREEN_SHORTCUT);
}
+ /** Move the specified task to fullscreen, regardless of focus state. */
+ public void moveTaskToFullscreen(int taskId) {
+ boolean leftOrTop;
+ if (mMainStage.containsTask(taskId)) {
+ leftOrTop = (mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT);
+ } else if (mSideStage.containsTask(taskId)) {
+ leftOrTop = (mSideStagePosition == SPLIT_POSITION_BOTTOM_OR_RIGHT);
+ } else {
+ return;
+ }
+ mSplitLayout.flingDividerToDismiss(!leftOrTop, EXIT_REASON_FULLSCREEN_SHORTCUT);
+
+ }
+
boolean isLaunchToSplit(TaskInfo taskInfo) {
return getActivateSplitPosition(taskInfo) != SPLIT_POSITION_UNDEFINED;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
index 0359761388dc..a841b7f96d3c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
@@ -92,7 +92,6 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
protected SurfaceControl mDimLayer;
protected SparseArray<ActivityManager.RunningTaskInfo> mChildrenTaskInfo = new SparseArray<>();
private final SparseArray<SurfaceControl> mChildrenLeashes = new SparseArray<>();
- private int mLastVisibleTaskId = INVALID_TASK_ID;
// TODO(b/204308910): Extracts SplitDecorManager related code to common package.
private SplitDecorManager mSplitDecorManager;
@@ -124,13 +123,6 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
}
/**
- * Returns the last visible task's id.
- */
- int getLastVisibleTaskId() {
- return mLastVisibleTaskId;
- }
-
- /**
* Returns the top visible child task's id.
*/
int getTopVisibleChildTaskId() {
@@ -229,9 +221,6 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
return;
}
mChildrenTaskInfo.put(taskInfo.taskId, taskInfo);
- if (taskInfo.isVisible && taskInfo.taskId != mLastVisibleTaskId) {
- mLastVisibleTaskId = taskInfo.taskId;
- }
mCallbacks.onChildTaskStatusChanged(taskInfo.taskId, true /* present */,
taskInfo.isVisible);
if (!ENABLE_SHELL_TRANSITIONS) {
@@ -264,9 +253,6 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
} else if (mChildrenTaskInfo.contains(taskId)) {
mChildrenTaskInfo.remove(taskId);
mChildrenLeashes.remove(taskId);
- if (taskId == mLastVisibleTaskId) {
- mLastVisibleTaskId = INVALID_TASK_ID;
- }
mCallbacks.onChildTaskStatusChanged(taskId, false /* present */, taskInfo.isVisible);
if (ENABLE_SHELL_TRANSITIONS) {
// Status is managed/synchronized by the transition lifecycle.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/AbsSplashWindowCreator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/AbsSplashWindowCreator.java
deleted file mode 100644
index 1ddd8f9a3a14..000000000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/AbsSplashWindowCreator.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.startingsurface;
-
-import android.content.Context;
-import android.content.pm.ActivityInfo;
-import android.hardware.display.DisplayManager;
-import android.view.Display;
-
-import com.android.wm.shell.common.ShellExecutor;
-
-// abstract class to create splash screen window(or windowless window)
-abstract class AbsSplashWindowCreator {
- protected static final String TAG = StartingWindowController.TAG;
- protected final SplashscreenContentDrawer mSplashscreenContentDrawer;
- protected final Context mContext;
- protected final DisplayManager mDisplayManager;
- protected final ShellExecutor mSplashScreenExecutor;
- protected final StartingSurfaceDrawer.StartingWindowRecordManager mStartingWindowRecordManager;
-
- private StartingSurface.SysuiProxy mSysuiProxy;
-
- AbsSplashWindowCreator(SplashscreenContentDrawer contentDrawer, Context context,
- ShellExecutor splashScreenExecutor, DisplayManager displayManager,
- StartingSurfaceDrawer.StartingWindowRecordManager startingWindowRecordManager) {
- mSplashscreenContentDrawer = contentDrawer;
- mContext = context;
- mSplashScreenExecutor = splashScreenExecutor;
- mDisplayManager = displayManager;
- mStartingWindowRecordManager = startingWindowRecordManager;
- }
-
- int getSplashScreenTheme(int splashScreenThemeResId, ActivityInfo activityInfo) {
- return splashScreenThemeResId != 0
- ? splashScreenThemeResId
- : activityInfo.getThemeResource() != 0 ? activityInfo.getThemeResource()
- : com.android.internal.R.style.Theme_DeviceDefault_DayNight;
- }
-
- protected Display getDisplay(int displayId) {
- return mDisplayManager.getDisplay(displayId);
- }
-
- void setSysuiProxy(StartingSurface.SysuiProxy sysuiProxy) {
- mSysuiProxy = sysuiProxy;
- }
-
- protected void requestTopUi(boolean requestTopUi) {
- if (mSysuiProxy != null) {
- mSysuiProxy.requestTopUi(requestTopUi, TAG);
- }
- }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SnapshotWindowCreator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SnapshotWindowCreator.java
deleted file mode 100644
index 20c4d5ae5f58..000000000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SnapshotWindowCreator.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.startingsurface;
-
-import android.window.StartingWindowInfo;
-import android.window.TaskSnapshot;
-
-import com.android.wm.shell.common.ShellExecutor;
-
-class SnapshotWindowCreator {
- private final ShellExecutor mMainExecutor;
- private final StartingSurfaceDrawer.StartingWindowRecordManager
- mStartingWindowRecordManager;
-
- SnapshotWindowCreator(ShellExecutor mainExecutor,
- StartingSurfaceDrawer.StartingWindowRecordManager startingWindowRecordManager) {
- mMainExecutor = mainExecutor;
- mStartingWindowRecordManager = startingWindowRecordManager;
- }
-
- void makeTaskSnapshotWindow(StartingWindowInfo startingWindowInfo, TaskSnapshot snapshot) {
- final int taskId = startingWindowInfo.taskInfo.taskId;
- // Remove any existing starting window for this task before adding.
- mStartingWindowRecordManager.removeWindow(taskId, true);
- final TaskSnapshotWindow surface = TaskSnapshotWindow.create(startingWindowInfo,
- startingWindowInfo.appToken, snapshot, mMainExecutor,
- () -> mStartingWindowRecordManager.removeWindow(taskId, true));
- if (surface != null) {
- final SnapshotWindowRecord tView = new SnapshotWindowRecord(surface,
- startingWindowInfo.taskInfo.topActivityType, mMainExecutor);
- mStartingWindowRecordManager.addRecord(taskId, tView);
- }
- }
-
- private static class SnapshotWindowRecord extends StartingSurfaceDrawer.SnapshotRecord {
- private final TaskSnapshotWindow mTaskSnapshotWindow;
-
- SnapshotWindowRecord(TaskSnapshotWindow taskSnapshotWindow,
- int activityType, ShellExecutor removeExecutor) {
- super(activityType, removeExecutor);
- mTaskSnapshotWindow = taskSnapshotWindow;
- mBGColor = mTaskSnapshotWindow.getBackgroundColor();
- }
-
- @Override
- protected void removeImmediately() {
- super.removeImmediately();
- mTaskSnapshotWindow.removeImmediately();
- }
-
- @Override
- protected boolean hasImeSurface() {
- return mTaskSnapshotWindow.hasImeSurface();
- }
- }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
index 79cd891741d6..ebb957b2201b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
@@ -24,6 +24,9 @@ import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_LEGACY_SPLA
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SOLID_COLOR_SPLASH_SCREEN;
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
+import static com.android.wm.shell.startingsurface.StartingSurfaceDrawer.MAX_ANIMATION_DURATION;
+import static com.android.wm.shell.startingsurface.StartingSurfaceDrawer.MINIMAL_ANIMATION_DURATION;
+
import android.annotation.ColorInt;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -93,25 +96,6 @@ import java.util.function.UnaryOperator;
public class SplashscreenContentDrawer {
private static final String TAG = StartingWindowController.TAG;
- /**
- * The minimum duration during which the splash screen is shown when the splash screen icon is
- * animated.
- */
- static final long MINIMAL_ANIMATION_DURATION = 400L;
-
- /**
- * Allow the icon style splash screen to be displayed for longer to give time for the animation
- * to finish, i.e. the extra buffer time to keep the splash screen if the animation is slightly
- * longer than the {@link #MINIMAL_ANIMATION_DURATION} duration.
- */
- static final long TIME_WINDOW_DURATION = 100L;
-
- /**
- * The maximum duration during which the splash screen will be shown if the application is ready
- * to show before the icon animation finishes.
- */
- static final long MAX_ANIMATION_DURATION = MINIMAL_ANIMATION_DURATION + TIME_WINDOW_DURATION;
-
// The acceptable area ratio of foreground_icon_area/background_icon_area, if there is an
// icon which it's non-transparent foreground area is similar to it's background area, then
// do not enlarge the foreground drawable.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenWindowCreator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenWindowCreator.java
deleted file mode 100644
index 4db81e232f20..000000000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenWindowCreator.java
+++ /dev/null
@@ -1,506 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.startingsurface;
-
-import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
-import static android.view.Choreographer.CALLBACK_INSETS_ANIMATION;
-import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN;
-
-import android.annotation.Nullable;
-import android.app.ActivityManager;
-import android.app.ActivityTaskManager;
-import android.app.ActivityThread;
-import android.app.TaskInfo;
-import android.content.Context;
-import android.content.pm.ActivityInfo;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.content.res.TypedArray;
-import android.graphics.Color;
-import android.graphics.PixelFormat;
-import android.hardware.display.DisplayManager;
-import android.os.IBinder;
-import android.os.RemoteCallback;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.os.Trace;
-import android.os.UserHandle;
-import android.util.Slog;
-import android.util.SparseArray;
-import android.view.Choreographer;
-import android.view.Display;
-import android.view.SurfaceControlViewHost;
-import android.view.View;
-import android.view.WindowInsetsController;
-import android.view.WindowManager;
-import android.view.WindowManagerGlobal;
-import android.widget.FrameLayout;
-import android.window.SplashScreenView;
-import android.window.StartingWindowInfo;
-import android.window.StartingWindowRemovalInfo;
-
-import com.android.internal.R;
-import com.android.internal.protolog.common.ProtoLog;
-import com.android.internal.util.ContrastColorUtil;
-import com.android.wm.shell.common.ShellExecutor;
-import com.android.wm.shell.protolog.ShellProtoLogGroup;
-
-import java.util.function.Supplier;
-
-/**
- * A class which able to draw splash screen as the starting window for a task.
- *
- * In order to speed up, there will use two threads to creating a splash screen in parallel.
- * Right now we are still using PhoneWindow to create splash screen window, so the view is added to
- * the ViewRootImpl, and those view won't be draw immediately because the ViewRootImpl will call
- * scheduleTraversal to register a callback from Choreographer, so the drawing result of the view
- * can synchronize on each frame.
- *
- * The bad thing is that we cannot decide when would Choreographer#doFrame happen, and drawing
- * the AdaptiveIconDrawable object can be time consuming, so we use the splash-screen background
- * thread to draw the AdaptiveIconDrawable object to a Bitmap and cache it to a BitmapShader after
- * the SplashScreenView just created, once we get the BitmapShader then the #draw call can be very
- * quickly.
- *
- * So basically we are using the spare time to prepare the SplashScreenView while splash screen
- * thread is waiting for
- * 1. WindowManager#addView(binder call to WM),
- * 2. Choreographer#doFrame happen(uncertain time for next frame, depends on device),
- * 3. Session#relayout(another binder call to WM which under Choreographer#doFrame, but will
- * always happen before #draw).
- * Because above steps are running on splash-screen thread, so pre-draw the BitmapShader on
- * splash-screen background tread can make they execute in parallel, which ensure it is faster then
- * to draw the AdaptiveIconDrawable when receive callback from Choreographer#doFrame.
- *
- * Here is the sequence to compare the difference between using single and two thread.
- *
- * Single thread:
- * => makeSplashScreenContentView -> WM#addView .. waiting for Choreographer#doFrame -> relayout
- * -> draw -> AdaptiveIconDrawable#draw
- *
- * Two threads:
- * => makeSplashScreenContentView -> cachePaint(=AdaptiveIconDrawable#draw)
- * => WM#addView -> .. waiting for Choreographer#doFrame -> relayout -> draw -> (draw the Paint
- * directly).
- */
-class SplashscreenWindowCreator extends AbsSplashWindowCreator {
- private static final int LIGHT_BARS_MASK =
- WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS
- | WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
-
- private final WindowManagerGlobal mWindowManagerGlobal;
- private Choreographer mChoreographer;
-
- /**
- * Records of {@link SurfaceControlViewHost} where the splash screen icon animation is
- * rendered and that have not yet been removed by their client.
- */
- private final SparseArray<SurfaceControlViewHost> mAnimatedSplashScreenSurfaceHosts =
- new SparseArray<>(1);
-
- SplashscreenWindowCreator(SplashscreenContentDrawer contentDrawer, Context context,
- ShellExecutor splashScreenExecutor, DisplayManager displayManager,
- StartingSurfaceDrawer.StartingWindowRecordManager startingWindowRecordManager) {
- super(contentDrawer, context, splashScreenExecutor, displayManager,
- startingWindowRecordManager);
- mSplashScreenExecutor.execute(() -> mChoreographer = Choreographer.getInstance());
- mWindowManagerGlobal = WindowManagerGlobal.getInstance();
- }
-
- void addSplashScreenStartingWindow(StartingWindowInfo windowInfo,
- @StartingWindowInfo.StartingWindowType int suggestType) {
- final ActivityManager.RunningTaskInfo taskInfo = windowInfo.taskInfo;
- final ActivityInfo activityInfo = windowInfo.targetActivityInfo != null
- ? windowInfo.targetActivityInfo
- : taskInfo.topActivityInfo;
- if (activityInfo == null || activityInfo.packageName == null) {
- return;
- }
- // replace with the default theme if the application didn't set
- final int theme = getSplashScreenTheme(windowInfo.splashScreenThemeResId, activityInfo);
- final Context context = SplashscreenContentDrawer.createContext(mContext, windowInfo, theme,
- suggestType, mDisplayManager);
- if (context == null) {
- return;
- }
- final WindowManager.LayoutParams params = SplashscreenContentDrawer.createLayoutParameters(
- context, windowInfo, suggestType, activityInfo.packageName,
- suggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN
- ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT, windowInfo.appToken);
-
- final int displayId = taskInfo.displayId;
- final int taskId = taskInfo.taskId;
- final Display display = getDisplay(displayId);
-
- // TODO(b/173975965) tracking performance
- // Prepare the splash screen content view on splash screen worker thread in parallel, so the
- // content view won't be blocked by binder call like addWindow and relayout.
- // 1. Trigger splash screen worker thread to create SplashScreenView before/while
- // Session#addWindow.
- // 2. Synchronize the SplashscreenView to splash screen thread before Choreographer start
- // traversal, which will call Session#relayout on splash screen thread.
- // 3. Pre-draw the BitmapShader if the icon is immobile on splash screen worker thread, at
- // the same time the splash screen thread should be executing Session#relayout. Blocking the
- // traversal -> draw on splash screen thread until the BitmapShader of the icon is ready.
-
- // Record whether create splash screen view success, notify to current thread after
- // create splash screen view finished.
- final SplashScreenViewSupplier viewSupplier = new SplashScreenViewSupplier();
- final FrameLayout rootLayout = new FrameLayout(
- mSplashscreenContentDrawer.createViewContextWrapper(context));
- rootLayout.setPadding(0, 0, 0, 0);
- rootLayout.setFitsSystemWindows(false);
- final Runnable setViewSynchronized = () -> {
- Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "addSplashScreenView");
- // waiting for setContentView before relayoutWindow
- SplashScreenView contentView = viewSupplier.get();
- final StartingSurfaceDrawer.StartingWindowRecord sRecord =
- mStartingWindowRecordManager.getRecord(taskId);
- final SplashWindowRecord record = sRecord instanceof SplashWindowRecord
- ? (SplashWindowRecord) sRecord : null;
- // If record == null, either the starting window added fail or removed already.
- // Do not add this view if the token is mismatch.
- if (record != null && windowInfo.appToken == record.mAppToken) {
- // if view == null then creation of content view was failed.
- if (contentView != null) {
- try {
- rootLayout.addView(contentView);
- } catch (RuntimeException e) {
- Slog.w(TAG, "failed set content view to starting window "
- + "at taskId: " + taskId, e);
- contentView = null;
- }
- }
- record.setSplashScreenView(contentView);
- }
- Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
- };
- requestTopUi(true);
- mSplashscreenContentDrawer.createContentView(context, suggestType, windowInfo,
- viewSupplier::setView, viewSupplier::setUiThreadInitTask);
- try {
- if (addWindow(taskId, windowInfo.appToken, rootLayout, display, params, suggestType)) {
- // We use the splash screen worker thread to create SplashScreenView while adding
- // the window, as otherwise Choreographer#doFrame might be delayed on this thread.
- // And since Choreographer#doFrame won't happen immediately after adding the window,
- // if the view is not added to the PhoneWindow on the first #doFrame, the view will
- // not be rendered on the first frame. So here we need to synchronize the view on
- // the window before first round relayoutWindow, which will happen after insets
- // animation.
- mChoreographer.postCallback(CALLBACK_INSETS_ANIMATION, setViewSynchronized, null);
- final SplashWindowRecord record =
- (SplashWindowRecord) mStartingWindowRecordManager.getRecord(taskId);
- if (record != null) {
- record.parseAppSystemBarColor(context);
- // Block until we get the background color.
- final SplashScreenView contentView = viewSupplier.get();
- if (suggestType != STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) {
- contentView.addOnAttachStateChangeListener(
- new View.OnAttachStateChangeListener() {
- @Override
- public void onViewAttachedToWindow(View v) {
- final int lightBarAppearance =
- ContrastColorUtil.isColorLight(
- contentView.getInitBackgroundColor())
- ? LIGHT_BARS_MASK : 0;
- contentView.getWindowInsetsController()
- .setSystemBarsAppearance(
- lightBarAppearance, LIGHT_BARS_MASK);
- }
-
- @Override
- public void onViewDetachedFromWindow(View v) {
- }
- });
- }
- }
- } else {
- // release the icon view host
- final SplashScreenView contentView = viewSupplier.get();
- if (contentView.getSurfaceHost() != null) {
- SplashScreenView.releaseIconHost(contentView.getSurfaceHost());
- }
- }
- } catch (RuntimeException e) {
- // don't crash if something else bad happens, for example a
- // failure loading resources because we are loading from an app
- // on external storage that has been unmounted.
- Slog.w(TAG, "failed creating starting window at taskId: " + taskId, e);
- }
- }
-
- int estimateTaskBackgroundColor(TaskInfo taskInfo) {
- if (taskInfo.topActivityInfo == null) {
- return Color.TRANSPARENT;
- }
- final ActivityInfo activityInfo = taskInfo.topActivityInfo;
- final String packageName = activityInfo.packageName;
- final int userId = taskInfo.userId;
- final Context windowContext;
- try {
- windowContext = mContext.createPackageContextAsUser(
- packageName, Context.CONTEXT_RESTRICTED, UserHandle.of(userId));
- } catch (PackageManager.NameNotFoundException e) {
- Slog.w(TAG, "Failed creating package context with package name "
- + packageName + " for user " + taskInfo.userId, e);
- return Color.TRANSPARENT;
- }
- try {
- final IPackageManager packageManager = ActivityThread.getPackageManager();
- final String splashScreenThemeName = packageManager.getSplashScreenTheme(packageName,
- userId);
- final int splashScreenThemeId = splashScreenThemeName != null
- ? windowContext.getResources().getIdentifier(splashScreenThemeName, null, null)
- : 0;
-
- final int theme = getSplashScreenTheme(splashScreenThemeId, activityInfo);
-
- if (theme != windowContext.getThemeResId()) {
- windowContext.setTheme(theme);
- }
- return mSplashscreenContentDrawer.estimateTaskBackgroundColor(windowContext);
- } catch (RuntimeException | RemoteException e) {
- Slog.w(TAG, "failed get starting window background color at taskId: "
- + taskInfo.taskId, e);
- }
- return Color.TRANSPARENT;
- }
-
- /**
- * Called when the Task wants to copy the splash screen.
- */
- public void copySplashScreenView(int taskId) {
- final StartingSurfaceDrawer.StartingWindowRecord record =
- mStartingWindowRecordManager.getRecord(taskId);
- final SplashWindowRecord preView = record instanceof SplashWindowRecord
- ? (SplashWindowRecord) record : null;
- SplashScreenView.SplashScreenViewParcelable parcelable;
- SplashScreenView splashScreenView = preView != null ? preView.mSplashView : null;
- if (splashScreenView != null && splashScreenView.isCopyable()) {
- parcelable = new SplashScreenView.SplashScreenViewParcelable(splashScreenView);
- parcelable.setClientCallback(
- new RemoteCallback((bundle) -> mSplashScreenExecutor.execute(
- () -> onAppSplashScreenViewRemoved(taskId, false))));
- splashScreenView.onCopied();
- mAnimatedSplashScreenSurfaceHosts.append(taskId, splashScreenView.getSurfaceHost());
- } else {
- parcelable = null;
- }
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
- "Copying splash screen window view for task: %d with parcelable %b",
- taskId, parcelable != null);
- ActivityTaskManager.getInstance().onSplashScreenViewCopyFinished(taskId, parcelable);
- }
-
- /**
- * Called when the {@link SplashScreenView} is removed from the client Activity view's hierarchy
- * or when the Activity is clean up.
- *
- * @param taskId The Task id on which the splash screen was attached
- */
- public void onAppSplashScreenViewRemoved(int taskId) {
- onAppSplashScreenViewRemoved(taskId, true /* fromServer */);
- }
-
- /**
- * @param fromServer If true, this means the removal was notified by the server. This is only
- * used for debugging purposes.
- * @see #onAppSplashScreenViewRemoved(int)
- */
- private void onAppSplashScreenViewRemoved(int taskId, boolean fromServer) {
- SurfaceControlViewHost viewHost =
- mAnimatedSplashScreenSurfaceHosts.get(taskId);
- if (viewHost == null) {
- return;
- }
- mAnimatedSplashScreenSurfaceHosts.remove(taskId);
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
- "%s the splash screen. Releasing SurfaceControlViewHost for task: %d",
- fromServer ? "Server cleaned up" : "App removed", taskId);
- SplashScreenView.releaseIconHost(viewHost);
- }
-
- protected boolean addWindow(int taskId, IBinder appToken, View view, Display display,
- WindowManager.LayoutParams params,
- @StartingWindowInfo.StartingWindowType int suggestType) {
- boolean shouldSaveView = true;
- final Context context = view.getContext();
- try {
- Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "addRootView");
- mWindowManagerGlobal.addView(view, params, display,
- null /* parentWindow */, context.getUserId());
- } catch (WindowManager.BadTokenException e) {
- // ignore
- Slog.w(TAG, appToken + " already running, starting window not displayed. "
- + e.getMessage());
- shouldSaveView = false;
- } finally {
- Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
- if (view.getParent() == null) {
- Slog.w(TAG, "view not successfully added to wm, removing view");
- mWindowManagerGlobal.removeView(view, true /* immediate */);
- shouldSaveView = false;
- }
- }
- if (shouldSaveView) {
- mStartingWindowRecordManager.removeWindow(taskId, true);
- saveSplashScreenRecord(appToken, taskId, view, suggestType);
- }
- return shouldSaveView;
- }
-
- private void saveSplashScreenRecord(IBinder appToken, int taskId, View view,
- @StartingWindowInfo.StartingWindowType int suggestType) {
- final SplashWindowRecord tView =
- new SplashWindowRecord(appToken, view, suggestType);
- mStartingWindowRecordManager.addRecord(taskId, tView);
- }
-
- private void removeWindowInner(View decorView, boolean hideView) {
- requestTopUi(false);
- if (hideView) {
- decorView.setVisibility(View.GONE);
- }
- mWindowManagerGlobal.removeView(decorView, false /* immediate */);
- }
-
- private static class SplashScreenViewSupplier implements Supplier<SplashScreenView> {
- private SplashScreenView mView;
- private boolean mIsViewSet;
- private Runnable mUiThreadInitTask;
- void setView(SplashScreenView view) {
- synchronized (this) {
- mView = view;
- mIsViewSet = true;
- notify();
- }
- }
-
- void setUiThreadInitTask(Runnable initTask) {
- synchronized (this) {
- mUiThreadInitTask = initTask;
- }
- }
-
- @Override
- @Nullable
- public SplashScreenView get() {
- synchronized (this) {
- while (!mIsViewSet) {
- try {
- wait();
- } catch (InterruptedException ignored) {
- }
- }
- if (mUiThreadInitTask != null) {
- mUiThreadInitTask.run();
- mUiThreadInitTask = null;
- }
- return mView;
- }
- }
- }
-
- private class SplashWindowRecord extends StartingSurfaceDrawer.StartingWindowRecord {
- private final IBinder mAppToken;
- private final View mRootView;
- @StartingWindowInfo.StartingWindowType private final int mSuggestType;
- private final long mCreateTime;
-
- private boolean mSetSplashScreen;
- private SplashScreenView mSplashView;
- private int mSystemBarAppearance;
- private boolean mDrawsSystemBarBackgrounds;
-
- SplashWindowRecord(IBinder appToken, View decorView,
- @StartingWindowInfo.StartingWindowType int suggestType) {
- mAppToken = appToken;
- mRootView = decorView;
- mSuggestType = suggestType;
- mCreateTime = SystemClock.uptimeMillis();
- }
-
- void setSplashScreenView(SplashScreenView splashScreenView) {
- if (mSetSplashScreen) {
- return;
- }
- mSplashView = splashScreenView;
- mBGColor = mSplashView.getInitBackgroundColor();
- mSetSplashScreen = true;
- }
-
- void parseAppSystemBarColor(Context context) {
- final TypedArray a = context.obtainStyledAttributes(R.styleable.Window);
- mDrawsSystemBarBackgrounds = a.getBoolean(
- R.styleable.Window_windowDrawsSystemBarBackgrounds, false);
- if (a.getBoolean(R.styleable.Window_windowLightStatusBar, false)) {
- mSystemBarAppearance |= WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
- }
- if (a.getBoolean(R.styleable.Window_windowLightNavigationBar, false)) {
- mSystemBarAppearance |= WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
- }
- a.recycle();
- }
-
- // Reset the system bar color which set by splash screen, make it align to the app.
- void clearSystemBarColor() {
- if (mRootView == null || !mRootView.isAttachedToWindow()) {
- return;
- }
- if (mRootView.getLayoutParams() instanceof WindowManager.LayoutParams) {
- final WindowManager.LayoutParams lp =
- (WindowManager.LayoutParams) mRootView.getLayoutParams();
- if (mDrawsSystemBarBackgrounds) {
- lp.flags |= WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
- } else {
- lp.flags &= ~WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
- }
- mRootView.setLayoutParams(lp);
- }
- mRootView.getWindowInsetsController().setSystemBarsAppearance(
- mSystemBarAppearance, LIGHT_BARS_MASK);
- }
-
- @Override
- public void removeIfPossible(StartingWindowRemovalInfo info, boolean immediately) {
- if (mRootView != null) {
- if (mSplashView != null) {
- clearSystemBarColor();
- if (immediately
- || mSuggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) {
- removeWindowInner(mRootView, false);
- } else {
- if (info.playRevealAnimation) {
- mSplashscreenContentDrawer.applyExitAnimation(mSplashView,
- info.windowAnimationLeash, info.mainFrame,
- () -> removeWindowInner(mRootView, true),
- mCreateTime, info.roundedCornerRadius);
- } else {
- // the SplashScreenView has been copied to client, hide the view to skip
- // default exit animation
- removeWindowInner(mRootView, true);
- }
- }
- } else {
- // shouldn't happen
- Slog.e(TAG, "Found empty splash screen, remove!");
- removeWindowInner(mRootView, false);
- }
- }
- }
- }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
index ff06db370d1a..4f07bfeacce5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
@@ -16,80 +16,169 @@
package com.android.wm.shell.startingsurface;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
+import static android.view.Choreographer.CALLBACK_INSETS_ANIMATION;
import static android.view.Display.DEFAULT_DISPLAY;
+import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN;
+import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SNAPSHOT;
-import android.annotation.CallSuper;
+import android.annotation.Nullable;
+import android.app.ActivityManager.RunningTaskInfo;
+import android.app.ActivityTaskManager;
+import android.app.ActivityThread;
import android.app.TaskInfo;
-import android.app.WindowConfiguration;
import android.content.Context;
-import android.content.res.Configuration;
+import android.content.pm.ActivityInfo;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.content.res.TypedArray;
import android.graphics.Color;
+import android.graphics.PixelFormat;
import android.hardware.display.DisplayManager;
+import android.os.IBinder;
+import android.os.RemoteCallback;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.os.Trace;
+import android.os.UserHandle;
+import android.util.Slog;
import android.util.SparseArray;
-import android.view.IWindow;
-import android.view.SurfaceControl;
-import android.view.SurfaceSession;
+import android.view.Choreographer;
+import android.view.Display;
+import android.view.SurfaceControlViewHost;
+import android.view.View;
+import android.view.WindowInsetsController;
import android.view.WindowManager;
-import android.view.WindowlessWindowManager;
+import android.view.WindowManagerGlobal;
+import android.widget.FrameLayout;
import android.window.SplashScreenView;
+import android.window.SplashScreenView.SplashScreenViewParcelable;
import android.window.StartingWindowInfo;
import android.window.StartingWindowInfo.StartingWindowType;
import android.window.StartingWindowRemovalInfo;
import android.window.TaskSnapshot;
+import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
+import com.android.internal.util.ContrastColorUtil;
import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.common.annotations.ShellSplashscreenThread;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
+import java.util.function.Supplier;
+
/**
* A class which able to draw splash screen or snapshot as the starting window for a task.
+ *
+ * In order to speed up, there will use two threads to creating a splash screen in parallel.
+ * Right now we are still using PhoneWindow to create splash screen window, so the view is added to
+ * the ViewRootImpl, and those view won't be draw immediately because the ViewRootImpl will call
+ * scheduleTraversal to register a callback from Choreographer, so the drawing result of the view
+ * can synchronize on each frame.
+ *
+ * The bad thing is that we cannot decide when would Choreographer#doFrame happen, and drawing
+ * the AdaptiveIconDrawable object can be time consuming, so we use the splash-screen background
+ * thread to draw the AdaptiveIconDrawable object to a Bitmap and cache it to a BitmapShader after
+ * the SplashScreenView just created, once we get the BitmapShader then the #draw call can be very
+ * quickly.
+ *
+ * So basically we are using the spare time to prepare the SplashScreenView while splash screen
+ * thread is waiting for
+ * 1. WindowManager#addView(binder call to WM),
+ * 2. Choreographer#doFrame happen(uncertain time for next frame, depends on device),
+ * 3. Session#relayout(another binder call to WM which under Choreographer#doFrame, but will
+ * always happen before #draw).
+ * Because above steps are running on splash-screen thread, so pre-draw the BitmapShader on
+ * splash-screen background tread can make they execute in parallel, which ensure it is faster then
+ * to draw the AdaptiveIconDrawable when receive callback from Choreographer#doFrame.
+ *
+ * Here is the sequence to compare the difference between using single and two thread.
+ *
+ * Single thread:
+ * => makeSplashScreenContentView -> WM#addView .. waiting for Choreographer#doFrame -> relayout
+ * -> draw -> AdaptiveIconDrawable#draw
+ *
+ * Two threads:
+ * => makeSplashScreenContentView -> cachePaint(=AdaptiveIconDrawable#draw)
+ * => WM#addView -> .. waiting for Choreographer#doFrame -> relayout -> draw -> (draw the Paint
+ * directly).
*/
@ShellSplashscreenThread
public class StartingSurfaceDrawer {
+ private static final String TAG = StartingWindowController.TAG;
+ private final Context mContext;
+ private final DisplayManager mDisplayManager;
private final ShellExecutor mSplashScreenExecutor;
@VisibleForTesting
final SplashscreenContentDrawer mSplashscreenContentDrawer;
- @VisibleForTesting
- final SplashscreenWindowCreator mSplashscreenWindowCreator;
- private final SnapshotWindowCreator mSnapshotWindowCreator;
- private final WindowlessSplashWindowCreator mWindowlessSplashWindowCreator;
- private final WindowlessSnapshotWindowCreator mWindowlessSnapshotWindowCreator;
+ private Choreographer mChoreographer;
+ private final WindowManagerGlobal mWindowManagerGlobal;
+ private StartingSurface.SysuiProxy mSysuiProxy;
+ private final StartingWindowRemovalInfo mTmpRemovalInfo = new StartingWindowRemovalInfo();
+
+ private static final int LIGHT_BARS_MASK =
+ WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS
+ | WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
+ /**
+ * The minimum duration during which the splash screen is shown when the splash screen icon is
+ * animated.
+ */
+ static final long MINIMAL_ANIMATION_DURATION = 400L;
+
+ /**
+ * Allow the icon style splash screen to be displayed for longer to give time for the animation
+ * to finish, i.e. the extra buffer time to keep the splash screen if the animation is slightly
+ * longer than the {@link #MINIMAL_ANIMATION_DURATION} duration.
+ */
+ static final long TIME_WINDOW_DURATION = 100L;
+
+ /**
+ * The maximum duration during which the splash screen will be shown if the application is ready
+ * to show before the icon animation finishes.
+ */
+ static final long MAX_ANIMATION_DURATION = MINIMAL_ANIMATION_DURATION + TIME_WINDOW_DURATION;
- @VisibleForTesting
- final StartingWindowRecordManager mWindowRecords = new StartingWindowRecordManager();
- // Windowless surface could co-exist with starting window in a task.
- @VisibleForTesting
- final StartingWindowRecordManager mWindowlessRecords = new StartingWindowRecordManager();
/**
* @param splashScreenExecutor The thread used to control add and remove starting window.
*/
public StartingSurfaceDrawer(Context context, ShellExecutor splashScreenExecutor,
IconProvider iconProvider, TransactionPool pool) {
+ mContext = context;
+ mDisplayManager = mContext.getSystemService(DisplayManager.class);
mSplashScreenExecutor = splashScreenExecutor;
- final DisplayManager displayManager = context.getSystemService(DisplayManager.class);
- mSplashscreenContentDrawer = new SplashscreenContentDrawer(context, iconProvider, pool);
- displayManager.getDisplay(DEFAULT_DISPLAY);
-
- mSplashscreenWindowCreator = new SplashscreenWindowCreator(mSplashscreenContentDrawer,
- context, splashScreenExecutor, displayManager, mWindowRecords);
- mSnapshotWindowCreator = new SnapshotWindowCreator(splashScreenExecutor,
- mWindowRecords);
- mWindowlessSplashWindowCreator = new WindowlessSplashWindowCreator(
- mSplashscreenContentDrawer, context, splashScreenExecutor, displayManager,
- mWindowlessRecords, pool);
- mWindowlessSnapshotWindowCreator = new WindowlessSnapshotWindowCreator(
- mWindowlessRecords, context, displayManager, mSplashscreenContentDrawer, pool);
+ mSplashscreenContentDrawer = new SplashscreenContentDrawer(mContext, iconProvider, pool);
+ mSplashScreenExecutor.execute(() -> mChoreographer = Choreographer.getInstance());
+ mWindowManagerGlobal = WindowManagerGlobal.getInstance();
+ mDisplayManager.getDisplay(DEFAULT_DISPLAY);
+ }
+
+ @VisibleForTesting
+ final SparseArray<StartingWindowRecord> mStartingWindowRecords = new SparseArray<>();
+
+ /**
+ * Records of {@link SurfaceControlViewHost} where the splash screen icon animation is
+ * rendered and that have not yet been removed by their client.
+ */
+ private final SparseArray<SurfaceControlViewHost> mAnimatedSplashScreenSurfaceHosts =
+ new SparseArray<>(1);
+
+ private Display getDisplay(int displayId) {
+ return mDisplayManager.getDisplay(displayId);
+ }
+
+ int getSplashScreenTheme(int splashScreenThemeResId, ActivityInfo activityInfo) {
+ return splashScreenThemeResId != 0
+ ? splashScreenThemeResId
+ : activityInfo.getThemeResource() != 0 ? activityInfo.getThemeResource()
+ : com.android.internal.R.style.Theme_DeviceDefault_DayNight;
}
void setSysuiProxy(StartingSurface.SysuiProxy sysuiProxy) {
- mSplashscreenWindowCreator.setSysuiProxy(sysuiProxy);
- mWindowlessSplashWindowCreator.setSysuiProxy(sysuiProxy);
+ mSysuiProxy = sysuiProxy;
}
/**
@@ -97,55 +186,231 @@ public class StartingSurfaceDrawer {
*
* @param suggestType The suggestion type to draw the splash screen.
*/
- void addSplashScreenStartingWindow(StartingWindowInfo windowInfo,
+ void addSplashScreenStartingWindow(StartingWindowInfo windowInfo, IBinder appToken,
@StartingWindowType int suggestType) {
- mSplashscreenWindowCreator.addSplashScreenStartingWindow(windowInfo, suggestType);
+ final RunningTaskInfo taskInfo = windowInfo.taskInfo;
+ final ActivityInfo activityInfo = windowInfo.targetActivityInfo != null
+ ? windowInfo.targetActivityInfo
+ : taskInfo.topActivityInfo;
+ if (activityInfo == null || activityInfo.packageName == null) {
+ return;
+ }
+ // replace with the default theme if the application didn't set
+ final int theme = getSplashScreenTheme(windowInfo.splashScreenThemeResId, activityInfo);
+ final Context context = SplashscreenContentDrawer.createContext(mContext, windowInfo, theme,
+ suggestType, mDisplayManager);
+ if (context == null) {
+ return;
+ }
+ final WindowManager.LayoutParams params = SplashscreenContentDrawer.createLayoutParameters(
+ context, windowInfo, suggestType, activityInfo.packageName,
+ suggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN
+ ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT, appToken);
+
+ final int displayId = taskInfo.displayId;
+ final int taskId = taskInfo.taskId;
+ final Display display = getDisplay(displayId);
+
+ // TODO(b/173975965) tracking performance
+ // Prepare the splash screen content view on splash screen worker thread in parallel, so the
+ // content view won't be blocked by binder call like addWindow and relayout.
+ // 1. Trigger splash screen worker thread to create SplashScreenView before/while
+ // Session#addWindow.
+ // 2. Synchronize the SplashscreenView to splash screen thread before Choreographer start
+ // traversal, which will call Session#relayout on splash screen thread.
+ // 3. Pre-draw the BitmapShader if the icon is immobile on splash screen worker thread, at
+ // the same time the splash screen thread should be executing Session#relayout. Blocking the
+ // traversal -> draw on splash screen thread until the BitmapShader of the icon is ready.
+
+ // Record whether create splash screen view success, notify to current thread after
+ // create splash screen view finished.
+ final SplashScreenViewSupplier viewSupplier = new SplashScreenViewSupplier();
+ final FrameLayout rootLayout = new FrameLayout(
+ mSplashscreenContentDrawer.createViewContextWrapper(context));
+ rootLayout.setPadding(0, 0, 0, 0);
+ rootLayout.setFitsSystemWindows(false);
+ final Runnable setViewSynchronized = () -> {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "addSplashScreenView");
+ // waiting for setContentView before relayoutWindow
+ SplashScreenView contentView = viewSupplier.get();
+ final StartingWindowRecord record = mStartingWindowRecords.get(taskId);
+ // If record == null, either the starting window added fail or removed already.
+ // Do not add this view if the token is mismatch.
+ if (record != null && appToken == record.mAppToken) {
+ // if view == null then creation of content view was failed.
+ if (contentView != null) {
+ try {
+ rootLayout.addView(contentView);
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "failed set content view to starting window "
+ + "at taskId: " + taskId, e);
+ contentView = null;
+ }
+ }
+ record.setSplashScreenView(contentView);
+ }
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+ };
+ if (mSysuiProxy != null) {
+ mSysuiProxy.requestTopUi(true, TAG);
+ }
+ mSplashscreenContentDrawer.createContentView(context, suggestType, windowInfo,
+ viewSupplier::setView, viewSupplier::setUiThreadInitTask);
+ try {
+ if (addWindow(taskId, appToken, rootLayout, display, params, suggestType)) {
+ // We use the splash screen worker thread to create SplashScreenView while adding
+ // the window, as otherwise Choreographer#doFrame might be delayed on this thread.
+ // And since Choreographer#doFrame won't happen immediately after adding the window,
+ // if the view is not added to the PhoneWindow on the first #doFrame, the view will
+ // not be rendered on the first frame. So here we need to synchronize the view on
+ // the window before first round relayoutWindow, which will happen after insets
+ // animation.
+ mChoreographer.postCallback(CALLBACK_INSETS_ANIMATION, setViewSynchronized, null);
+ final StartingWindowRecord record = mStartingWindowRecords.get(taskId);
+ record.parseAppSystemBarColor(context);
+ // Block until we get the background color.
+ final SplashScreenView contentView = viewSupplier.get();
+ if (suggestType != STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) {
+ contentView.addOnAttachStateChangeListener(
+ new View.OnAttachStateChangeListener() {
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ final int lightBarAppearance = ContrastColorUtil.isColorLight(
+ contentView.getInitBackgroundColor())
+ ? LIGHT_BARS_MASK : 0;
+ contentView.getWindowInsetsController().setSystemBarsAppearance(
+ lightBarAppearance, LIGHT_BARS_MASK);
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(View v) {
+ }
+ });
+ }
+ record.mBGColor = contentView.getInitBackgroundColor();
+ } else {
+ // release the icon view host
+ final SplashScreenView contentView = viewSupplier.get();
+ if (contentView.getSurfaceHost() != null) {
+ SplashScreenView.releaseIconHost(contentView.getSurfaceHost());
+ }
+ }
+ } catch (RuntimeException e) {
+ // don't crash if something else bad happens, for example a
+ // failure loading resources because we are loading from an app
+ // on external storage that has been unmounted.
+ Slog.w(TAG, "failed creating starting window at taskId: " + taskId, e);
+ }
}
int getStartingWindowBackgroundColorForTask(int taskId) {
- final StartingWindowRecord startingWindowRecord = mWindowRecords.getRecord(taskId);
+ final StartingWindowRecord startingWindowRecord = mStartingWindowRecords.get(taskId);
if (startingWindowRecord == null) {
return Color.TRANSPARENT;
}
- return startingWindowRecord.getBGColor();
+ return startingWindowRecord.mBGColor;
+ }
+
+ private static class SplashScreenViewSupplier implements Supplier<SplashScreenView> {
+ private SplashScreenView mView;
+ private boolean mIsViewSet;
+ private Runnable mUiThreadInitTask;
+ void setView(SplashScreenView view) {
+ synchronized (this) {
+ mView = view;
+ mIsViewSet = true;
+ notify();
+ }
+ }
+
+ void setUiThreadInitTask(Runnable initTask) {
+ synchronized (this) {
+ mUiThreadInitTask = initTask;
+ }
+ }
+
+ @Override
+ @Nullable
+ public SplashScreenView get() {
+ synchronized (this) {
+ while (!mIsViewSet) {
+ try {
+ wait();
+ } catch (InterruptedException ignored) {
+ }
+ }
+ if (mUiThreadInitTask != null) {
+ mUiThreadInitTask.run();
+ mUiThreadInitTask = null;
+ }
+ return mView;
+ }
+ }
}
int estimateTaskBackgroundColor(TaskInfo taskInfo) {
- return mSplashscreenWindowCreator.estimateTaskBackgroundColor(taskInfo);
+ if (taskInfo.topActivityInfo == null) {
+ return Color.TRANSPARENT;
+ }
+ final ActivityInfo activityInfo = taskInfo.topActivityInfo;
+ final String packageName = activityInfo.packageName;
+ final int userId = taskInfo.userId;
+ final Context windowContext;
+ try {
+ windowContext = mContext.createPackageContextAsUser(
+ packageName, Context.CONTEXT_RESTRICTED, UserHandle.of(userId));
+ } catch (PackageManager.NameNotFoundException e) {
+ Slog.w(TAG, "Failed creating package context with package name "
+ + packageName + " for user " + taskInfo.userId, e);
+ return Color.TRANSPARENT;
+ }
+ try {
+ final IPackageManager packageManager = ActivityThread.getPackageManager();
+ final String splashScreenThemeName = packageManager.getSplashScreenTheme(packageName,
+ userId);
+ final int splashScreenThemeId = splashScreenThemeName != null
+ ? windowContext.getResources().getIdentifier(splashScreenThemeName, null, null)
+ : 0;
+
+ final int theme = getSplashScreenTheme(splashScreenThemeId, activityInfo);
+
+ if (theme != windowContext.getThemeResId()) {
+ windowContext.setTheme(theme);
+ }
+ return mSplashscreenContentDrawer.estimateTaskBackgroundColor(windowContext);
+ } catch (RuntimeException | RemoteException e) {
+ Slog.w(TAG, "failed get starting window background color at taskId: "
+ + taskInfo.taskId, e);
+ }
+ return Color.TRANSPARENT;
}
/**
* Called when a task need a snapshot starting window.
*/
- void makeTaskSnapshotWindow(StartingWindowInfo startingWindowInfo, TaskSnapshot snapshot) {
- mSnapshotWindowCreator.makeTaskSnapshotWindow(startingWindowInfo, snapshot);
+ void makeTaskSnapshotWindow(StartingWindowInfo startingWindowInfo, IBinder appToken,
+ TaskSnapshot snapshot) {
+ final int taskId = startingWindowInfo.taskInfo.taskId;
+ // Remove any existing starting window for this task before adding.
+ removeWindowNoAnimate(taskId);
+ final TaskSnapshotWindow surface = TaskSnapshotWindow.create(startingWindowInfo, appToken,
+ snapshot, mSplashScreenExecutor, () -> removeWindowNoAnimate(taskId));
+ if (surface == null) {
+ return;
+ }
+ final StartingWindowRecord tView = new StartingWindowRecord(appToken,
+ null/* decorView */, surface, STARTING_WINDOW_TYPE_SNAPSHOT);
+ mStartingWindowRecords.put(taskId, tView);
}
/**
* Called when the content of a task is ready to show, starting window can be removed.
*/
public void removeStartingWindow(StartingWindowRemovalInfo removalInfo) {
- if (removalInfo.windowlessSurface) {
- mWindowlessRecords.removeWindow(removalInfo, removalInfo.removeImmediately);
- } else {
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
- "Task start finish, remove starting surface for task: %d",
- removalInfo.taskId);
- mWindowRecords.removeWindow(removalInfo, removalInfo.removeImmediately);
- }
- }
-
- /**
- * Create a windowless starting surface and attach to the root surface.
- */
- void addWindowlessStartingSurface(StartingWindowInfo windowInfo) {
- if (windowInfo.taskSnapshot != null) {
- mWindowlessSnapshotWindowCreator.makeTaskSnapshotWindow(windowInfo,
- windowInfo.rootSurface, windowInfo.taskSnapshot, mSplashScreenExecutor);
- } else {
- mWindowlessSplashWindowCreator.addSplashScreenStartingWindow(
- windowInfo, windowInfo.rootSurface);
- }
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+ "Task start finish, remove starting surface for task: %d",
+ removalInfo.taskId);
+ removeWindowSynced(removalInfo, false /* immediately */);
}
/**
@@ -154,15 +419,37 @@ public class StartingSurfaceDrawer {
public void clearAllWindows() {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
"Clear all starting windows immediately");
- mWindowRecords.clearAllWindows();
- mWindowlessRecords.clearAllWindows();
+ final int taskSize = mStartingWindowRecords.size();
+ final int[] taskIds = new int[taskSize];
+ for (int i = taskSize - 1; i >= 0; --i) {
+ taskIds[i] = mStartingWindowRecords.keyAt(i);
+ }
+ for (int i = taskSize - 1; i >= 0; --i) {
+ removeWindowNoAnimate(taskIds[i]);
+ }
}
/**
* Called when the Task wants to copy the splash screen.
*/
public void copySplashScreenView(int taskId) {
- mSplashscreenWindowCreator.copySplashScreenView(taskId);
+ final StartingWindowRecord preView = mStartingWindowRecords.get(taskId);
+ SplashScreenViewParcelable parcelable;
+ SplashScreenView splashScreenView = preView != null ? preView.mContentView : null;
+ if (splashScreenView != null && splashScreenView.isCopyable()) {
+ parcelable = new SplashScreenViewParcelable(splashScreenView);
+ parcelable.setClientCallback(
+ new RemoteCallback((bundle) -> mSplashScreenExecutor.execute(
+ () -> onAppSplashScreenViewRemoved(taskId, false))));
+ splashScreenView.onCopied();
+ mAnimatedSplashScreenSurfaceHosts.append(taskId, splashScreenView.getSurfaceHost());
+ } else {
+ parcelable = null;
+ }
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+ "Copying splash screen window view for task: %d with parcelable %b",
+ taskId, parcelable != null);
+ ActivityTaskManager.getInstance().onSplashScreenViewCopyFinished(taskId, parcelable);
}
/**
@@ -172,148 +459,195 @@ public class StartingSurfaceDrawer {
* @param taskId The Task id on which the splash screen was attached
*/
public void onAppSplashScreenViewRemoved(int taskId) {
- mSplashscreenWindowCreator.onAppSplashScreenViewRemoved(taskId);
+ onAppSplashScreenViewRemoved(taskId, true /* fromServer */);
}
- void onImeDrawnOnTask(int taskId) {
- onImeDrawnOnTask(mWindowRecords, taskId);
- onImeDrawnOnTask(mWindowlessRecords, taskId);
- }
-
- private void onImeDrawnOnTask(StartingWindowRecordManager records, int taskId) {
- final StartingSurfaceDrawer.StartingWindowRecord sRecord =
- records.getRecord(taskId);
- final SnapshotRecord record = sRecord instanceof SnapshotRecord
- ? (SnapshotRecord) sRecord : null;
- if (record != null && record.hasImeSurface()) {
- records.removeWindow(taskId, true);
+ /**
+ * @param fromServer If true, this means the removal was notified by the server. This is only
+ * used for debugging purposes.
+ * @see #onAppSplashScreenViewRemoved(int)
+ */
+ private void onAppSplashScreenViewRemoved(int taskId, boolean fromServer) {
+ SurfaceControlViewHost viewHost =
+ mAnimatedSplashScreenSurfaceHosts.get(taskId);
+ if (viewHost == null) {
+ return;
}
+ mAnimatedSplashScreenSurfaceHosts.remove(taskId);
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+ "%s the splash screen. Releasing SurfaceControlViewHost for task: %d",
+ fromServer ? "Server cleaned up" : "App removed", taskId);
+ SplashScreenView.releaseIconHost(viewHost);
}
- static class WindowlessStartingWindow extends WindowlessWindowManager {
- SurfaceControl mChildSurface;
-
- WindowlessStartingWindow(Configuration c, SurfaceControl rootSurface) {
- super(c, rootSurface, null /* hostInputToken */);
- }
-
- @Override
- protected SurfaceControl getParentSurface(IWindow window,
- WindowManager.LayoutParams attrs) {
- final SurfaceControl.Builder builder = new SurfaceControl.Builder(new SurfaceSession())
- .setContainerLayer()
- .setName("Windowless window")
- .setHidden(false)
- .setParent(mRootSurface)
- .setCallsite("WindowlessStartingWindow#attachToParentSurface");
- mChildSurface = builder.build();
- try (SurfaceControl.Transaction t = new SurfaceControl.Transaction()) {
- t.setLayer(mChildSurface, Integer.MAX_VALUE);
- t.apply();
+ protected boolean addWindow(int taskId, IBinder appToken, View view, Display display,
+ WindowManager.LayoutParams params, @StartingWindowType int suggestType) {
+ boolean shouldSaveView = true;
+ final Context context = view.getContext();
+ try {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "addRootView");
+ mWindowManagerGlobal.addView(view, params, display,
+ null /* parentWindow */, context.getUserId());
+ } catch (WindowManager.BadTokenException e) {
+ // ignore
+ Slog.w(TAG, appToken + " already running, starting window not displayed. "
+ + e.getMessage());
+ shouldSaveView = false;
+ } finally {
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+ if (view.getParent() == null) {
+ Slog.w(TAG, "view not successfully added to wm, removing view");
+ mWindowManagerGlobal.removeView(view, true /* immediate */);
+ shouldSaveView = false;
}
- return mChildSurface;
}
- }
- abstract static class StartingWindowRecord {
- protected int mBGColor;
- abstract void removeIfPossible(StartingWindowRemovalInfo info, boolean immediately);
- int getBGColor() {
- return mBGColor;
+ if (shouldSaveView) {
+ removeWindowNoAnimate(taskId);
+ saveSplashScreenRecord(appToken, taskId, view, suggestType);
}
+ return shouldSaveView;
}
- abstract static class SnapshotRecord extends StartingWindowRecord {
- private static final long DELAY_REMOVAL_TIME_GENERAL = 100;
- /**
- * The max delay time in milliseconds for removing the task snapshot window with IME
- * visible.
- * Ideally the delay time will be shorter when receiving
- * {@link StartingSurfaceDrawer#onImeDrawnOnTask(int)}.
- */
- private static final long MAX_DELAY_REMOVAL_TIME_IME_VISIBLE = 600;
- private final Runnable mScheduledRunnable = this::removeImmediately;
-
- @WindowConfiguration.ActivityType protected final int mActivityType;
- protected final ShellExecutor mRemoveExecutor;
-
- SnapshotRecord(int activityType, ShellExecutor removeExecutor) {
- mActivityType = activityType;
- mRemoveExecutor = removeExecutor;
- }
-
- @Override
- public final void removeIfPossible(StartingWindowRemovalInfo info, boolean immediately) {
- if (immediately) {
- removeImmediately();
- } else {
- scheduleRemove(info.deferRemoveForIme);
- }
- }
-
- void scheduleRemove(boolean deferRemoveForIme) {
- // Show the latest content as soon as possible for unlocking to home.
- if (mActivityType == ACTIVITY_TYPE_HOME) {
- removeImmediately();
- return;
- }
- mRemoveExecutor.removeCallbacks(mScheduledRunnable);
- final long delayRemovalTime = hasImeSurface() && deferRemoveForIme
- ? MAX_DELAY_REMOVAL_TIME_IME_VISIBLE
- : DELAY_REMOVAL_TIME_GENERAL;
- mRemoveExecutor.executeDelayed(mScheduledRunnable, delayRemovalTime);
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
- "Defer removing snapshot surface in %d", delayRemovalTime);
- }
+ @VisibleForTesting
+ void saveSplashScreenRecord(IBinder appToken, int taskId, View view,
+ @StartingWindowType int suggestType) {
+ final StartingWindowRecord tView = new StartingWindowRecord(appToken, view,
+ null/* TaskSnapshotWindow */, suggestType);
+ mStartingWindowRecords.put(taskId, tView);
+ }
- protected abstract boolean hasImeSurface();
+ private void removeWindowNoAnimate(int taskId) {
+ mTmpRemovalInfo.taskId = taskId;
+ removeWindowSynced(mTmpRemovalInfo, true /* immediately */);
+ }
- @CallSuper
- protected void removeImmediately() {
- mRemoveExecutor.removeCallbacks(mScheduledRunnable);
+ void onImeDrawnOnTask(int taskId) {
+ final StartingWindowRecord record = mStartingWindowRecords.get(taskId);
+ if (record != null && record.mTaskSnapshotWindow != null
+ && record.mTaskSnapshotWindow.hasImeSurface()) {
+ removeWindowNoAnimate(taskId);
}
}
- static class StartingWindowRecordManager {
- private final StartingWindowRemovalInfo mTmpRemovalInfo = new StartingWindowRemovalInfo();
- private final SparseArray<StartingWindowRecord> mStartingWindowRecords =
- new SparseArray<>();
+ protected void removeWindowSynced(StartingWindowRemovalInfo removalInfo, boolean immediately) {
+ final int taskId = removalInfo.taskId;
+ final StartingWindowRecord record = mStartingWindowRecords.get(taskId);
+ if (record != null) {
+ if (record.mDecorView != null) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+ "Removing splash screen window for task: %d", taskId);
+ if (record.mContentView != null) {
+ record.clearSystemBarColor();
+ if (immediately
+ || record.mSuggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) {
+ removeWindowInner(record.mDecorView, false);
+ } else {
+ if (removalInfo.playRevealAnimation) {
+ mSplashscreenContentDrawer.applyExitAnimation(record.mContentView,
+ removalInfo.windowAnimationLeash, removalInfo.mainFrame,
+ () -> removeWindowInner(record.mDecorView, true),
+ record.mCreateTime, removalInfo.roundedCornerRadius);
+ } else {
+ // the SplashScreenView has been copied to client, hide the view to skip
+ // default exit animation
+ removeWindowInner(record.mDecorView, true);
+ }
+ }
+ } else {
+ // shouldn't happen
+ Slog.e(TAG, "Found empty splash screen, remove!");
+ removeWindowInner(record.mDecorView, false);
+ }
- void clearAllWindows() {
- final int taskSize = mStartingWindowRecords.size();
- final int[] taskIds = new int[taskSize];
- for (int i = taskSize - 1; i >= 0; --i) {
- taskIds[i] = mStartingWindowRecords.keyAt(i);
}
- for (int i = taskSize - 1; i >= 0; --i) {
- removeWindow(taskIds[i], true);
+ if (record.mTaskSnapshotWindow != null) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+ "Removing task snapshot window for %d", taskId);
+ if (immediately) {
+ record.mTaskSnapshotWindow.removeImmediately();
+ } else {
+ record.mTaskSnapshotWindow.scheduleRemove(removalInfo.deferRemoveForIme);
+ }
}
+ mStartingWindowRecords.remove(taskId);
}
+ }
- void addRecord(int taskId, StartingWindowRecord record) {
- mStartingWindowRecords.put(taskId, record);
+ private void removeWindowInner(View decorView, boolean hideView) {
+ if (mSysuiProxy != null) {
+ mSysuiProxy.requestTopUi(false, TAG);
+ }
+ if (hideView) {
+ decorView.setVisibility(View.GONE);
}
+ mWindowManagerGlobal.removeView(decorView, false /* immediate */);
+ }
- void removeWindow(StartingWindowRemovalInfo removeInfo, boolean immediately) {
- final int taskId = removeInfo.taskId;
- final StartingWindowRecord record = mStartingWindowRecords.get(taskId);
- if (record != null) {
- record.removeIfPossible(removeInfo, immediately);
- mStartingWindowRecords.remove(taskId);
+ /**
+ * Record the view or surface for a starting window.
+ */
+ private static class StartingWindowRecord {
+ private final IBinder mAppToken;
+ private final View mDecorView;
+ private final TaskSnapshotWindow mTaskSnapshotWindow;
+ private SplashScreenView mContentView;
+ private boolean mSetSplashScreen;
+ @StartingWindowType private int mSuggestType;
+ private int mBGColor;
+ private final long mCreateTime;
+ private int mSystemBarAppearance;
+ private boolean mDrawsSystemBarBackgrounds;
+
+ StartingWindowRecord(IBinder appToken, View decorView,
+ TaskSnapshotWindow taskSnapshotWindow, @StartingWindowType int suggestType) {
+ mAppToken = appToken;
+ mDecorView = decorView;
+ mTaskSnapshotWindow = taskSnapshotWindow;
+ if (mTaskSnapshotWindow != null) {
+ mBGColor = mTaskSnapshotWindow.getBackgroundColor();
}
+ mSuggestType = suggestType;
+ mCreateTime = SystemClock.uptimeMillis();
}
- void removeWindow(int taskId, boolean immediately) {
- mTmpRemovalInfo.taskId = taskId;
- removeWindow(mTmpRemovalInfo, immediately);
+ private void setSplashScreenView(SplashScreenView splashScreenView) {
+ if (mSetSplashScreen) {
+ return;
+ }
+ mContentView = splashScreenView;
+ mSetSplashScreen = true;
}
- StartingWindowRecord getRecord(int taskId) {
- return mStartingWindowRecords.get(taskId);
+ private void parseAppSystemBarColor(Context context) {
+ final TypedArray a = context.obtainStyledAttributes(R.styleable.Window);
+ mDrawsSystemBarBackgrounds = a.getBoolean(
+ R.styleable.Window_windowDrawsSystemBarBackgrounds, false);
+ if (a.getBoolean(R.styleable.Window_windowLightStatusBar, false)) {
+ mSystemBarAppearance |= WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
+ }
+ if (a.getBoolean(R.styleable.Window_windowLightNavigationBar, false)) {
+ mSystemBarAppearance |= WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
+ }
+ a.recycle();
}
- @VisibleForTesting
- int recordSize() {
- return mStartingWindowRecords.size();
+ // Reset the system bar color which set by splash screen, make it align to the app.
+ private void clearSystemBarColor() {
+ if (mDecorView == null || !mDecorView.isAttachedToWindow()) {
+ return;
+ }
+ if (mDecorView.getLayoutParams() instanceof WindowManager.LayoutParams) {
+ final WindowManager.LayoutParams lp =
+ (WindowManager.LayoutParams) mDecorView.getLayoutParams();
+ if (mDrawsSystemBarBackgrounds) {
+ lp.flags |= WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+ } else {
+ lp.flags &= ~WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+ }
+ mDecorView.setLayoutParams(lp);
+ }
+ mDecorView.getWindowInsetsController().setSystemBarsAppearance(
+ mSystemBarAppearance, LIGHT_BARS_MASK);
}
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
index bec4ba3bf0d1..be2e79342d07 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
@@ -21,7 +21,6 @@ import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_NONE;
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SNAPSHOT;
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SOLID_COLOR_SPLASH_SCREEN;
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
-import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_WINDOWLESS;
import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_STARTING_WINDOW;
@@ -30,6 +29,7 @@ import android.app.ActivityManager.RunningTaskInfo;
import android.app.TaskInfo;
import android.content.Context;
import android.graphics.Color;
+import android.os.IBinder;
import android.os.Trace;
import android.util.SparseIntArray;
import android.window.StartingWindowInfo;
@@ -152,23 +152,22 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo
/**
* Called when a task need a starting window.
*/
- public void addStartingWindow(StartingWindowInfo windowInfo) {
+ public void addStartingWindow(StartingWindowInfo windowInfo, IBinder appToken) {
mSplashScreenExecutor.execute(() -> {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "addStartingWindow");
final int suggestionType = mStartingWindowTypeAlgorithm.getSuggestedWindowType(
windowInfo);
final RunningTaskInfo runningTaskInfo = windowInfo.taskInfo;
- if (suggestionType == STARTING_WINDOW_TYPE_WINDOWLESS) {
- mStartingSurfaceDrawer.addWindowlessStartingSurface(windowInfo);
- } else if (isSplashScreenType(suggestionType)) {
- mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, suggestionType);
+ if (isSplashScreenType(suggestionType)) {
+ mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, appToken,
+ suggestionType);
} else if (suggestionType == STARTING_WINDOW_TYPE_SNAPSHOT) {
final TaskSnapshot snapshot = windowInfo.taskSnapshot;
- mStartingSurfaceDrawer.makeTaskSnapshotWindow(windowInfo, snapshot);
+ mStartingSurfaceDrawer.makeTaskSnapshotWindow(windowInfo, appToken,
+ snapshot);
}
- if (suggestionType != STARTING_WINDOW_TYPE_NONE
- && suggestionType != STARTING_WINDOW_TYPE_WINDOWLESS) {
+ if (suggestionType != STARTING_WINDOW_TYPE_NONE) {
int taskId = runningTaskInfo.taskId;
int color = mStartingSurfaceDrawer
.getStartingWindowBackgroundColorForTask(taskId);
@@ -219,13 +218,11 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo
public void removeStartingWindow(StartingWindowRemovalInfo removalInfo) {
mSplashScreenExecutor.execute(() -> mStartingSurfaceDrawer.removeStartingWindow(
removalInfo));
- if (!removalInfo.windowlessSurface) {
- mSplashScreenExecutor.executeDelayed(() -> {
- synchronized (mTaskBackgroundColors) {
- mTaskBackgroundColors.delete(removalInfo.taskId);
- }
- }, TASK_BG_COLOR_RETAIN_TIME_MS);
- }
+ mSplashScreenExecutor.executeDelayed(() -> {
+ synchronized (mTaskBackgroundColors) {
+ mTaskBackgroundColors.delete(removalInfo.taskId);
+ }
+ }, TASK_BG_COLOR_RETAIN_TIME_MS);
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
index c964df1452e0..a05ed4f24a08 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
@@ -16,6 +16,7 @@
package com.android.wm.shell.startingsurface;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.graphics.Color.WHITE;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
@@ -62,14 +63,24 @@ public class TaskSnapshotWindow {
private static final String TAG = StartingWindowController.TAG;
private static final String TITLE_FORMAT = "SnapshotStartingWindow for taskId=";
+ private static final long DELAY_REMOVAL_TIME_GENERAL = 100;
+ /**
+ * The max delay time in milliseconds for removing the task snapshot window with IME visible.
+ * Ideally the delay time will be shorter when receiving
+ * {@link StartingSurfaceDrawer#onImeDrawnOnTask(int)}.
+ */
+ private static final long MAX_DELAY_REMOVAL_TIME_IME_VISIBLE = 600;
+
private final Window mWindow;
private final Runnable mClearWindowHandler;
private final ShellExecutor mSplashScreenExecutor;
private final IWindowSession mSession;
private boolean mHasDrawn;
private final Paint mBackgroundPaint = new Paint();
+ private final int mActivityType;
private final int mOrientationOnCreation;
+ private final Runnable mScheduledRunnable = this::removeImmediately;
private final boolean mHasImeSurface;
static TaskSnapshotWindow create(StartingWindowInfo info, IBinder appToken,
@@ -93,6 +104,7 @@ public class TaskSnapshotWindow {
final Point taskSize = snapshot.getTaskSize();
final Rect taskBounds = new Rect(0, 0, taskSize.x, taskSize.y);
final int orientation = snapshot.getOrientation();
+ final int activityType = runningTaskInfo.topActivityType;
final int displayId = runningTaskInfo.displayId;
final IWindowSession session = WindowManagerGlobal.getWindowSession();
@@ -102,11 +114,16 @@ public class TaskSnapshotWindow {
final InsetsSourceControl.Array tmpControls = new InsetsSourceControl.Array();
final MergedConfiguration tmpMergedConfiguration = new MergedConfiguration();
- final TaskDescription taskDescription =
- SnapshotDrawerUtils.getOrCreateTaskDescription(runningTaskInfo);
+ final TaskDescription taskDescription;
+ if (runningTaskInfo.taskDescription != null) {
+ taskDescription = runningTaskInfo.taskDescription;
+ } else {
+ taskDescription = new TaskDescription();
+ taskDescription.setBackgroundColor(WHITE);
+ }
final TaskSnapshotWindow snapshotSurface = new TaskSnapshotWindow(
- snapshot, taskDescription, orientation,
+ snapshot, taskDescription, orientation, activityType,
clearWindowHandler, splashScreenExecutor);
final Window window = snapshotSurface.mWindow;
@@ -136,8 +153,6 @@ public class TaskSnapshotWindow {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
} catch (RemoteException e) {
snapshotSurface.clearWindowSynced();
- Slog.w(TAG, "Failed to relayout snapshot starting window");
- return null;
}
SnapshotDrawerUtils.drawSnapshotOnSurface(info, layoutParams, surfaceControl, snapshot,
@@ -149,7 +164,7 @@ public class TaskSnapshotWindow {
}
public TaskSnapshotWindow(TaskSnapshot snapshot, TaskDescription taskDescription,
- int currentOrientation, Runnable clearWindowHandler,
+ int currentOrientation, int activityType, Runnable clearWindowHandler,
ShellExecutor splashScreenExecutor) {
mSplashScreenExecutor = splashScreenExecutor;
mSession = WindowManagerGlobal.getWindowSession();
@@ -158,6 +173,7 @@ public class TaskSnapshotWindow {
int backgroundColor = taskDescription.getBackgroundColor();
mBackgroundPaint.setColor(backgroundColor != 0 ? backgroundColor : WHITE);
mOrientationOnCreation = currentOrientation;
+ mActivityType = activityType;
mClearWindowHandler = clearWindowHandler;
mHasImeSurface = snapshot.hasImeSurface();
}
@@ -170,7 +186,23 @@ public class TaskSnapshotWindow {
return mHasImeSurface;
}
+ void scheduleRemove(boolean deferRemoveForIme) {
+ // Show the latest content as soon as possible for unlocking to home.
+ if (mActivityType == ACTIVITY_TYPE_HOME) {
+ removeImmediately();
+ return;
+ }
+ mSplashScreenExecutor.removeCallbacks(mScheduledRunnable);
+ final long delayRemovalTime = mHasImeSurface && deferRemoveForIme
+ ? MAX_DELAY_REMOVAL_TIME_IME_VISIBLE
+ : DELAY_REMOVAL_TIME_GENERAL;
+ mSplashScreenExecutor.executeDelayed(mScheduledRunnable, delayRemovalTime);
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+ "Defer removing snapshot surface in %d", delayRemovalTime);
+ }
+
void removeImmediately() {
+ mSplashScreenExecutor.removeCallbacks(mScheduledRunnable);
try {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
"Removing taskSnapshot surface, mHasDrawn=%b", mHasDrawn);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java
deleted file mode 100644
index 144547885501..000000000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.startingsurface;
-
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
-import android.app.ActivityManager;
-import android.content.Context;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.hardware.display.DisplayManager;
-import android.view.Display;
-import android.view.InsetsState;
-import android.view.SurfaceControl;
-import android.view.SurfaceControlViewHost;
-import android.view.WindowManager;
-import android.widget.FrameLayout;
-import android.window.SnapshotDrawerUtils;
-import android.window.StartingWindowInfo;
-import android.window.TaskSnapshot;
-
-import com.android.wm.shell.common.ShellExecutor;
-import com.android.wm.shell.common.TransactionPool;
-
-class WindowlessSnapshotWindowCreator {
- private static final int DEFAULT_FADEOUT_DURATION = 233;
- private final StartingSurfaceDrawer.StartingWindowRecordManager
- mStartingWindowRecordManager;
- private final DisplayManager mDisplayManager;
- private final Context mContext;
- private final SplashscreenContentDrawer mSplashscreenContentDrawer;
- private final TransactionPool mTransactionPool;
-
- WindowlessSnapshotWindowCreator(
- StartingSurfaceDrawer.StartingWindowRecordManager startingWindowRecordManager,
- Context context,
- DisplayManager displayManager, SplashscreenContentDrawer splashscreenContentDrawer,
- TransactionPool transactionPool) {
- mStartingWindowRecordManager = startingWindowRecordManager;
- mContext = context;
- mDisplayManager = displayManager;
- mSplashscreenContentDrawer = splashscreenContentDrawer;
- mTransactionPool = transactionPool;
- }
-
- void makeTaskSnapshotWindow(StartingWindowInfo info, SurfaceControl rootSurface,
- TaskSnapshot snapshot, ShellExecutor removeExecutor) {
- final ActivityManager.RunningTaskInfo runningTaskInfo = info.taskInfo;
- final int taskId = runningTaskInfo.taskId;
- final String title = "Windowless Snapshot " + taskId;
- final WindowManager.LayoutParams lp = SnapshotDrawerUtils.createLayoutParameters(
- info, title, TYPE_APPLICATION_OVERLAY, snapshot.getHardwareBuffer().getFormat(),
- null /* token */);
- if (lp == null) {
- return;
- }
- final Display display = mDisplayManager.getDisplay(runningTaskInfo.displayId);
- final StartingSurfaceDrawer.WindowlessStartingWindow wlw =
- new StartingSurfaceDrawer.WindowlessStartingWindow(
- runningTaskInfo.configuration, rootSurface);
- final SurfaceControlViewHost mViewHost = new SurfaceControlViewHost(
- mContext, display, wlw, "WindowlessSnapshotWindowCreator");
- final Point taskSize = snapshot.getTaskSize();
- final Rect snapshotBounds = new Rect(0, 0, taskSize.x, taskSize.y);
- final Rect windowBounds = runningTaskInfo.configuration.windowConfiguration.getBounds();
- final InsetsState topWindowInsetsState = info.topOpaqueWindowInsetsState;
- final FrameLayout rootLayout = new FrameLayout(
- mSplashscreenContentDrawer.createViewContextWrapper(mContext));
- mViewHost.setView(rootLayout, lp);
- SnapshotDrawerUtils.drawSnapshotOnSurface(info, lp, wlw.mChildSurface, snapshot,
- snapshotBounds, windowBounds, topWindowInsetsState, false /* releaseAfterDraw */);
-
- final ActivityManager.TaskDescription taskDescription =
- SnapshotDrawerUtils.getOrCreateTaskDescription(runningTaskInfo);
-
- final SnapshotWindowRecord record = new SnapshotWindowRecord(mViewHost, wlw.mChildSurface,
- taskDescription.getBackgroundColor(), snapshot.hasImeSurface(),
- runningTaskInfo.topActivityType, removeExecutor);
- mStartingWindowRecordManager.addRecord(taskId, record);
- info.notifyAddComplete(wlw.mChildSurface);
- }
-
- private class SnapshotWindowRecord extends StartingSurfaceDrawer.SnapshotRecord {
- private SurfaceControlViewHost mViewHost;
- private SurfaceControl mChildSurface;
- private final boolean mHasImeSurface;
-
- SnapshotWindowRecord(SurfaceControlViewHost viewHost, SurfaceControl childSurface,
- int bgColor, boolean hasImeSurface, int activityType,
- ShellExecutor removeExecutor) {
- super(activityType, removeExecutor);
- mViewHost = viewHost;
- mChildSurface = childSurface;
- mBGColor = bgColor;
- mHasImeSurface = hasImeSurface;
- }
-
- @Override
- protected void removeImmediately() {
- super.removeImmediately();
- fadeoutThenRelease();
- }
-
- void fadeoutThenRelease() {
- final ValueAnimator fadeOutAnimator = ValueAnimator.ofFloat(1f, 0f);
- fadeOutAnimator.setDuration(DEFAULT_FADEOUT_DURATION);
- final SurfaceControl.Transaction t = mTransactionPool.acquire();
- fadeOutAnimator.addUpdateListener(animation -> {
- if (mChildSurface == null || !mChildSurface.isValid()) {
- fadeOutAnimator.cancel();
- return;
- }
- t.setAlpha(mChildSurface, (float) animation.getAnimatedValue());
- t.apply();
- });
-
- fadeOutAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation) {
- if (mChildSurface == null || !mChildSurface.isValid()) {
- fadeOutAnimator.cancel();
- }
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- mTransactionPool.release(t);
- if (mChildSurface != null) {
- final SurfaceControl.Transaction t = mTransactionPool.acquire();
- t.remove(mChildSurface).apply();
- mTransactionPool.release(t);
- mChildSurface = null;
- }
- if (mViewHost != null) {
- mViewHost.release();
- mViewHost = null;
- }
- }
- });
- fadeOutAnimator.start();
- }
-
- @Override
- protected boolean hasImeSurface() {
- return mHasImeSurface;
- }
- }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSplashWindowCreator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSplashWindowCreator.java
deleted file mode 100644
index 12a0d4054b4d..000000000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSplashWindowCreator.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.startingsurface;
-
-import static android.graphics.Color.WHITE;
-import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
-
-import android.app.ActivityManager;
-import android.content.Context;
-import android.content.pm.ActivityInfo;
-import android.graphics.PixelFormat;
-import android.graphics.Rect;
-import android.hardware.display.DisplayManager;
-import android.os.Binder;
-import android.os.SystemClock;
-import android.view.Display;
-import android.view.SurfaceControl;
-import android.view.SurfaceControlViewHost;
-import android.view.WindowManager;
-import android.widget.FrameLayout;
-import android.window.SplashScreenView;
-import android.window.StartingWindowInfo;
-import android.window.StartingWindowRemovalInfo;
-
-import com.android.wm.shell.common.ShellExecutor;
-import com.android.wm.shell.common.TransactionPool;
-
-class WindowlessSplashWindowCreator extends AbsSplashWindowCreator {
-
- private final TransactionPool mTransactionPool;
-
- WindowlessSplashWindowCreator(SplashscreenContentDrawer contentDrawer,
- Context context,
- ShellExecutor splashScreenExecutor,
- DisplayManager displayManager,
- StartingSurfaceDrawer.StartingWindowRecordManager startingWindowRecordManager,
- TransactionPool pool) {
- super(contentDrawer, context, splashScreenExecutor, displayManager,
- startingWindowRecordManager);
- mTransactionPool = pool;
- }
-
- void addSplashScreenStartingWindow(StartingWindowInfo windowInfo, SurfaceControl rootSurface) {
- final ActivityManager.RunningTaskInfo taskInfo = windowInfo.taskInfo;
- final ActivityInfo activityInfo = windowInfo.targetActivityInfo != null
- ? windowInfo.targetActivityInfo
- : taskInfo.topActivityInfo;
- if (activityInfo == null || activityInfo.packageName == null) {
- return;
- }
-
- final int displayId = taskInfo.displayId;
- final Display display = mDisplayManager.getDisplay(displayId);
- if (display == null) {
- // Can't show splash screen on requested display, so skip showing at all.
- return;
- }
- final Context myContext = SplashscreenContentDrawer.createContext(mContext, windowInfo,
- 0 /* theme */, STARTING_WINDOW_TYPE_SPLASH_SCREEN, mDisplayManager);
- if (myContext == null) {
- return;
- }
- final StartingSurfaceDrawer.WindowlessStartingWindow wlw =
- new StartingSurfaceDrawer.WindowlessStartingWindow(
- taskInfo.configuration, rootSurface);
- final SurfaceControlViewHost viewHost = new SurfaceControlViewHost(
- myContext, display, wlw, "WindowlessSplashWindowCreator");
- final String title = "Windowless Splash " + taskInfo.taskId;
- final WindowManager.LayoutParams lp = SplashscreenContentDrawer.createLayoutParameters(
- myContext, windowInfo, STARTING_WINDOW_TYPE_SPLASH_SCREEN, title,
- PixelFormat.TRANSLUCENT, new Binder());
- final Rect windowBounds = taskInfo.configuration.windowConfiguration.getBounds();
- lp.width = windowBounds.width();
- lp.height = windowBounds.height();
- final ActivityManager.TaskDescription taskDescription;
- if (taskInfo.taskDescription != null) {
- taskDescription = taskInfo.taskDescription;
- } else {
- taskDescription = new ActivityManager.TaskDescription();
- taskDescription.setBackgroundColor(WHITE);
- }
-
- final FrameLayout rootLayout = new FrameLayout(
- mSplashscreenContentDrawer.createViewContextWrapper(mContext));
- viewHost.setView(rootLayout, lp);
-
- final int bgColor = taskDescription.getBackgroundColor();
- final SplashScreenView splashScreenView = mSplashscreenContentDrawer
- .makeSimpleSplashScreenContentView(myContext, windowInfo, bgColor);
- rootLayout.addView(splashScreenView);
- final SplashWindowRecord record = new SplashWindowRecord(viewHost, splashScreenView,
- wlw.mChildSurface, bgColor);
- mStartingWindowRecordManager.addRecord(taskInfo.taskId, record);
- windowInfo.notifyAddComplete(wlw.mChildSurface);
- }
-
- private class SplashWindowRecord extends StartingSurfaceDrawer.StartingWindowRecord {
- private SurfaceControlViewHost mViewHost;
- private final long mCreateTime;
- private SurfaceControl mChildSurface;
- private final SplashScreenView mSplashView;
-
- SplashWindowRecord(SurfaceControlViewHost viewHost, SplashScreenView splashView,
- SurfaceControl childSurface, int bgColor) {
- mViewHost = viewHost;
- mSplashView = splashView;
- mChildSurface = childSurface;
- mBGColor = bgColor;
- mCreateTime = SystemClock.uptimeMillis();
- }
-
- @Override
- public void removeIfPossible(StartingWindowRemovalInfo info, boolean immediately) {
- if (!immediately) {
- mSplashscreenContentDrawer.applyExitAnimation(mSplashView,
- info.windowAnimationLeash, info.mainFrame,
- this::release, mCreateTime, 0 /* roundedCornerRadius */);
- } else {
- release();
- }
- }
-
- void release() {
- if (mChildSurface != null) {
- final SurfaceControl.Transaction t = mTransactionPool.acquire();
- t.remove(mChildSurface).apply();
- mTransactionPool.release(t);
- mChildSurface = null;
- }
- if (mViewHost != null) {
- mViewHost.release();
- mViewHost = null;
- }
- }
- }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/phone/PhoneStartingWindowTypeAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/phone/PhoneStartingWindowTypeAlgorithm.java
index 72fc8686f648..bb43d7c1a090 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/phone/PhoneStartingWindowTypeAlgorithm.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/phone/PhoneStartingWindowTypeAlgorithm.java
@@ -22,7 +22,6 @@ import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_NONE;
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SNAPSHOT;
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SOLID_COLOR_SPLASH_SCREEN;
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
-import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_WINDOWLESS;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_CREATED;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_DRAWN;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT;
@@ -31,7 +30,6 @@ import static android.window.StartingWindowInfo.TYPE_PARAMETER_NEW_TASK;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_PROCESS_RUNNING;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_TASK_SWITCH;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_USE_SOLID_COLOR_SPLASH_SCREEN;
-import static android.window.StartingWindowInfo.TYPE_PARAMETER_WINDOWLESS;
import android.window.StartingWindowInfo;
@@ -57,7 +55,6 @@ public class PhoneStartingWindowTypeAlgorithm implements StartingWindowTypeAlgor
final boolean legacySplashScreen =
((parameter & TYPE_PARAMETER_LEGACY_SPLASH_SCREEN) != 0);
final boolean activityDrawn = (parameter & TYPE_PARAMETER_ACTIVITY_DRAWN) != 0;
- final boolean windowlessSurface = (parameter & TYPE_PARAMETER_WINDOWLESS) != 0;
final boolean topIsHome = windowInfo.taskInfo.topActivityType == ACTIVITY_TYPE_HOME;
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
@@ -70,15 +67,10 @@ public class PhoneStartingWindowTypeAlgorithm implements StartingWindowTypeAlgor
+ "isSolidColorSplashScreen=%b, "
+ "legacySplashScreen=%b, "
+ "activityDrawn=%b, "
- + "windowless=%b, "
+ "topIsHome=%b",
newTask, taskSwitch, processRunning, allowTaskSnapshot, activityCreated,
- isSolidColorSplashScreen, legacySplashScreen, activityDrawn, windowlessSurface,
- topIsHome);
+ isSolidColorSplashScreen, legacySplashScreen, activityDrawn, topIsHome);
- if (windowlessSurface) {
- return STARTING_WINDOW_TYPE_WINDOWLESS;
- }
if (!topIsHome) {
if (!processRunning || newTask || (taskSwitch && !activityCreated)) {
return getSplashscreenType(isSolidColorSplashScreen, legacySplashScreen);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInit.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInit.java
index ac52235375c4..2e2f569a52b8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInit.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInit.java
@@ -21,6 +21,7 @@ import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_INIT;
import android.os.Build;
import android.os.SystemClock;
import android.util.Pair;
+import android.view.SurfaceControl;
import androidx.annotation.VisibleForTesting;
@@ -75,6 +76,7 @@ public class ShellInit {
@VisibleForTesting
public void init() {
ProtoLog.v(WM_SHELL_INIT, "Initializing Shell Components: %d", mInitCallbacks.size());
+ SurfaceControl.setDebugUsageAfterRelease(true);
// Init in order of registration
for (int i = 0; i < mInitCallbacks.size(); i++) {
final Pair<String, Runnable> info = mInitCallbacks.get(i);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/CounterRotatorHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/CounterRotatorHelper.java
index 19133e29de4b..628ce27fe514 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/CounterRotatorHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/CounterRotatorHelper.java
@@ -28,6 +28,7 @@ import android.window.WindowContainerToken;
import androidx.annotation.NonNull;
import com.android.wm.shell.util.CounterRotator;
+import com.android.wm.shell.util.TransitionUtil;
import java.util.List;
@@ -57,7 +58,7 @@ public class CounterRotatorHelper {
for (int i = numChanges - 1; i >= 0; --i) {
final TransitionInfo.Change change = changes.get(i);
final WindowContainerToken parent = change.getParent();
- if (!Transitions.isClosingType(change.getMode())
+ if (!TransitionUtil.isClosingType(change.getMode())
|| !TransitionInfo.isIndependent(change, info) || parent == null) {
continue;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
index 8e916e63cac6..75112b62c1c6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
@@ -44,6 +44,7 @@ import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.splitscreen.SplitScreenController;
import com.android.wm.shell.splitscreen.StageCoordinator;
import com.android.wm.shell.sysui.ShellInit;
+import com.android.wm.shell.util.TransitionUtil;
import java.util.ArrayList;
import java.util.Optional;
@@ -77,7 +78,6 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler {
int mAnimType = 0;
final IBinder mTransition;
- Transitions.TransitionFinishCallback mFinishCallback = null;
Transitions.TransitionHandler mLeftoversHandler = null;
WindowContainerTransaction mFinishWCT = null;
@@ -149,7 +149,7 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler {
mSplitHandler.addEnterOrExitIfNeeded(request, out);
return out;
} else if (request.getRemoteTransition() != null
- && Transitions.isOpeningType(request.getType())
+ && TransitionUtil.isOpeningType(request.getType())
&& (request.getTriggerTask() == null
|| (request.getTriggerTask().topActivityType != ACTIVITY_TYPE_HOME
&& request.getTriggerTask().topActivityType != ACTIVITY_TYPE_RECENTS))) {
@@ -240,20 +240,25 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler {
}
if (pipChange == null) {
if (mixed.mLeftoversHandler != null) {
- return mixed.mLeftoversHandler.startAnimation(mixed.mTransition, info,
- startTransaction, finishTransaction, finishCallback);
+ if (mixed.mLeftoversHandler.startAnimation(mixed.mTransition,
+ info, startTransaction, finishTransaction, (wct, wctCB) -> {
+ mActiveTransitions.remove(mixed);
+ finishCallback.onTransitionFinished(wct, wctCB);
+ })) {
+ return true;
+ }
}
+ mActiveTransitions.remove(mixed);
return false;
}
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Splitting PIP into a separate"
+ " animation because remote-animation likely doesn't support it");
- mixed.mFinishCallback = finishCallback;
Transitions.TransitionFinishCallback finishCB = (wct, wctCB) -> {
--mixed.mInFlightSubAnimations;
mixed.joinFinishArgs(wct, wctCB);
if (mixed.mInFlightSubAnimations > 0) return;
mActiveTransitions.remove(mixed);
- mixed.mFinishCallback.onTransitionFinished(mixed.mFinishWCT, wctCB);
+ finishCallback.onTransitionFinished(mixed.mFinishWCT, wctCB);
};
// Split the transition into 2 parts: the pip part and the rest.
mixed.mInFlightSubAnimations = 2;
@@ -303,10 +308,10 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler {
}
if (pipChange == null) {
// um, something probably went wrong.
+ mActiveTransitions.remove(mixed);
return false;
}
final boolean isGoingHome = homeIsOpening;
- mixed.mFinishCallback = finishCallback;
Transitions.TransitionFinishCallback finishCB = (wct, wctCB) -> {
--mixed.mInFlightSubAnimations;
mixed.joinFinishArgs(wct, wctCB);
@@ -315,7 +320,7 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler {
if (isGoingHome) {
mSplitHandler.onTransitionAnimationComplete();
}
- mixed.mFinishCallback.onTransitionFinished(mixed.mFinishWCT, wctCB);
+ finishCallback.onTransitionFinished(mixed.mFinishWCT, wctCB);
};
if (isGoingHome) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Animation is actually mixed "
@@ -407,7 +412,6 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler {
unlinkMissingParents(everythingElse);
final MixedTransition mixed = new MixedTransition(
MixedTransition.TYPE_DISPLAY_AND_SPLIT_CHANGE, transition);
- mixed.mFinishCallback = finishCallback;
mActiveTransitions.add(mixed);
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Animation is a mix of display change "
+ "and split change.");
@@ -419,7 +423,7 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler {
mixed.joinFinishArgs(wct, wctCB);
if (mixed.mInFlightSubAnimations > 0) return;
mActiveTransitions.remove(mixed);
- mixed.mFinishCallback.onTransitionFinished(mixed.mFinishWCT, null /* wctCB */);
+ finishCallback.onTransitionFinished(mixed.mFinishWCT, null /* wctCB */);
};
// Dispatch the display change. This will most-likely be taken by the default handler.
@@ -446,7 +450,9 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler {
// Already done, so no need to end it.
return;
}
- if (mixed.mType == MixedTransition.TYPE_ENTER_PIP_FROM_SPLIT) {
+ if (mixed.mType == MixedTransition.TYPE_DISPLAY_AND_SPLIT_CHANGE) {
+ // queue since no actual animation.
+ } else if (mixed.mType == MixedTransition.TYPE_ENTER_PIP_FROM_SPLIT) {
if (mixed.mAnimType == MixedTransition.ANIM_TYPE_GOING_HOME) {
boolean ended = mSplitHandler.end();
// If split couldn't end (because it is remote), then don't end everything else
@@ -460,8 +466,12 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler {
} else {
mPipHandler.end();
}
- } else if (mixed.mType == MixedTransition.TYPE_DISPLAY_AND_SPLIT_CHANGE) {
- // queue
+ } else if (mixed.mType == MixedTransition.TYPE_OPTIONS_REMOTE_AND_PIP_CHANGE) {
+ mPipHandler.end();
+ if (mixed.mLeftoversHandler != null) {
+ mixed.mLeftoversHandler.mergeAnimation(transition, info, t, mergeTarget,
+ finishCallback);
+ }
} else {
throw new IllegalStateException("Playing a mixed transition with unknown type? "
+ mixed.mType);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
index a3e05f2cf859..f66c26bb87e4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
@@ -112,6 +112,7 @@ import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.sysui.ShellInit;
+import com.android.wm.shell.util.TransitionUtil;
import java.util.ArrayList;
import java.util.List;
@@ -445,7 +446,7 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
backgroundColorForTransition);
if (!isTask && a.hasExtension()) {
- if (!Transitions.isOpeningType(change.getMode())) {
+ if (!TransitionUtil.isOpeningType(change.getMode())) {
// Can screenshot now (before startTransaction is applied)
edgeExtendWindow(change, a, startTransaction, finishTransaction);
} else {
@@ -456,7 +457,7 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
}
}
- final Rect clipRect = Transitions.isClosingType(change.getMode())
+ final Rect clipRect = TransitionUtil.isClosingType(change.getMode())
? new Rect(mRotator.getEndBoundsInStartRotation(change))
: new Rect(change.getEndAbsBounds());
clipRect.offsetTo(0, 0);
@@ -562,12 +563,12 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
final int flags = info.getFlags();
final int changeMode = change.getMode();
final int changeFlags = change.getFlags();
- final boolean isOpeningType = Transitions.isOpeningType(type);
- final boolean enter = Transitions.isOpeningType(changeMode);
+ final boolean isOpeningType = TransitionUtil.isOpeningType(type);
+ final boolean enter = TransitionUtil.isOpeningType(changeMode);
final boolean isTask = change.getTaskInfo() != null;
final TransitionInfo.AnimationOptions options = info.getAnimationOptions();
final int overrideType = options != null ? options.getType() : ANIM_NONE;
- final Rect endBounds = Transitions.isClosingType(changeMode)
+ final Rect endBounds = TransitionUtil.isClosingType(changeMode)
? mRotator.getEndBoundsInStartRotation(change)
: change.getEndAbsBounds();
@@ -689,8 +690,8 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
private void attachThumbnail(@NonNull ArrayList<Animator> animations,
@NonNull Runnable finishCallback, TransitionInfo.Change change,
TransitionInfo.AnimationOptions options, float cornerRadius) {
- final boolean isOpen = Transitions.isOpeningType(change.getMode());
- final boolean isClose = Transitions.isClosingType(change.getMode());
+ final boolean isOpen = TransitionUtil.isOpeningType(change.getMode());
+ final boolean isClose = TransitionUtil.isClosingType(change.getMode());
if (isOpen) {
if (options.getType() == ANIM_OPEN_CROSS_PROFILE_APPS) {
attachCrossProfileThumbnailAnimation(animations, finishCallback, change,
@@ -772,16 +773,16 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
final TransitionInfo.Change change = info.getChanges().get(i);
if ((change.getFlags() & FLAG_SHOW_WALLPAPER) != 0) {
- if (Transitions.isOpeningType(change.getMode())) {
+ if (TransitionUtil.isOpeningType(change.getMode())) {
hasOpenWallpaper = true;
- } else if (Transitions.isClosingType(change.getMode())) {
+ } else if (TransitionUtil.isClosingType(change.getMode())) {
hasCloseWallpaper = true;
}
}
}
if (hasOpenWallpaper && hasCloseWallpaper) {
- return Transitions.isOpeningType(info.getType())
+ return TransitionUtil.isOpeningType(info.getType())
? WALLPAPER_TRANSITION_INTRA_OPEN : WALLPAPER_TRANSITION_INTRA_CLOSE;
} else if (hasOpenWallpaper) {
return WALLPAPER_TRANSITION_OPEN;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
index 02f19ebdb758..3c4e8898f215 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
@@ -39,6 +39,7 @@ import androidx.annotation.BinderThread;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
+import com.android.wm.shell.util.TransitionUtil;
import java.util.ArrayList;
@@ -93,7 +94,7 @@ public class RemoteTransitionHandler implements Transitions.TransitionHandler {
@NonNull SurfaceControl.Transaction startTransaction,
@NonNull SurfaceControl.Transaction finishTransaction,
@NonNull Transitions.TransitionFinishCallback finishCallback) {
- if (!Transitions.SHELL_TRANSITIONS_ROTATION && Transitions.hasDisplayChange(info)) {
+ if (!Transitions.SHELL_TRANSITIONS_ROTATION && TransitionUtil.hasDisplayChange(info)) {
// Note that if the remote doesn't have permission ACCESS_SURFACE_FLINGER, some
// operations of the start transaction may be ignored.
return false;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/SleepHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/SleepHandler.java
new file mode 100644
index 000000000000..0386ec38a3ff
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/SleepHandler.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.transition;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.IBinder;
+import android.util.Log;
+import android.view.SurfaceControl;
+import android.window.TransitionInfo;
+import android.window.TransitionRequestInfo;
+import android.window.WindowContainerTransaction;
+
+import java.util.ArrayList;
+
+/**
+ * A Simple handler that tracks SLEEP transitions. We track them specially since we (ab)use these
+ * as sentinels for fast-forwarding through animations when the screen is off.
+ *
+ * There should only be one SleepHandler and it is used explicitly by {@link Transitions} so we
+ * don't register it like a normal handler.
+ */
+class SleepHandler implements Transitions.TransitionHandler {
+ final ArrayList<IBinder> mSleepTransitions = new ArrayList<>();
+
+ @Override
+ public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
+ @NonNull SurfaceControl.Transaction startTransaction,
+ @NonNull SurfaceControl.Transaction finishTransaction,
+ @NonNull Transitions.TransitionFinishCallback finishCallback) {
+ startTransaction.apply();
+ finishCallback.onTransitionFinished(null, null);
+ mSleepTransitions.remove(transition);
+ return true;
+ }
+
+ @Override
+ @Nullable
+ public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
+ @NonNull TransitionRequestInfo request) {
+ mSleepTransitions.add(transition);
+ return new WindowContainerTransaction();
+ }
+
+ @Override
+ public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted,
+ @Nullable SurfaceControl.Transaction finishTransaction) {
+ Log.e(Transitions.TAG, "Sleep transition was consumed. This doesn't make sense");
+ mSleepTransitions.remove(transition);
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java
index 5a5ceab383e7..bcc37baa5b00 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java
@@ -54,6 +54,7 @@ import com.android.internal.R;
import com.android.internal.policy.TransitionAnimation;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
+import com.android.wm.shell.util.TransitionUtil;
/** The helper class that provides methods for adding styles to transition animations. */
public class TransitionAnimationHelper {
@@ -66,7 +67,7 @@ public class TransitionAnimationHelper {
final int type = info.getType();
final int changeMode = change.getMode();
final int changeFlags = change.getFlags();
- final boolean enter = Transitions.isOpeningType(changeMode);
+ final boolean enter = TransitionUtil.isOpeningType(changeMode);
final boolean isTask = change.getTaskInfo() != null;
final TransitionInfo.AnimationOptions options = info.getAnimationOptions();
final int overrideType = options != null ? options.getType() : ANIM_NONE;
@@ -142,8 +143,12 @@ public class TransitionAnimationHelper {
Animation a = null;
if (animAttr != 0) {
if (overrideType == ANIM_FROM_STYLE && !isTask) {
- a = loadCustomActivityTransition(animAttr, options, enter, transitionAnimation);
- if (a == null) {
+ final TransitionInfo.AnimationOptions.CustomActivityTransition customTransition =
+ getCustomActivityTransition(animAttr, options);
+ if (customTransition != null) {
+ a = loadCustomActivityTransition(
+ customTransition, options, enter, transitionAnimation);
+ } else {
a = transitionAnimation
.loadAnimationAttr(options.getPackageName(), options.getAnimations(),
animAttr, translucent);
@@ -160,10 +165,8 @@ public class TransitionAnimationHelper {
return a;
}
- static Animation loadCustomActivityTransition(int animAttr,
- TransitionInfo.AnimationOptions options, boolean enter,
- TransitionAnimation transitionAnimation) {
- Animation a = null;
+ static TransitionInfo.AnimationOptions.CustomActivityTransition getCustomActivityTransition(
+ int animAttr, TransitionInfo.AnimationOptions options) {
boolean isOpen = false;
switch (animAttr) {
case R.styleable.WindowAnimation_activityOpenEnterAnimation:
@@ -177,17 +180,19 @@ public class TransitionAnimationHelper {
return null;
}
- final TransitionInfo.AnimationOptions.CustomActivityTransition transitionAnim =
- options.getCustomActivityTransition(isOpen);
- if (transitionAnim != null) {
- a = transitionAnimation.loadAppTransitionAnimation(options.getPackageName(),
- enter ? transitionAnim.getCustomEnterResId()
- : transitionAnim.getCustomExitResId());
- if (a != null && transitionAnim.getCustomBackgroundColor() != 0) {
- a.setBackdropColor(transitionAnim.getCustomBackgroundColor());
- }
- }
+ return options.getCustomActivityTransition(isOpen);
+ }
+ static Animation loadCustomActivityTransition(
+ @NonNull TransitionInfo.AnimationOptions.CustomActivityTransition transitionAnim,
+ TransitionInfo.AnimationOptions options, boolean enter,
+ TransitionAnimation transitionAnimation) {
+ final Animation a = transitionAnimation.loadAppTransitionAnimation(options.getPackageName(),
+ enter ? transitionAnim.getCustomEnterResId()
+ : transitionAnim.getCustomExitResId());
+ if (a != null && transitionAnim.getCustomBackgroundColor() != 0) {
+ a.setBackdropColor(transitionAnim.getCustomBackgroundColor());
+ }
return a;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index 0a67477212e9..155990a40836 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -19,13 +19,12 @@ package com.android.wm.shell.transition;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_FIRST_CUSTOM;
-import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
import static android.view.WindowManager.TRANSIT_OPEN;
+import static android.view.WindowManager.TRANSIT_SLEEP;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.view.WindowManager.fixScale;
-import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
import static android.window.TransitionInfo.FLAG_IS_OCCLUDED;
import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
import static android.window.TransitionInfo.FLAG_NO_ANIMATION;
@@ -33,6 +32,8 @@ import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPI
import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_SHELL_TRANSITIONS;
+import static com.android.wm.shell.util.TransitionUtil.isClosingType;
+import static com.android.wm.shell.util.TransitionUtil.isOpeningType;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -124,6 +125,7 @@ public class Transitions implements RemoteCallable<Transitions> {
private final DisplayController mDisplayController;
private final ShellController mShellController;
private final ShellTransitionImpl mImpl = new ShellTransitionImpl();
+ private final SleepHandler mSleepHandler = new SleepHandler();
private boolean mIsRegistered = false;
@@ -137,6 +139,14 @@ public class Transitions implements RemoteCallable<Transitions> {
private float mTransitionAnimationScaleSetting = 1.0f;
+ /**
+ * How much time we allow for an animation to finish itself on sleep. If it takes longer, we
+ * will force-finish it (on this end) which may leave it in a bad state but won't hang the
+ * device. This needs to be pretty small because it is an allowance for each queued animation,
+ * however it can't be too small since there is some potential IPC involved.
+ */
+ private static final int SLEEP_ALLOWANCE_MS = 120;
+
private static final class ActiveTransition {
IBinder mToken;
TransitionHandler mHandler;
@@ -319,29 +329,6 @@ public class Transitions implements RemoteCallable<Transitions> {
}
}
- /** @return true if the transition was triggered by opening something vs closing something */
- public static boolean isOpeningType(@WindowManager.TransitionType int type) {
- return type == TRANSIT_OPEN
- || type == TRANSIT_TO_FRONT
- || type == TRANSIT_KEYGUARD_GOING_AWAY;
- }
-
- /** @return true if the transition was triggered by closing something vs opening something */
- public static boolean isClosingType(@WindowManager.TransitionType int type) {
- return type == TRANSIT_CLOSE || type == TRANSIT_TO_BACK;
- }
-
- /** Returns {@code true} if the transition has a display change. */
- public static boolean hasDisplayChange(@NonNull TransitionInfo info) {
- for (int i = info.getChanges().size() - 1; i >= 0; --i) {
- final TransitionInfo.Change change = info.getChanges().get(i);
- if (change.getMode() == TRANSIT_CHANGE && change.hasFlags(FLAG_IS_DISPLAY)) {
- return true;
- }
- }
- return false;
- }
-
/**
* Sets up visibility/alpha/transforms to resemble the starting state of an animation.
*/
@@ -501,11 +488,29 @@ public class Transitions implements RemoteCallable<Transitions> {
+ Arrays.toString(mActiveTransitions.stream().map(
activeTransition -> activeTransition.mToken).toArray()));
}
+ final ActiveTransition active = mActiveTransitions.get(activeIdx);
for (int i = 0; i < mObservers.size(); ++i) {
mObservers.get(i).onTransitionReady(transitionToken, info, t, finishT);
}
+ if (info.getType() == TRANSIT_SLEEP) {
+ if (activeIdx > 0) {
+ active.mInfo = info;
+ active.mStartT = t;
+ active.mFinishT = finishT;
+ if (!info.getRootLeash().isValid()) {
+ // Shell has some debug settings which makes calling binders with invalid
+ // surfaces crash, so replace it with a "real" one.
+ info.setRootLeash(new SurfaceControl.Builder().setName("Invalid")
+ .setContainerLayer().build(), 0, 0);
+ }
+ // Sleep starts a process of forcing all prior transitions to finish immediately
+ finishForSleep(null /* forceFinish */);
+ return;
+ }
+ }
+
// Allow to notify keyguard un-occluding state to KeyguardService, which can happen while
// screen-off, so there might no visibility change involved.
if (!info.getRootLeash().isValid() && info.getType() != TRANSIT_KEYGUARD_UNOCCLUDE) {
@@ -550,7 +555,6 @@ public class Transitions implements RemoteCallable<Transitions> {
return;
}
- final ActiveTransition active = mActiveTransitions.get(activeIdx);
active.mInfo = info;
active.mStartT = t;
active.mFinishT = finishT;
@@ -795,6 +799,12 @@ public class Transitions implements RemoteCallable<Transitions> {
++mergeIdx;
continue;
}
+ if (mergeCandidate.mInfo == null) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition merge candidate"
+ + " %s is not ready yet", mergeCandidate.mToken);
+ // The later transition should not be merged if the prior one is not ready.
+ return;
+ }
if (mergeCandidate.mMerged) {
throw new IllegalStateException("Can't merge a transition after not-merging"
+ " a preceding one.");
@@ -820,23 +830,30 @@ public class Transitions implements RemoteCallable<Transitions> {
}
final ActiveTransition active = new ActiveTransition();
WindowContainerTransaction wct = null;
- for (int i = mHandlers.size() - 1; i >= 0; --i) {
- wct = mHandlers.get(i).handleRequest(transitionToken, request);
- if (wct != null) {
- active.mHandler = mHandlers.get(i);
- break;
+
+ // If we have sleep, we use a special handler and we try to finish everything ASAP.
+ if (request.getType() == TRANSIT_SLEEP) {
+ mSleepHandler.handleRequest(transitionToken, request);
+ active.mHandler = mSleepHandler;
+ } else {
+ for (int i = mHandlers.size() - 1; i >= 0; --i) {
+ wct = mHandlers.get(i).handleRequest(transitionToken, request);
+ if (wct != null) {
+ active.mHandler = mHandlers.get(i);
+ break;
+ }
}
- }
- if (request.getDisplayChange() != null) {
- TransitionRequestInfo.DisplayChange change = request.getDisplayChange();
- if (change.getEndRotation() != change.getStartRotation()) {
- // Is a rotation, so dispatch to all displayChange listeners
- if (wct == null) {
- wct = new WindowContainerTransaction();
+ if (request.getDisplayChange() != null) {
+ TransitionRequestInfo.DisplayChange change = request.getDisplayChange();
+ if (change.getEndRotation() != change.getStartRotation()) {
+ // Is a rotation, so dispatch to all displayChange listeners
+ if (wct == null) {
+ wct = new WindowContainerTransaction();
+ }
+ mDisplayController.getChangeController().dispatchOnDisplayChange(wct,
+ change.getDisplayId(), change.getStartRotation(),
+ change.getEndRotation(), null /* newDisplayAreaInfo */);
}
- mDisplayController.getChangeController().dispatchOnDisplayChange(wct,
- change.getDisplayId(), change.getStartRotation(), change.getEndRotation(),
- null /* newDisplayAreaInfo */);
}
}
mOrganizer.startTransition(transitionToken, wct != null && wct.isEmpty() ? null : wct);
@@ -863,6 +880,56 @@ public class Transitions implements RemoteCallable<Transitions> {
}
/**
+ * Finish running animations (almost) immediately when a SLEEP transition comes in. We use this
+ * as both a way to reduce unnecessary work (animations not visible while screen off) and as a
+ * failsafe to unblock "stuck" animations (in particular remote animations).
+ *
+ * This works by "merging" the sleep transition into the currently-playing transition (even if
+ * its out-of-order) -- turning SLEEP into a signal. If the playing transition doesn't finish
+ * within `SLEEP_ALLOWANCE_MS` from this merge attempt, this will then finish it directly (and
+ * send an abort/consumed message).
+ *
+ * This is then repeated until there are no more pending sleep transitions.
+ *
+ * @param forceFinish When non-null, this is the transition that we last sent the SLEEP merge
+ * signal to -- so it will be force-finished if it's still running.
+ */
+ private void finishForSleep(@Nullable IBinder forceFinish) {
+ if (mActiveTransitions.isEmpty() || mSleepHandler.mSleepTransitions.isEmpty()) {
+ return;
+ }
+ if (forceFinish != null && mActiveTransitions.get(0).mToken == forceFinish) {
+ Log.e(TAG, "Forcing transition to finish due to sleep timeout: "
+ + mActiveTransitions.get(0).mToken);
+ onFinish(mActiveTransitions.get(0).mToken, null, null, true);
+ }
+ final SurfaceControl.Transaction dummyT = new SurfaceControl.Transaction();
+ while (!mActiveTransitions.isEmpty() && !mSleepHandler.mSleepTransitions.isEmpty()) {
+ final ActiveTransition playing = mActiveTransitions.get(0);
+ int sleepIdx = findActiveTransition(mSleepHandler.mSleepTransitions.get(0));
+ if (sleepIdx >= 0) {
+ // Try to signal that we are sleeping by attempting to merge the sleep transition
+ // into the playing one.
+ final ActiveTransition nextSleep = mActiveTransitions.get(sleepIdx);
+ playing.mHandler.mergeAnimation(nextSleep.mToken, nextSleep.mInfo, dummyT,
+ playing.mToken, (wct, cb) -> {});
+ } else {
+ Log.e(TAG, "Couldn't find sleep transition in active list: "
+ + mSleepHandler.mSleepTransitions.get(0));
+ }
+ // it's possible to complete immediately. If that happens, just repeat the signal
+ // loop until we either finish everything or start playing an animation that isn't
+ // finishing immediately.
+ if (!mActiveTransitions.isEmpty() && mActiveTransitions.get(0) == playing) {
+ // Give it a (very) short amount of time to process it before forcing.
+ mMainExecutor.executeDelayed(
+ () -> finishForSleep(playing.mToken), SLEEP_ALLOWANCE_MS);
+ break;
+ }
+ }
+ }
+
+ /**
* Interface for a callback that must be called after a TransitionHandler finishes playing an
* animation.
*/
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/FullscreenUnfoldTaskAnimator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/FullscreenUnfoldTaskAnimator.java
index 06a8438a3a25..f81fc6fbea49 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/FullscreenUnfoldTaskAnimator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/FullscreenUnfoldTaskAnimator.java
@@ -35,6 +35,7 @@ import android.view.InsetsSource;
import android.view.InsetsState;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
+import android.view.WindowInsets;
import com.android.internal.policy.ScreenDecorationsUtils;
import com.android.wm.shell.common.DisplayInsetsController;
@@ -66,13 +67,12 @@ public class FullscreenUnfoldTaskAnimator implements UnfoldTaskAnimator,
private static final float START_SCALE = END_SCALE - VERTICAL_START_MARGIN * 2;
private final SparseArray<AnimationContext> mAnimationContextByTaskId = new SparseArray<>();
- private final int mExpandedTaskBarHeight;
private final DisplayInsetsController mDisplayInsetsController;
private final UnfoldBackgroundController mBackgroundController;
private final Context mContext;
private final ShellController mShellController;
- private InsetsSource mTaskbarInsetsSource;
+ private InsetsSource mExpandedTaskbarInsetsSource;
private float mWindowCornerRadiusPx;
public FullscreenUnfoldTaskAnimator(Context context,
@@ -82,8 +82,6 @@ public class FullscreenUnfoldTaskAnimator implements UnfoldTaskAnimator,
mDisplayInsetsController = displayInsetsController;
mBackgroundController = backgroundController;
mShellController = shellController;
- mExpandedTaskBarHeight = context.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.taskbar_frame_height);
mWindowCornerRadiusPx = ScreenDecorationsUtils.getWindowCornerRadius(context);
}
@@ -101,21 +99,32 @@ public class FullscreenUnfoldTaskAnimator implements UnfoldTaskAnimator,
@Override
public void insetsChanged(InsetsState insetsState) {
- mTaskbarInsetsSource = insetsState.peekSource(InsetsState.ITYPE_EXTRA_NAVIGATION_BAR);
+ mExpandedTaskbarInsetsSource = getExpandedTaskbarSource(insetsState);
for (int i = mAnimationContextByTaskId.size() - 1; i >= 0; i--) {
AnimationContext context = mAnimationContextByTaskId.valueAt(i);
- context.update(mTaskbarInsetsSource, context.mTaskInfo);
+ context.update(mExpandedTaskbarInsetsSource, context.mTaskInfo);
}
}
+ private static InsetsSource getExpandedTaskbarSource(InsetsState state) {
+ for (int i = state.sourceSize() - 1; i >= 0; i--) {
+ final InsetsSource source = state.sourceAt(i);
+ if (source.getType() == WindowInsets.Type.navigationBars()
+ && source.insetsRoundedCornerFrame()) {
+ return source;
+ }
+ }
+ return null;
+ }
+
public boolean hasActiveTasks() {
return mAnimationContextByTaskId.size() > 0;
}
@Override
public void onTaskAppeared(TaskInfo taskInfo, SurfaceControl leash) {
- AnimationContext animationContext = new AnimationContext(leash, mTaskbarInsetsSource,
- taskInfo);
+ AnimationContext animationContext = new AnimationContext(
+ leash, mExpandedTaskbarInsetsSource, taskInfo);
mAnimationContextByTaskId.put(taskInfo.taskId, animationContext);
}
@@ -123,7 +132,7 @@ public class FullscreenUnfoldTaskAnimator implements UnfoldTaskAnimator,
public void onTaskChanged(TaskInfo taskInfo) {
AnimationContext animationContext = mAnimationContextByTaskId.get(taskInfo.taskId);
if (animationContext != null) {
- animationContext.update(mTaskbarInsetsSource, taskInfo);
+ animationContext.update(mExpandedTaskbarInsetsSource, taskInfo);
}
}
@@ -222,11 +231,7 @@ public class FullscreenUnfoldTaskAnimator implements UnfoldTaskAnimator,
mStartCropRect.set(mTaskInfo.getConfiguration().windowConfiguration.getBounds());
if (taskBarInsetsSource != null) {
- // Only insets the cropping window with task bar when it's expanded
- if (taskBarInsetsSource.getFrame().height() >= mExpandedTaskBarHeight) {
- mStartCropRect.inset(taskBarInsetsSource
- .calculateVisibleInsets(mStartCropRect));
- }
+ mStartCropRect.inset(taskBarInsetsSource.calculateVisibleInsets(mStartCropRect));
}
mEndCropRect.set(mStartCropRect);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/SplitTaskUnfoldAnimator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/SplitTaskUnfoldAnimator.java
index f835c7bbd810..2f0c96487d68 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/SplitTaskUnfoldAnimator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/SplitTaskUnfoldAnimator.java
@@ -37,6 +37,7 @@ import android.view.InsetsSource;
import android.view.InsetsState;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
+import android.view.WindowInsets;
import com.android.internal.policy.ScreenDecorationsUtils;
import com.android.wm.shell.common.DisplayInsetsController;
@@ -76,7 +77,6 @@ public class SplitTaskUnfoldAnimator implements UnfoldTaskAnimator,
private final Executor mExecutor;
private final DisplayInsetsController mDisplayInsetsController;
private final SparseArray<AnimationContext> mAnimationContextByTaskId = new SparseArray<>();
- private final int mExpandedTaskBarHeight;
private final ShellController mShellController;
private final Lazy<Optional<SplitScreenController>> mSplitScreenController;
private final UnfoldBackgroundController mUnfoldBackgroundController;
@@ -86,7 +86,7 @@ public class SplitTaskUnfoldAnimator implements UnfoldTaskAnimator,
private final Rect mRootStageBounds = new Rect();
private float mWindowCornerRadiusPx;
- private InsetsSource mTaskbarInsetsSource;
+ private InsetsSource mExpandedTaskbarInsetsSource;
@SplitPosition
private int mMainStagePosition = SPLIT_POSITION_UNDEFINED;
@@ -103,8 +103,6 @@ public class SplitTaskUnfoldAnimator implements UnfoldTaskAnimator,
mShellController = shellController;
mUnfoldBackgroundController = unfoldBackgroundController;
mSplitScreenController = splitScreenController;
- mExpandedTaskBarHeight = context.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.taskbar_frame_height);
mWindowCornerRadiusPx = ScreenDecorationsUtils.getWindowCornerRadius(context);
}
@@ -143,10 +141,21 @@ public class SplitTaskUnfoldAnimator implements UnfoldTaskAnimator,
@Override
public void insetsChanged(InsetsState insetsState) {
- mTaskbarInsetsSource = insetsState.peekSource(InsetsState.ITYPE_EXTRA_NAVIGATION_BAR);
+ mExpandedTaskbarInsetsSource = getExpandedTaskbarSource(insetsState);
updateContexts();
}
+ private static InsetsSource getExpandedTaskbarSource(InsetsState state) {
+ for (int i = state.sourceSize() - 1; i >= 0; i--) {
+ final InsetsSource source = state.sourceAt(i);
+ if (source.getType() == WindowInsets.Type.navigationBars()
+ && source.insetsRoundedCornerFrame()) {
+ return source;
+ }
+ }
+ return null;
+ }
+
@Override
public void onTaskStageChanged(int taskId, int stage, boolean visible) {
final AnimationContext context = mAnimationContextByTaskId.get(taskId);
@@ -307,7 +316,8 @@ public class SplitTaskUnfoldAnimator implements UnfoldTaskAnimator,
boolean taskbarExpanded = isTaskbarExpanded();
if (taskbarExpanded) {
// Only insets the cropping window with taskbar when taskbar is expanded
- mStartCropRect.inset(mTaskbarInsetsSource.calculateVisibleInsets(mStartCropRect));
+ mStartCropRect.inset(mExpandedTaskbarInsetsSource.calculateVisibleInsets(
+ mStartCropRect));
}
// Offset to surface coordinates as layout bounds are in screen coordinates
@@ -360,8 +370,7 @@ public class SplitTaskUnfoldAnimator implements UnfoldTaskAnimator,
}
private boolean isTaskbarExpanded() {
- return mTaskbarInsetsSource != null
- && mTaskbarInsetsSource.getFrame().height() >= mExpandedTaskBarHeight;
+ return mExpandedTaskbarInsetsSource != null;
}
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java b/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java
new file mode 100644
index 000000000000..8c6e1e7f5f1b
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.util;
+
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+import static android.view.RemoteAnimationTarget.MODE_CHANGING;
+import static android.view.RemoteAnimationTarget.MODE_CLOSING;
+import static android.view.RemoteAnimationTarget.MODE_OPENING;
+import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
+import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
+import static android.view.WindowManager.TRANSIT_CHANGE;
+import static android.view.WindowManager.TRANSIT_CLOSE;
+import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
+import static android.view.WindowManager.TRANSIT_OPEN;
+import static android.view.WindowManager.TRANSIT_TO_BACK;
+import static android.view.WindowManager.TRANSIT_TO_FRONT;
+import static android.window.TransitionInfo.FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY;
+import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
+import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
+import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
+
+import static com.android.wm.shell.common.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.app.ActivityManager;
+import android.app.WindowConfiguration;
+import android.graphics.Rect;
+import android.util.ArrayMap;
+import android.util.SparseBooleanArray;
+import android.view.RemoteAnimationTarget;
+import android.view.SurfaceControl;
+import android.view.WindowManager;
+import android.window.TransitionInfo;
+
+import java.util.function.Predicate;
+
+/** Various utility functions for transitions. */
+public class TransitionUtil {
+
+ /** @return true if the transition was triggered by opening something vs closing something */
+ public static boolean isOpeningType(@WindowManager.TransitionType int type) {
+ return type == TRANSIT_OPEN
+ || type == TRANSIT_TO_FRONT
+ || type == TRANSIT_KEYGUARD_GOING_AWAY;
+ }
+
+ /** @return true if the transition was triggered by closing something vs opening something */
+ public static boolean isClosingType(@WindowManager.TransitionType int type) {
+ return type == TRANSIT_CLOSE || type == TRANSIT_TO_BACK;
+ }
+
+ /** Returns {@code true} if the transition has a display change. */
+ public static boolean hasDisplayChange(@NonNull TransitionInfo info) {
+ for (int i = info.getChanges().size() - 1; i >= 0; --i) {
+ final TransitionInfo.Change change = info.getChanges().get(i);
+ if (change.getMode() == TRANSIT_CHANGE && change.hasFlags(FLAG_IS_DISPLAY)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /** Returns `true` if `change` is a wallpaper. */
+ public static boolean isWallpaper(TransitionInfo.Change change) {
+ return (change.getTaskInfo() == null)
+ && change.hasFlags(FLAG_IS_WALLPAPER)
+ && !change.hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY);
+ }
+
+ /** Returns `true` if `change` is not an app window or wallpaper. */
+ public static boolean isNonApp(TransitionInfo.Change change) {
+ return (change.getTaskInfo() == null)
+ && !change.hasFlags(FLAG_IS_WALLPAPER)
+ && !change.hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY);
+ }
+
+ /**
+ * Filter that selects leaf-tasks only. THIS IS ORDER-DEPENDENT! For it to work properly, you
+ * MUST call `test` in the same order that the changes appear in the TransitionInfo.
+ */
+ public static class LeafTaskFilter implements Predicate<TransitionInfo.Change> {
+ private final SparseBooleanArray mChildTaskTargets = new SparseBooleanArray();
+
+ @Override
+ public boolean test(TransitionInfo.Change change) {
+ final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
+ // Children always come before parent since changes are in top-to-bottom z-order.
+ if ((taskInfo == null) || mChildTaskTargets.get(taskInfo.taskId)) {
+ // has children, so not a leaf. Skip.
+ return false;
+ }
+ if (taskInfo.hasParentTask()) {
+ mChildTaskTargets.put(taskInfo.parentTaskId, true);
+ }
+ return true;
+ }
+ }
+
+
+ private static int newModeToLegacyMode(int newMode) {
+ switch (newMode) {
+ case WindowManager.TRANSIT_OPEN:
+ case WindowManager.TRANSIT_TO_FRONT:
+ return MODE_OPENING;
+ case WindowManager.TRANSIT_CLOSE:
+ case WindowManager.TRANSIT_TO_BACK:
+ return MODE_CLOSING;
+ default:
+ return MODE_CHANGING;
+ }
+ }
+
+ /**
+ * Very similar to Transitions#setupAnimHierarchy but specialized for leashes.
+ */
+ @SuppressLint("NewApi")
+ private static void setupLeash(@NonNull SurfaceControl leash,
+ @NonNull TransitionInfo.Change change, int layer,
+ @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t) {
+ final boolean isOpening = TransitionUtil.isOpeningType(info.getType());
+ // Put animating stuff above this line and put static stuff below it.
+ int zSplitLine = info.getChanges().size();
+ // changes should be ordered top-to-bottom in z
+ final int mode = change.getMode();
+
+ t.reparent(leash, info.getRootLeash());
+ final Rect absBounds =
+ (mode == TRANSIT_OPEN) ? change.getEndAbsBounds() : change.getStartAbsBounds();
+ t.setPosition(leash, absBounds.left - info.getRootOffset().x,
+ absBounds.top - info.getRootOffset().y);
+
+ // Put all the OPEN/SHOW on top
+ if (TransitionUtil.isOpeningType(mode)) {
+ if (isOpening) {
+ t.setLayer(leash, zSplitLine + info.getChanges().size() - layer);
+ if ((change.getFlags() & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) == 0) {
+ // if transferred, it should be left visible.
+ t.setAlpha(leash, 0.f);
+ }
+ } else {
+ // put on bottom and leave it visible
+ t.setLayer(leash, zSplitLine - layer);
+ }
+ } else if (TransitionUtil.isClosingType(mode)) {
+ if (isOpening) {
+ // put on bottom and leave visible
+ t.setLayer(leash, zSplitLine - layer);
+ } else {
+ // put on top
+ t.setLayer(leash, zSplitLine + info.getChanges().size() - layer);
+ }
+ } else { // CHANGE
+ t.setLayer(leash, zSplitLine + info.getChanges().size() - layer);
+ }
+ }
+
+ @SuppressLint("NewApi")
+ private static SurfaceControl createLeash(TransitionInfo info, TransitionInfo.Change change,
+ int order, SurfaceControl.Transaction t) {
+ // TODO: once we can properly sync transactions across process, then get rid of this leash.
+ if (change.getParent() != null && (change.getFlags() & FLAG_IS_WALLPAPER) != 0) {
+ // Special case for wallpaper atm. Normally these are left alone; but, a quirk of
+ // making leashes means we have to handle them specially.
+ return change.getLeash();
+ }
+ SurfaceControl leashSurface = new SurfaceControl.Builder()
+ .setName(change.getLeash().toString() + "_transition-leash")
+ .setContainerLayer()
+ // Initial the surface visible to respect the visibility of the original surface.
+ .setHidden(false)
+ .setParent(info.getRootLeash())
+ .build();
+ // Copied Transitions setup code (which expects bottom-to-top order, so we swap here)
+ setupLeash(leashSurface, change, info.getChanges().size() - order, info, t);
+ t.reparent(change.getLeash(), leashSurface);
+ t.setAlpha(change.getLeash(), 1.0f);
+ t.show(change.getLeash());
+ t.setPosition(change.getLeash(), 0, 0);
+ t.setLayer(change.getLeash(), 0);
+ return leashSurface;
+ }
+
+ /**
+ * Creates a new RemoteAnimationTarget from the provided change info
+ */
+ public static RemoteAnimationTarget newTarget(TransitionInfo.Change change, int order,
+ TransitionInfo info, SurfaceControl.Transaction t,
+ @Nullable ArrayMap<SurfaceControl, SurfaceControl> leashMap) {
+ final SurfaceControl leash = createLeash(info, change, order, t);
+ if (leashMap != null) {
+ leashMap.put(change.getLeash(), leash);
+ }
+ return newTarget(change, order, leash);
+ }
+
+ /**
+ * Creates a new RemoteAnimationTarget from the provided change and leash
+ */
+ public static RemoteAnimationTarget newTarget(TransitionInfo.Change change, int order,
+ SurfaceControl leash) {
+ int taskId;
+ boolean isNotInRecents;
+ ActivityManager.RunningTaskInfo taskInfo;
+ WindowConfiguration windowConfiguration;
+
+ taskInfo = change.getTaskInfo();
+ if (taskInfo != null) {
+ taskId = taskInfo.taskId;
+ isNotInRecents = !taskInfo.isRunning;
+ windowConfiguration = taskInfo.configuration.windowConfiguration;
+ } else {
+ taskId = INVALID_TASK_ID;
+ isNotInRecents = true;
+ windowConfiguration = new WindowConfiguration();
+ }
+
+ Rect localBounds = new Rect(change.getEndAbsBounds());
+ localBounds.offsetTo(change.getEndRelOffset().x, change.getEndRelOffset().y);
+
+ RemoteAnimationTarget target = new RemoteAnimationTarget(
+ taskId,
+ newModeToLegacyMode(change.getMode()),
+ // TODO: once we can properly sync transactions across process,
+ // then get rid of this leash.
+ leash,
+ (change.getFlags() & TransitionInfo.FLAG_TRANSLUCENT) != 0,
+ null,
+ // TODO(shell-transitions): we need to send content insets? evaluate how its used.
+ new Rect(0, 0, 0, 0),
+ order,
+ null,
+ localBounds,
+ new Rect(change.getEndAbsBounds()),
+ windowConfiguration,
+ isNotInRecents,
+ null,
+ new Rect(change.getStartAbsBounds()),
+ taskInfo,
+ change.getAllowEnterPip(),
+ (change.getFlags() & FLAG_IS_DIVIDER_BAR) != 0
+ ? TYPE_DOCK_DIVIDER : INVALID_WINDOW_TYPE
+ );
+ target.setWillShowImeOnTarget(
+ (change.getFlags() & TransitionInfo.FLAG_WILL_IME_SHOWN) != 0);
+ target.setRotationChange(change.getEndRotation() - change.getStartRotation());
+ return target;
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
index 2981f5e160f6..9224b3cbd798 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
@@ -174,7 +174,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
mWindowDecorByTaskId.put(taskInfo.taskId, windowDecoration);
final TaskPositioner taskPositioner =
- new TaskPositioner(mTaskOrganizer, windowDecoration);
+ new TaskPositioner(mTaskOrganizer, windowDecoration, mDisplayController);
final CaptionTouchEventListener touchEventListener =
new CaptionTouchEventListener(taskInfo, taskPositioner);
windowDecoration.setCaptionListeners(touchEventListener, touchEventListener);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index de5f2f467e99..2aa6d1217fa6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -20,10 +20,14 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
+import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
+
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityTaskManager;
import android.content.Context;
+import android.graphics.Rect;
import android.hardware.input.InputManager;
import android.os.Handler;
import android.os.Looper;
@@ -37,7 +41,6 @@ import android.view.MotionEvent;
import android.view.SurfaceControl;
import android.view.View;
import android.window.WindowContainerToken;
-import android.window.WindowContainerTransaction;
import androidx.annotation.Nullable;
@@ -50,6 +53,7 @@ import com.android.wm.shell.desktopmode.DesktopModeController;
import com.android.wm.shell.desktopmode.DesktopModeStatus;
import com.android.wm.shell.desktopmode.DesktopTasksController;
import com.android.wm.shell.freeform.FreeformTaskTransitionStarter;
+import com.android.wm.shell.splitscreen.SplitScreenController;
import java.util.Optional;
@@ -80,6 +84,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
private final InputMonitorFactory mInputMonitorFactory;
private TaskOperations mTaskOperations;
+ private Optional<SplitScreenController> mSplitScreenController;
+
public DesktopModeWindowDecorViewModel(
Context context,
Handler mainHandler,
@@ -88,7 +94,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
DisplayController displayController,
SyncTransactionQueue syncQueue,
Optional<DesktopModeController> desktopModeController,
- Optional<DesktopTasksController> desktopTasksController) {
+ Optional<DesktopTasksController> desktopTasksController,
+ Optional<SplitScreenController> splitScreenController) {
this(
context,
mainHandler,
@@ -98,6 +105,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
syncQueue,
desktopModeController,
desktopTasksController,
+ splitScreenController,
new DesktopModeWindowDecoration.Factory(),
new InputMonitorFactory());
}
@@ -112,6 +120,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
SyncTransactionQueue syncQueue,
Optional<DesktopModeController> desktopModeController,
Optional<DesktopTasksController> desktopTasksController,
+ Optional<SplitScreenController> splitScreenController,
DesktopModeWindowDecoration.Factory desktopModeWindowDecorFactory,
InputMonitorFactory inputMonitorFactory) {
mContext = context;
@@ -120,6 +129,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
mActivityTaskManager = mContext.getSystemService(ActivityTaskManager.class);
mTaskOrganizer = taskOrganizer;
mDisplayController = displayController;
+ mSplitScreenController = splitScreenController;
mSyncQueue = syncQueue;
mDesktopModeController = desktopModeController;
mDesktopTasksController = desktopTasksController;
@@ -230,6 +240,15 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
final int id = v.getId();
if (id == R.id.close_window || id == R.id.close_button) {
mTaskOperations.closeTask(mTaskToken);
+ if (mSplitScreenController.isPresent()
+ && mSplitScreenController.get().isSplitScreenVisible()) {
+ int remainingTaskPosition = mTaskId == mSplitScreenController.get()
+ .getTaskInfo(SPLIT_POSITION_TOP_OR_LEFT).taskId
+ ? SPLIT_POSITION_BOTTOM_OR_RIGHT : SPLIT_POSITION_TOP_OR_LEFT;
+ ActivityManager.RunningTaskInfo remainingTask = mSplitScreenController.get()
+ .getTaskInfo(remainingTaskPosition);
+ mSplitScreenController.get().moveTaskToFullscreen(remainingTask.taskId);
+ }
} else if (id == R.id.back_button) {
mTaskOperations.injectBackKey();
} else if (id == R.id.caption_handle) {
@@ -261,9 +280,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
if (taskInfo.isFocused) {
return mDragDetector.isDragEvent();
}
- final WindowContainerTransaction wct = new WindowContainerTransaction();
- wct.reorder(mTaskToken, true /* onTop */);
- mSyncQueue.queue(wct);
return false;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
@@ -401,14 +417,14 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
* @param ev the {@link MotionEvent} received by {@link EventReceiver}
*/
private void handleReceivedMotionEvent(MotionEvent ev, InputMonitor inputMonitor) {
+ final DesktopModeWindowDecoration relevantDecor = getRelevantWindowDecor(ev);
if (DesktopModeStatus.isProto2Enabled()) {
- final DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
- if (focusedDecor == null
- || focusedDecor.mTaskInfo.getWindowingMode() != WINDOWING_MODE_FREEFORM) {
- handleCaptionThroughStatusBar(ev);
+ if (relevantDecor == null
+ || relevantDecor.mTaskInfo.getWindowingMode() != WINDOWING_MODE_FREEFORM) {
+ handleCaptionThroughStatusBar(ev, relevantDecor);
}
}
- handleEventOutsideFocusedCaption(ev);
+ handleEventOutsideFocusedCaption(ev, relevantDecor);
// Prevent status bar from reacting to a caption drag.
if (DesktopModeStatus.isProto2Enabled()) {
if (mTransitionDragActive) {
@@ -422,16 +438,16 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
}
// If an UP/CANCEL action is received outside of caption bounds, turn off handle menu
- private void handleEventOutsideFocusedCaption(MotionEvent ev) {
+ private void handleEventOutsideFocusedCaption(MotionEvent ev,
+ DesktopModeWindowDecoration relevantDecor) {
final int action = ev.getActionMasked();
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
- final DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
- if (focusedDecor == null) {
+ if (relevantDecor == null) {
return;
}
if (!mTransitionDragActive) {
- focusedDecor.closeHandleMenuIfNeeded(ev);
+ relevantDecor.closeHandleMenuIfNeeded(ev);
}
}
}
@@ -441,39 +457,38 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
* Perform caption actions if not able to through normal means.
* Turn on desktop mode if handle is dragged below status bar.
*/
- private void handleCaptionThroughStatusBar(MotionEvent ev) {
+ private void handleCaptionThroughStatusBar(MotionEvent ev,
+ DesktopModeWindowDecoration relevantDecor) {
switch (ev.getActionMasked()) {
case MotionEvent.ACTION_DOWN: {
// Begin drag through status bar if applicable.
- final DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
- if (focusedDecor != null) {
+ if (relevantDecor != null) {
boolean dragFromStatusBarAllowed = false;
if (DesktopModeStatus.isProto2Enabled()) {
// In proto2 any full screen task can be dragged to freeform
- dragFromStatusBarAllowed = focusedDecor.mTaskInfo.getWindowingMode()
+ dragFromStatusBarAllowed = relevantDecor.mTaskInfo.getWindowingMode()
== WINDOWING_MODE_FULLSCREEN;
}
- if (dragFromStatusBarAllowed && focusedDecor.checkTouchEventInHandle(ev)) {
+ if (dragFromStatusBarAllowed && relevantDecor.checkTouchEventInHandle(ev)) {
mTransitionDragActive = true;
}
}
break;
}
case MotionEvent.ACTION_UP: {
- final DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
- if (focusedDecor == null) {
+ if (relevantDecor == null) {
mTransitionDragActive = false;
return;
}
if (mTransitionDragActive) {
mTransitionDragActive = false;
final int statusBarHeight = mDisplayController
- .getDisplayLayout(focusedDecor.mTaskInfo.displayId).stableInsets().top;
+ .getDisplayLayout(relevantDecor.mTaskInfo.displayId).stableInsets().top;
if (ev.getY() > statusBarHeight) {
if (DesktopModeStatus.isProto2Enabled()) {
mDesktopTasksController.ifPresent(
- c -> c.moveToDesktop(focusedDecor.mTaskInfo));
+ c -> c.moveToDesktop(relevantDecor.mTaskInfo));
} else if (DesktopModeStatus.isProto1Enabled()) {
mDesktopModeController.ifPresent(c -> c.setDesktopModeActive(true));
}
@@ -481,7 +496,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
return;
}
}
- focusedDecor.checkClickEvent(ev);
+ relevantDecor.checkClickEvent(ev);
break;
}
case MotionEvent.ACTION_CANCEL: {
@@ -491,6 +506,38 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
}
@Nullable
+ private DesktopModeWindowDecoration getRelevantWindowDecor(MotionEvent ev) {
+ if (mSplitScreenController.isPresent()
+ && mSplitScreenController.get().isSplitScreenVisible()) {
+ // We can't look at focused task here as only one task will have focus.
+ return getSplitScreenDecor(ev);
+ } else {
+ return getFocusedDecor();
+ }
+ }
+
+ @Nullable
+ private DesktopModeWindowDecoration getSplitScreenDecor(MotionEvent ev) {
+ ActivityManager.RunningTaskInfo topOrLeftTask =
+ mSplitScreenController.get().getTaskInfo(SPLIT_POSITION_TOP_OR_LEFT);
+ ActivityManager.RunningTaskInfo bottomOrRightTask =
+ mSplitScreenController.get().getTaskInfo(SPLIT_POSITION_BOTTOM_OR_RIGHT);
+ if (topOrLeftTask != null && topOrLeftTask.getConfiguration()
+ .windowConfiguration.getBounds().contains((int) ev.getX(), (int) ev.getY())) {
+ return mWindowDecorByTaskId.get(topOrLeftTask.taskId);
+ } else if (bottomOrRightTask != null && bottomOrRightTask.getConfiguration()
+ .windowConfiguration.getBounds().contains((int) ev.getX(), (int) ev.getY())) {
+ Rect bottomOrRightBounds = bottomOrRightTask.getConfiguration().windowConfiguration
+ .getBounds();
+ ev.offsetLocation(-bottomOrRightBounds.left, -bottomOrRightBounds.top);
+ return mWindowDecorByTaskId.get(bottomOrRightTask.taskId);
+ } else {
+ return null;
+ }
+
+ }
+
+ @Nullable
private DesktopModeWindowDecoration getFocusedDecor() {
final int size = mWindowDecorByTaskId.size();
DesktopModeWindowDecoration focusedDecor = null;
@@ -505,7 +552,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
}
private void createInputChannel(int displayId) {
- final InputManager inputManager = InputManager.getInstance();
+ final InputManager inputManager = mContext.getSystemService(InputManager.class);
final InputMonitor inputMonitor =
mInputMonitorFactory.create(inputManager, mContext);
final EventReceiver eventReceiver = new EventReceiver(inputMonitor,
@@ -558,7 +605,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
mWindowDecorByTaskId.put(taskInfo.taskId, windowDecoration);
final TaskPositioner taskPositioner =
- new TaskPositioner(mTaskOrganizer, windowDecoration, mDragStartListener);
+ new TaskPositioner(mTaskOrganizer, windowDecoration, mDisplayController,
+ mDragStartListener);
final DesktopModeTouchEventListener touchEventListener =
new DesktopModeTouchEventListener(taskInfo, taskPositioner);
windowDecoration.setCaptionListeners(touchEventListener, touchEventListener);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index 0779f1d72551..72da1089c91c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -74,6 +74,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
private boolean mDesktopActive;
private AdditionalWindow mHandleMenu;
private final int mHandleMenuWidthId = R.dimen.freeform_decor_caption_menu_width;
+ private final int mHandleMenuShadowRadiusId = R.dimen.caption_menu_shadow_radius;
+ private final int mHandleMenuCornerRadiusId = R.dimen.caption_menu_corner_radius;
private PointF mHandleMenuPosition = new PointF();
DesktopModeWindowDecoration(
@@ -353,19 +355,16 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
.windowConfiguration.getBounds().width();
final int menuWidth = loadDimensionPixelSize(resources, mHandleMenuWidthId);
final int menuHeight = loadDimensionPixelSize(resources, mCaptionMenuHeightId);
-
- // Elevation gives the appearance of a changed x/y coordinate; this is to fix that
- int elevationOffset = 2 * loadDimensionPixelSize(resources,
- R.dimen.caption_menu_elevation);
+ final int shadowRadius = loadDimensionPixelSize(resources, mHandleMenuShadowRadiusId);
+ final int cornerRadius = loadDimensionPixelSize(resources, mHandleMenuCornerRadiusId);
final int x = mRelayoutParams.mCaptionX + (captionWidth / 2) - (menuWidth / 2)
- - mResult.mDecorContainerOffsetX - elevationOffset;
- final int y =
- mRelayoutParams.mCaptionY - mResult.mDecorContainerOffsetY - elevationOffset;
+ - mResult.mDecorContainerOffsetX;
+ final int y = mRelayoutParams.mCaptionY - mResult.mDecorContainerOffsetY;
mHandleMenuPosition.set(x, y);
String namePrefix = "Caption Menu";
mHandleMenu = addWindow(R.layout.desktop_mode_decor_handle_menu, namePrefix, t, x, y,
- menuWidth, menuHeight, 2 * elevationOffset);
+ menuWidth, menuHeight, shadowRadius, cornerRadius);
mSyncQueue.runInSync(transaction -> {
transaction.merge(t);
t.close();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskOperations.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskOperations.java
index aea340464304..d0fcd8651481 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskOperations.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskOperations.java
@@ -65,7 +65,7 @@ class TaskOperations {
InputDevice.SOURCE_KEYBOARD);
ev.setDisplayId(mContext.getDisplay().getDisplayId());
- if (!InputManager.getInstance()
+ if (!mContext.getSystemService(InputManager.class)
.injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC)) {
Log.e(TAG, "Inject input event fail");
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskPositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskPositioner.java
index d3f92277bf03..a3d364a0068e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskPositioner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskPositioner.java
@@ -19,9 +19,11 @@ package com.android.wm.shell.windowdecor;
import android.annotation.IntDef;
import android.graphics.PointF;
import android.graphics.Rect;
+import android.util.DisplayMetrics;
import android.window.WindowContainerTransaction;
import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.DisplayController;
class TaskPositioner implements DragPositioningCallback {
@@ -35,6 +37,7 @@ class TaskPositioner implements DragPositioningCallback {
static final int CTRL_TYPE_BOTTOM = 8;
private final ShellTaskOrganizer mTaskOrganizer;
+ private final DisplayController mDisplayController;
private final WindowDecoration mWindowDecoration;
private final Rect mTaskBoundsAtDragStart = new Rect();
@@ -45,14 +48,16 @@ class TaskPositioner implements DragPositioningCallback {
private int mCtrlType;
private DragStartListener mDragStartListener;
- TaskPositioner(ShellTaskOrganizer taskOrganizer, WindowDecoration windowDecoration) {
- this(taskOrganizer, windowDecoration, dragStartListener -> {});
+ TaskPositioner(ShellTaskOrganizer taskOrganizer, WindowDecoration windowDecoration,
+ DisplayController displayController) {
+ this(taskOrganizer, windowDecoration, displayController, dragStartListener -> {});
}
TaskPositioner(ShellTaskOrganizer taskOrganizer, WindowDecoration windowDecoration,
- DragStartListener dragStartListener) {
+ DisplayController displayController, DragStartListener dragStartListener) {
mTaskOrganizer = taskOrganizer;
mWindowDecoration = windowDecoration;
+ mDisplayController = displayController;
mDragStartListener = dragStartListener;
}
@@ -128,15 +133,44 @@ class TaskPositioner implements DragPositioningCallback {
mRepositionTaskBounds.offset((int) deltaX, (int) deltaY);
}
+ // If width or height are negative or less than the minimum width or height, revert the
+ // respective bounds to use previous bound dimensions.
+ if (mRepositionTaskBounds.width() < getMinWidth()) {
+ mRepositionTaskBounds.right = oldRight;
+ mRepositionTaskBounds.left = oldLeft;
+ }
+ if (mRepositionTaskBounds.height() < getMinHeight()) {
+ mRepositionTaskBounds.top = oldTop;
+ mRepositionTaskBounds.bottom = oldBottom;
+ }
+ // If there are no changes to the bounds after checking new bounds against minimum width
+ // and height, do not set bounds and return false
if (oldLeft == mRepositionTaskBounds.left && oldTop == mRepositionTaskBounds.top
&& oldRight == mRepositionTaskBounds.right
&& oldBottom == mRepositionTaskBounds.bottom) {
return false;
}
+
wct.setBounds(mWindowDecoration.mTaskInfo.token, mRepositionTaskBounds);
return true;
}
+ private float getMinWidth() {
+ return mWindowDecoration.mTaskInfo.minWidth < 0 ? getDefaultMinSize()
+ : mWindowDecoration.mTaskInfo.minWidth;
+ }
+
+ private float getMinHeight() {
+ return mWindowDecoration.mTaskInfo.minHeight < 0 ? getDefaultMinSize()
+ : mWindowDecoration.mTaskInfo.minHeight;
+ }
+
+ private float getDefaultMinSize() {
+ float density = mDisplayController.getDisplayLayout(mWindowDecoration.mTaskInfo.displayId)
+ .densityDpi() * DisplayMetrics.DENSITY_DEFAULT_SCALE;
+ return mWindowDecoration.mTaskInfo.defaultMinSize * density;
+ }
+
interface DragStartListener {
/**
* Inform the implementing class that a drag resize has started
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
index 91b0aa193aad..7a7ac476879e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
@@ -391,11 +391,12 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
* @param yPos y position of new window
* @param width width of new window
* @param height height of new window
- * @param cropPadding padding to add to window crop to ensure shadows display properly
- * @return
+ * @param shadowRadius radius of the shadow of the new window
+ * @param cornerRadius radius of the corners of the new window
+ * @return the {@link AdditionalWindow} that was added.
*/
AdditionalWindow addWindow(int layoutId, String namePrefix, SurfaceControl.Transaction t,
- int xPos, int yPos, int width, int height, int cropPadding) {
+ int xPos, int yPos, int width, int height, int shadowRadius, int cornerRadius) {
final SurfaceControl.Builder builder = mSurfaceControlBuilderSupplier.get();
SurfaceControl windowSurfaceControl = builder
.setName(namePrefix + " of Task=" + mTaskInfo.taskId)
@@ -404,9 +405,10 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
.build();
View v = LayoutInflater.from(mDecorWindowContext).inflate(layoutId, null);
- t.setPosition(
- windowSurfaceControl, xPos, yPos)
- .setWindowCrop(windowSurfaceControl, width + cropPadding, height + cropPadding)
+ t.setPosition(windowSurfaceControl, xPos, yPos)
+ .setWindowCrop(windowSurfaceControl, width, height)
+ .setShadowRadius(windowSurfaceControl, shadowRadius)
+ .setCornerRadius(windowSurfaceControl, cornerRadius)
.show(windowSurfaceControl);
final WindowManager.LayoutParams lp =
new WindowManager.LayoutParams(width, height,
diff --git a/libs/WindowManager/Shell/tests/flicker/Android.bp b/libs/WindowManager/Shell/tests/flicker/Android.bp
index d6adaa7d533b..b6696c70dbb1 100644
--- a/libs/WindowManager/Shell/tests/flicker/Android.bp
+++ b/libs/WindowManager/Shell/tests/flicker/Android.bp
@@ -41,6 +41,8 @@ android_test {
static_libs: [
"androidx.test.ext.junit",
"flickerlib",
+ "flickerlib-apphelpers",
+ "flickerlib-helpers",
"truth-prebuilt",
"app-helpers-core",
"launcher-helper-lib",
diff --git a/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml b/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml
index 65923ff36fc8..67ca9a1a17f7 100644
--- a/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml
+++ b/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml
@@ -24,7 +24,11 @@
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
<option name="run-command" value="settings put secure show_ime_with_hard_keyboard 1" />
+ <option name="run-command" value="settings put system show_touches 1" />
+ <option name="run-command" value="settings put system pointer_location 1" />
<option name="teardown-command" value="settings delete secure show_ime_with_hard_keyboard" />
+ <option name="teardown-command" value="settings delete system show_touches" />
+ <option name="teardown-command" value="settings delete system pointer_location" />
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true"/>
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt
index aafd7edc7ef8..c5ee7b722617 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt
@@ -18,12 +18,13 @@ package com.android.wm.shell.flicker
import android.app.Instrumentation
import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerBuilderProvider
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
import androidx.test.platform.app.InstrumentationRegistry
import com.android.launcher3.tapl.LauncherInstrumentation
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
import com.android.server.wm.flicker.entireScreenCovered
-import com.android.server.wm.flicker.junit.FlickerBuilderProvider
import com.android.server.wm.flicker.navBarLayerIsVisibleAtStartAndEnd
import com.android.server.wm.flicker.navBarLayerPositionAtStartAndEnd
import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
@@ -32,7 +33,6 @@ import com.android.server.wm.flicker.statusBarLayerPositionAtStartAndEnd
import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
import com.android.server.wm.flicker.taskBarLayerIsVisibleAtStartAndEnd
import com.android.server.wm.flicker.taskBarWindowIsAlwaysVisible
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
import org.junit.Assume
import org.junit.Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
index bd18108c841e..ed93045ec462 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
@@ -18,13 +18,13 @@
package com.android.wm.shell.flicker
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.helpers.WindowUtils
-import com.android.server.wm.flicker.traces.layers.LayerTraceEntrySubject
-import com.android.server.wm.flicker.traces.layers.LayersTraceSubject
-import com.android.server.wm.traces.common.component.matchers.IComponentMatcher
-import com.android.server.wm.traces.common.region.Region
-import com.android.server.wm.traces.common.service.PlatformConsts
+import android.tools.common.Rotation
+import android.tools.common.datatypes.Region
+import android.tools.common.datatypes.component.IComponentMatcher
+import android.tools.common.flicker.subject.layers.LayerTraceEntrySubject
+import android.tools.common.flicker.subject.layers.LayersTraceSubject
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.helpers.WindowUtils
fun FlickerTest.appPairsDividerIsVisibleAtEnd() {
assertLayersEnd { this.isVisible(APP_PAIR_SPLIT_DIVIDER_COMPONENT) }
@@ -247,7 +247,7 @@ fun LayersTraceSubject.splitAppLayerBoundsSnapToDivider(
component: IComponentMatcher,
landscapePosLeft: Boolean,
portraitPosTop: Boolean,
- rotation: PlatformConsts.Rotation
+ rotation: Rotation
): LayersTraceSubject {
return invoke("splitAppLayerBoundsSnapToDivider") {
it.splitAppLayerBoundsSnapToDivider(component, landscapePosLeft, portraitPosTop, rotation)
@@ -258,11 +258,13 @@ fun LayerTraceEntrySubject.splitAppLayerBoundsSnapToDivider(
component: IComponentMatcher,
landscapePosLeft: Boolean,
portraitPosTop: Boolean,
- rotation: PlatformConsts.Rotation
+ rotation: Rotation
): LayerTraceEntrySubject {
val displayBounds = WindowUtils.getDisplayBounds(rotation)
return invoke {
- val dividerRegion = layer(SPLIT_SCREEN_DIVIDER_COMPONENT).visibleRegion.region
+ val dividerRegion =
+ layer(SPLIT_SCREEN_DIVIDER_COMPONENT)?.visibleRegion?.region
+ ?: error("$SPLIT_SCREEN_DIVIDER_COMPONENT component not found")
visibleRegion(component)
.coversAtMost(
if (displayBounds.width > displayBounds.height) {
@@ -367,46 +369,54 @@ fun FlickerTest.dockedStackDividerNotExistsAtEnd() {
}
fun FlickerTest.appPairsPrimaryBoundsIsVisibleAtEnd(
- rotation: PlatformConsts.Rotation,
+ rotation: Rotation,
primaryComponent: IComponentMatcher
) {
assertLayersEnd {
- val dividerRegion = layer(APP_PAIR_SPLIT_DIVIDER_COMPONENT).visibleRegion.region
+ val dividerRegion =
+ layer(APP_PAIR_SPLIT_DIVIDER_COMPONENT)?.visibleRegion?.region
+ ?: error("$APP_PAIR_SPLIT_DIVIDER_COMPONENT component not found")
visibleRegion(primaryComponent).overlaps(getPrimaryRegion(dividerRegion, rotation))
}
}
fun FlickerTest.dockedStackPrimaryBoundsIsVisibleAtEnd(
- rotation: PlatformConsts.Rotation,
+ rotation: Rotation,
primaryComponent: IComponentMatcher
) {
assertLayersEnd {
- val dividerRegion = layer(DOCKED_STACK_DIVIDER_COMPONENT).visibleRegion.region
+ val dividerRegion =
+ layer(DOCKED_STACK_DIVIDER_COMPONENT)?.visibleRegion?.region
+ ?: error("$DOCKED_STACK_DIVIDER_COMPONENT component not found")
visibleRegion(primaryComponent).overlaps(getPrimaryRegion(dividerRegion, rotation))
}
}
fun FlickerTest.appPairsSecondaryBoundsIsVisibleAtEnd(
- rotation: PlatformConsts.Rotation,
+ rotation: Rotation,
secondaryComponent: IComponentMatcher
) {
assertLayersEnd {
- val dividerRegion = layer(APP_PAIR_SPLIT_DIVIDER_COMPONENT).visibleRegion.region
+ val dividerRegion =
+ layer(APP_PAIR_SPLIT_DIVIDER_COMPONENT)?.visibleRegion?.region
+ ?: error("$APP_PAIR_SPLIT_DIVIDER_COMPONENT component not found")
visibleRegion(secondaryComponent).overlaps(getSecondaryRegion(dividerRegion, rotation))
}
}
fun FlickerTest.dockedStackSecondaryBoundsIsVisibleAtEnd(
- rotation: PlatformConsts.Rotation,
+ rotation: Rotation,
secondaryComponent: IComponentMatcher
) {
assertLayersEnd {
- val dividerRegion = layer(DOCKED_STACK_DIVIDER_COMPONENT).visibleRegion.region
+ val dividerRegion =
+ layer(DOCKED_STACK_DIVIDER_COMPONENT)?.visibleRegion?.region
+ ?: error("$DOCKED_STACK_DIVIDER_COMPONENT component not found")
visibleRegion(secondaryComponent).overlaps(getSecondaryRegion(dividerRegion, rotation))
}
}
-fun getPrimaryRegion(dividerRegion: Region, rotation: PlatformConsts.Rotation): Region {
+fun getPrimaryRegion(dividerRegion: Region, rotation: Rotation): Region {
val displayBounds = WindowUtils.getDisplayBounds(rotation)
return if (rotation.isRotated()) {
Region.from(
@@ -425,7 +435,7 @@ fun getPrimaryRegion(dividerRegion: Region, rotation: PlatformConsts.Rotation):
}
}
-fun getSecondaryRegion(dividerRegion: Region, rotation: PlatformConsts.Rotation): Region {
+fun getSecondaryRegion(dividerRegion: Region, rotation: Rotation): Region {
val displayBounds = WindowUtils.getDisplayBounds(rotation)
return if (rotation.isRotated()) {
Region.from(
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt
index e9c805ee5f4d..983640a70c4b 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt
@@ -18,7 +18,7 @@
package com.android.wm.shell.flicker
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
+import android.tools.common.datatypes.component.ComponentNameMatcher
const val SYSTEM_UI_PACKAGE_NAME = "com.android.systemui"
const val LAUNCHER_UI_PACKAGE_NAME = "com.google.android.apps.nexuslauncher"
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/BaseBubbleScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/BaseBubbleScreen.kt
index 996b677470fe..bab81d79c804 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/BaseBubbleScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/BaseBubbleScreen.kt
@@ -21,16 +21,16 @@ import android.app.NotificationManager
import android.content.Context
import android.content.pm.PackageManager
import android.os.ServiceManager
+import android.tools.common.Rotation
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.flicker.legacy.IFlickerTestData
+import android.tools.device.helpers.SYSTEMUI_PACKAGE
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiObject2
import androidx.test.uiautomator.Until
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.IFlickerTestData
import com.android.server.wm.flicker.helpers.LaunchBubbleHelper
-import com.android.server.wm.flicker.helpers.SYSTEMUI_PACKAGE
-import com.android.server.wm.traces.common.service.PlatformConsts
import com.android.wm.shell.flicker.BaseTest
import org.junit.runners.Parameterized
@@ -89,7 +89,7 @@ abstract class BaseBubbleScreen(flicker: FlickerTest) : BaseTest(flicker) {
@JvmStatic
fun getParams(): List<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTest.kt
index 7358da3a58af..d0bca1332553 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTest.kt
@@ -18,14 +18,14 @@ package com.android.wm.shell.flicker.bubble
import android.os.SystemClock
import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
import androidx.test.filters.RequiresDevice
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiObject2
import androidx.test.uiautomator.Until
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import org.junit.Assume
import org.junit.Before
import org.junit.Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTestCfArm.kt
index 1a0fbe461444..bdfdad59c600 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTestCfArm.kt
@@ -16,8 +16,8 @@
package com.android.wm.shell.flicker.bubble
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTestShellTransit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTestShellTransit.kt
index cf696c8bbf59..5e85eb87e0e9 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTestShellTransit.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTestShellTransit.kt
@@ -17,10 +17,10 @@
package com.android.wm.shell.flicker.bubble
import android.platform.test.annotations.FlakyTest
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import org.junit.Assume
import org.junit.Before
import org.junit.runner.RunWith
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DragToDismissBubbleScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DragToDismissBubbleScreenTest.kt
index 9367a8a0491a..8474ce0e64e5 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DragToDismissBubbleScreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DragToDismissBubbleScreenTest.kt
@@ -19,14 +19,14 @@ package com.android.wm.shell.flicker.bubble
import android.content.Context
import android.graphics.Point
import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
import android.util.DisplayMetrics
import android.view.WindowManager
import androidx.test.filters.RequiresDevice
import androidx.test.uiautomator.By
import androidx.test.uiautomator.Until
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DragToDismissBubbleScreenTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DragToDismissBubbleScreenTestCfArm.kt
index 85a534c30ed5..62fa7b4516c7 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DragToDismissBubbleScreenTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DragToDismissBubbleScreenTestCfArm.kt
@@ -16,8 +16,8 @@
package com.android.wm.shell.flicker.bubble
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleOnLockreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleOnLocksreenTest.kt
index 0b1382be0c91..416315e4b06d 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleOnLockreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleOnLocksreenTest.kt
@@ -18,14 +18,14 @@ package com.android.wm.shell.flicker.bubble
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Postsubmit
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
import android.view.WindowInsets
import android.view.WindowManager
import androidx.test.filters.RequiresDevice
import androidx.test.uiautomator.By
import androidx.test.uiautomator.Until
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.navBarLayerIsVisibleAtEnd
import com.android.server.wm.flicker.navBarLayerPositionAtEnd
import org.junit.Assume
@@ -36,7 +36,7 @@ import org.junit.runners.Parameterized
/**
* Test launching a new activity from bubble.
*
- * To run this test: `atest WMShellFlickerTests:LaunchBubbleFromLockScreen`
+ * To run this test: `atest WMShellFlickerTests:OpenActivityFromBubbleOnLocksreenTest`
*
* Actions:
* ```
@@ -46,7 +46,7 @@ import org.junit.runners.Parameterized
@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-class OpenActivityFromBubbleOnLockreenTest(flicker: FlickerTest) : BaseBubbleScreen(flicker) {
+class OpenActivityFromBubbleOnLocksreenTest(flicker: FlickerTest) : BaseBubbleScreen(flicker) {
/** {@inheritDoc} */
override val transition: FlickerBuilder.() -> Unit
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleTest.kt
index 50507bf88d2f..07ba41333071 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleTest.kt
@@ -17,12 +17,12 @@
package com.android.wm.shell.flicker.bubble
import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
import androidx.test.filters.RequiresDevice
import androidx.test.uiautomator.By
import androidx.test.uiautomator.Until
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleTestCfArm.kt
index 94147e876372..6c61710d6284 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleTestCfArm.kt
@@ -16,8 +16,8 @@
package com.android.wm.shell.flicker.bubble
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/SendBubbleNotificationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/SendBubbleNotificationTest.kt
index 4be4dcd7e1f0..29f76d01af83 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/SendBubbleNotificationTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/SendBubbleNotificationTest.kt
@@ -17,12 +17,12 @@
package com.android.wm.shell.flicker.bubble
import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
import androidx.test.filters.RequiresDevice
import androidx.test.uiautomator.By
import androidx.test.uiautomator.Until
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/SendBubbleNotificationTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/SendBubbleNotificationTestCfArm.kt
index 7efbcdbf0013..e323ebf3b5c8 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/SendBubbleNotificationTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/SendBubbleNotificationTestCfArm.kt
@@ -16,8 +16,8 @@
package com.android.wm.shell.flicker.bubble
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt
index 88cf15e92c99..1045a5ac2ce8 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt
@@ -18,10 +18,10 @@ package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import org.junit.Assume
import org.junit.FixMethodOrder
import org.junit.Test
@@ -44,7 +44,7 @@ import org.junit.runners.Parameterized
* ```
* 1. All assertions are inherited from [EnterPipTest]
* 2. Part of the test setup occurs automatically via
- * [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ * [android.tools.device.flicker.legacy.runner.TransitionRunner],
* including configuring navigation mode, initial orientation and ensuring no
* apps are running before setup
* ```
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt
index 88542d51563d..2d2588ef4348 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt
@@ -17,11 +17,11 @@
package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -43,7 +43,7 @@ import org.junit.runners.Parameterized
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
* are inherited [PipTransition]
* 2. Part of the test setup occurs automatically via
- * [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ * [android.tools.device.flicker.legacy.runner.TransitionRunner],
* including configuring navigation mode, initial orientation and ensuring no
* apps are running before setup
* ```
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTestCfArm.kt
index fb1eb01918d7..02f60100d069 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTestCfArm.kt
@@ -16,10 +16,10 @@
package com.android.wm.shell.flicker.pip
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.service.PlatformConsts
+import android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@@ -40,7 +40,7 @@ class ClosePipBySwipingDownTestCfArm(flicker: FlickerTest) : ClosePipBySwipingDo
@JvmStatic
fun getParams(): List<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipTransition.kt
index 080e033f3074..6c5a344c8f79 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipTransition.kt
@@ -17,13 +17,13 @@
package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.Presubmit
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher.Companion.LAUNCHER
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher.Companion.LAUNCHER
-import com.android.server.wm.traces.common.service.PlatformConsts
import org.junit.Test
import org.junit.runners.Parameterized
@@ -32,7 +32,7 @@ abstract class ClosePipTransition(flicker: FlickerTest) : PipTransition(flicker)
override val transition: FlickerBuilder.() -> Unit
get() = buildTransition {
setup { this.setRotation(flicker.scenario.startRotation) }
- teardown { this.setRotation(PlatformConsts.Rotation.ROTATION_0) }
+ teardown { this.setRotation(Rotation.ROTATION_0) }
}
/**
@@ -91,7 +91,7 @@ abstract class ClosePipTransition(flicker: FlickerTest) : PipTransition(flicker)
@JvmStatic
fun getParams(): List<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt
index f27fa4a81328..e540ad543228 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt
@@ -17,10 +17,10 @@
package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -43,7 +43,7 @@ import org.junit.runners.Parameterized
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
* are inherited [PipTransition]
* 2. Part of the test setup occurs automatically via
- * [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ * [android.tools.device.flicker.legacy.runner.TransitionRunner],
* including configuring navigation mode, initial orientation and ensuring no
* apps are running before setup
* ```
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTestCfArm.kt
index fbada69f6f32..05262feceba5 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTestCfArm.kt
@@ -16,10 +16,10 @@
package com.android.wm.shell.flicker.pip
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.service.PlatformConsts
+import android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@@ -41,7 +41,7 @@ open class ClosePipWithDismissButtonTestCfArm(flicker: FlickerTest) :
@JvmStatic
fun getParams(): List<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
index 47537c6c5cdd..11bb0cc1306e 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
@@ -17,10 +17,10 @@
package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import org.junit.Assume
import org.junit.FixMethodOrder
import org.junit.Test
@@ -39,14 +39,6 @@ import org.junit.runners.Parameterized
* Select "Via code behind" radio button
* Press Home button or swipe up to go Home and put [pipApp] in pip mode
* ```
- * Notes:
- * ```
- * 1. All assertions are inherited from [EnterPipTest]
- * 2. Part of the test setup occurs automatically via
- * [com.android.server.wm.flicker.TransitionRunnerWithRules],
- * including configuring navigation mode, initial orientation and ensuring no
- * apps are running before setup
- * ```
*/
@RequiresDevice
@RunWith(Parameterized::class)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTestCfArm.kt
index e47805001cd0..90f99c0c4cae 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTestCfArm.kt
@@ -16,8 +16,8 @@
package com.android.wm.shell.flicker.pip
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt
index db5048968112..e079d5477e2f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt
@@ -20,18 +20,18 @@ import android.app.Activity
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.helpers.WindowUtils
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
import com.android.server.wm.flicker.entireScreenCovered
import com.android.server.wm.flicker.helpers.FixedOrientationAppHelper
-import com.android.server.wm.flicker.helpers.WindowUtils
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.testapp.ActivityOptions.Pip.ACTION_ENTER_PIP
import com.android.server.wm.flicker.testapp.ActivityOptions.PortraitOnlyActivity.EXTRA_FIXED_ORIENTATION
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.service.PlatformConsts
import com.android.wm.shell.flicker.pip.PipTransition.BroadcastActionTrigger.Companion.ORIENTATION_LANDSCAPE
import com.android.wm.shell.flicker.pip.PipTransition.BroadcastActionTrigger.Companion.ORIENTATION_PORTRAIT
import org.junit.Assume
@@ -58,7 +58,7 @@ import org.junit.runners.Parameterized
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
* are inherited [PipTransition]
* 2. Part of the test setup occurs automatically via
- * [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ * [android.tools.device.flicker.legacy.runner.TransitionRunner],
* including configuring navigation mode, initial orientation and ensuring no
* apps are running before setup
* ```
@@ -69,8 +69,8 @@ import org.junit.runners.Parameterized
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
open class EnterPipToOtherOrientation(flicker: FlickerTest) : PipTransition(flicker) {
private val testApp = FixedOrientationAppHelper(instrumentation)
- private val startingBounds = WindowUtils.getDisplayBounds(PlatformConsts.Rotation.ROTATION_90)
- private val endingBounds = WindowUtils.getDisplayBounds(PlatformConsts.Rotation.ROTATION_0)
+ private val startingBounds = WindowUtils.getDisplayBounds(Rotation.ROTATION_90)
+ private val endingBounds = WindowUtils.getDisplayBounds(Rotation.ROTATION_0)
/** Defines the transition used to run the test */
override val transition: FlickerBuilder.() -> Unit
@@ -213,7 +213,7 @@ open class EnterPipToOtherOrientation(flicker: FlickerTest) : PipTransition(flic
@JvmStatic
fun getParams(): Collection<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationCfArm.kt
index ec5f13cbed49..58416660826f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationCfArm.kt
@@ -16,10 +16,10 @@
package com.android.wm.shell.flicker.pip
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.service.PlatformConsts
+import android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@@ -42,7 +42,7 @@ open class EnterPipToOtherOrientationCfArm(flicker: FlickerTest) :
@JvmStatic
fun getParams(): Collection<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt
index 3ef66d7e8ed2..327225421580 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt
@@ -17,11 +17,11 @@
package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.Presubmit
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.service.PlatformConsts
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import org.junit.Test
import org.junit.runners.Parameterized
@@ -130,7 +130,7 @@ abstract class EnterPipTransition(flicker: FlickerTest) : PipTransition(flicker)
@JvmStatic
fun getParams(): List<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt
index c3c705eb58e5..1f060e931be2 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt
@@ -16,10 +16,10 @@
package com.android.wm.shell.flicker.pip
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@@ -40,7 +40,7 @@ import org.junit.runners.Parameterized
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
* are inherited from [PipTransition]
* 2. Part of the test setup occurs automatically via
- * [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ * [android.tools.device.flicker.legacy.runner.TransitionRunner],
* including configuring navigation mode, initial orientation and ensuring no
* apps are running before setup
* ```
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTestCfArm.kt
index b487ff4a296b..4390f0bb70b2 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTestCfArm.kt
@@ -16,10 +16,10 @@
package com.android.wm.shell.flicker.pip
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.service.PlatformConsts
+import android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@@ -40,7 +40,7 @@ class EnterPipViaAppUiButtonTestCfArm(flicker: FlickerTest) : EnterPipViaAppUiBu
@JvmStatic
fun getParams(): List<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt
index f88f8d6e64ed..2001f484ed96 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt
@@ -17,11 +17,11 @@
package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.Presubmit
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import com.android.server.wm.flicker.helpers.SimpleAppHelper
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.service.PlatformConsts
import org.junit.Test
import org.junit.runners.Parameterized
@@ -137,7 +137,7 @@ abstract class ExitPipToAppTransition(flicker: FlickerTest) : PipTransition(flic
@JvmStatic
fun getParams(): List<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt
index d2fbb2a2c941..313631cbe8ee 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt
@@ -18,11 +18,11 @@ package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import org.junit.Assume
import org.junit.FixMethodOrder
import org.junit.Test
@@ -47,7 +47,7 @@ import org.junit.runners.Parameterized
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
* are inherited [PipTransition]
* 2. Part of the test setup occurs automatically via
- * [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ * [android.tools.device.flicker.legacy.runner.TransitionRunner],
* including configuring navigation mode, initial orientation and ensuring no
* apps are running before setup
* ```
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTestCfArm.kt
index 8b3755e38366..eccb85d98798 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTestCfArm.kt
@@ -16,10 +16,10 @@
package com.android.wm.shell.flicker.pip
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.service.PlatformConsts
+import android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@@ -41,7 +41,7 @@ class ExitPipToAppViaExpandButtonTestCfArm(flicker: FlickerTest) :
@JvmStatic
fun getParams(): List<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt
index a9eb18d44856..93ffdd8d5294 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt
@@ -18,11 +18,11 @@ package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import org.junit.Assume
import org.junit.FixMethodOrder
import org.junit.Test
@@ -46,7 +46,7 @@ import org.junit.runners.Parameterized
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
* are inherited from [PipTransition]
* 2. Part of the test setup occurs automatically via
- * [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ * [android.tools.device.flicker.legacy.runner.TransitionRunner],
* including configuring navigation mode, initial orientation and ensuring no
* apps are running before setup
* ```
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTestCfArm.kt
index 39b1c82f9676..6ab6a1f0bb73 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTestCfArm.kt
@@ -16,10 +16,10 @@
package com.android.wm.shell.flicker.pip
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.service.PlatformConsts
+import android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@@ -40,7 +40,7 @@ class ExitPipToAppViaIntentTestCfArm(flicker: FlickerTest) : ExitPipToAppViaInte
@JvmStatic
fun getParams(): List<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
index d577b4f46319..7d5f740838bd 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
@@ -17,13 +17,13 @@
package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.Presubmit
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.service.PlatformConsts
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -45,7 +45,7 @@ import org.junit.runners.Parameterized
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
* are inherited [PipTransition]
* 2. Part of the test setup occurs automatically via
- * [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ * [android.tools.device.flicker.legacy.runner.TransitionRunner],
* including configuring navigation mode, initial orientation and ensuring no
* apps are running before setup
* ```
@@ -147,7 +147,7 @@ open class ExpandPipOnDoubleClickTest(flicker: FlickerTest) : PipTransition(flic
@JvmStatic
fun getParams(): List<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTestTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTestTestCfArm.kt
index 08db8aefb148..c09623490041 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTestTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTestTestCfArm.kt
@@ -16,10 +16,10 @@
package com.android.wm.shell.flicker.pip
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.service.PlatformConsts
+import android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@@ -41,7 +41,7 @@ class ExpandPipOnDoubleClickTestTestCfArm(flicker: FlickerTest) :
@JvmStatic
fun getParams(): List<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTest.kt
index fcb8af4e8d40..0b73aac02797 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTest.kt
@@ -17,12 +17,12 @@
package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.Presubmit
+import android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.service.PlatformConsts
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -61,7 +61,7 @@ open class ExpandPipOnPinchOpenTest(flicker: FlickerTest) : PipTransition(flicke
@JvmStatic
fun getParams(): List<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTestCfArm.kt
index 30050bf4e9d9..e064bf2ee921 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTestCfArm.kt
@@ -16,10 +16,10 @@
package com.android.wm.shell.flicker.pip
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.service.PlatformConsts
+import android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@@ -40,7 +40,7 @@ class ExpandPipOnPinchOpenTestCfArm(flicker: FlickerTest) : ExpandPipOnPinchOpen
@JvmStatic
fun getParams(): List<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt
index 39ac49f8c81c..9c007449fb8d 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt
@@ -17,10 +17,10 @@
package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import com.android.wm.shell.flicker.Direction
import org.junit.FixMethodOrder
import org.junit.Test
@@ -45,7 +45,7 @@ import org.junit.runners.Parameterized
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
* are inherited [PipTransition]
* 2. Part of the test setup occurs automatically via
- * [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ * [android.tools.device.flicker.legacy.runner.TransitionRunner],
* including configuring navigation mode, initial orientation and ensuring no
* apps are running before setup
* ```
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt
index 7db80a8c8110..c23838a987bf 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt
@@ -17,17 +17,17 @@
package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.Presubmit
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.helpers.WindowUtils
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
import com.android.server.wm.flicker.helpers.ImeAppHelper
-import com.android.server.wm.flicker.helpers.WindowUtils
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.service.PlatformConsts
import org.junit.Assume.assumeFalse
import org.junit.Before
import org.junit.FixMethodOrder
@@ -91,7 +91,7 @@ open class MovePipOnImeVisibilityChangeTest(flicker: FlickerTest) : PipTransitio
@JvmStatic
fun getParams(): Collection<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTestCfArm.kt
index be3bd60d28e8..d3d77d20662e 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTestCfArm.kt
@@ -16,10 +16,10 @@
package com.android.wm.shell.flicker.pip
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.service.PlatformConsts
+import android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@@ -37,7 +37,7 @@ class MovePipOnImeVisibilityChangeTestCfArm(flicker: FlickerTest) :
@JvmStatic
fun getParams(): Collection<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTestShellTransit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTestShellTransit.kt
index ef9920c3c793..6f8111690f0f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTestShellTransit.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTestShellTransit.kt
@@ -17,10 +17,10 @@
package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import org.junit.Assume
import org.junit.Before
import org.junit.FixMethodOrder
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipShelfHeightTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipShelfHeightTransition.kt
index 77a8c3c3e43f..109354ab5c79 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipShelfHeightTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipShelfHeightTransition.kt
@@ -17,11 +17,11 @@
package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.Presubmit
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
+import android.tools.common.Rotation
+import android.tools.common.flicker.subject.region.RegionSubject
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import com.android.server.wm.flicker.helpers.FixedOrientationAppHelper
-import com.android.server.wm.flicker.traces.region.RegionSubject
-import com.android.server.wm.traces.common.service.PlatformConsts
import com.android.wm.shell.flicker.Direction
import org.junit.Test
import org.junit.runners.Parameterized
@@ -118,7 +118,7 @@ abstract class MovePipShelfHeightTransition(flicker: FlickerTest) : PipTransitio
@JvmStatic
fun getParams(): List<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt
index 511a6511eb44..c8d5624b1d77 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt
@@ -17,10 +17,10 @@
package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import com.android.wm.shell.flicker.Direction
import org.junit.FixMethodOrder
import org.junit.Test
@@ -45,7 +45,7 @@ import org.junit.runners.Parameterized
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
* are inherited [PipTransition]
* 2. Part of the test setup occurs automatically via
- * [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ * [android.tools.device.flicker.legacy.runner.TransitionRunner],
* including configuring navigation mode, initial orientation and ensuring no
* apps are running before setup
* ```
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt
index e13344390584..85b2fbce2f21 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt
@@ -17,12 +17,12 @@
package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.Postsubmit
+import android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.service.PlatformConsts
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -61,7 +61,7 @@ class PipPinchInTest(flicker: FlickerTest) : PipTransition(flicker) {
@JvmStatic
fun getParams(): List<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt
index 166416a49e4b..b30f30830156 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt
@@ -19,15 +19,15 @@ package com.android.wm.shell.flicker.pip
import android.app.Instrumentation
import android.content.Intent
import android.platform.test.annotations.Presubmit
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule.Companion.removeAllTasksButHome
+import android.tools.device.helpers.WindowUtils
import com.android.server.wm.flicker.helpers.PipAppHelper
-import com.android.server.wm.flicker.helpers.WindowUtils
import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.rules.RemoveAllTasksButHomeRule.Companion.removeAllTasksButHome
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.service.PlatformConsts
import com.android.wm.shell.flicker.BaseTest
import com.google.common.truth.Truth
import org.junit.Test
@@ -70,7 +70,7 @@ abstract class PipTransition(flicker: FlickerTest) : BaseTest(flicker) {
): FlickerBuilder.() -> Unit {
return {
setup {
- setRotation(PlatformConsts.Rotation.ROTATION_0)
+ setRotation(Rotation.ROTATION_0)
removeAllTasksButHome()
pipApp.launchViaIntentAndWaitForPip(wmHelper, stringExtras = stringExtras)
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinned.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinned.kt
index 3f5d06748d05..3850c1f6c89a 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinned.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinned.kt
@@ -20,15 +20,15 @@ import android.app.Activity
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
+import android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.helpers.WindowUtils
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.helpers.WindowUtils
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.testapp.ActivityOptions
import com.android.server.wm.flicker.testapp.ActivityOptions.PortraitOnlyActivity.EXTRA_FIXED_ORIENTATION
-import com.android.server.wm.traces.common.service.PlatformConsts
import com.android.wm.shell.flicker.pip.PipTransition.BroadcastActionTrigger.Companion.ORIENTATION_LANDSCAPE
import org.junit.Assume
import org.junit.Before
@@ -47,8 +47,8 @@ import org.junit.runners.Parameterized
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
open class SetRequestedOrientationWhilePinned(flicker: FlickerTest) : PipTransition(flicker) {
- private val startingBounds = WindowUtils.getDisplayBounds(PlatformConsts.Rotation.ROTATION_0)
- private val endingBounds = WindowUtils.getDisplayBounds(PlatformConsts.Rotation.ROTATION_90)
+ private val startingBounds = WindowUtils.getDisplayBounds(Rotation.ROTATION_0)
+ private val endingBounds = WindowUtils.getDisplayBounds(Rotation.ROTATION_90)
/** {@inheritDoc} */
override val transition: FlickerBuilder.() -> Unit
@@ -66,7 +66,7 @@ open class SetRequestedOrientationWhilePinned(flicker: FlickerTest) : PipTransit
wmHelper
.StateSyncBuilder()
.withPipShown()
- .withRotation(PlatformConsts.Rotation.ROTATION_0)
+ .withRotation(Rotation.ROTATION_0)
.withNavOrTaskBarVisible()
.withStatusBarVisible()
.waitForAndVerify()
@@ -79,7 +79,7 @@ open class SetRequestedOrientationWhilePinned(flicker: FlickerTest) : PipTransit
wmHelper
.StateSyncBuilder()
.withFullScreenApp(pipApp)
- .withRotation(PlatformConsts.Rotation.ROTATION_90)
+ .withRotation(Rotation.ROTATION_90)
.withNavOrTaskBarVisible()
.withStatusBarVisible()
.waitForAndVerify()
@@ -98,7 +98,7 @@ open class SetRequestedOrientationWhilePinned(flicker: FlickerTest) : PipTransit
@Presubmit
@Test
fun displayEndsAt90Degrees() {
- flicker.assertWmEnd { hasRotation(PlatformConsts.Rotation.ROTATION_90) }
+ flicker.assertWmEnd { hasRotation(Rotation.ROTATION_90) }
}
@Presubmit
@@ -151,7 +151,7 @@ open class SetRequestedOrientationWhilePinned(flicker: FlickerTest) : PipTransit
@JvmStatic
fun getParams(): Collection<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt
index 720fe7244047..2cf8f61f13fe 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt
@@ -17,14 +17,14 @@
package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.helpers.WindowUtils
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
import com.android.server.wm.flicker.helpers.SimpleAppHelper
-import com.android.server.wm.flicker.helpers.WindowUtils
import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -48,7 +48,7 @@ import org.junit.runners.Parameterized
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
* are inherited from [PipTransition]
* 2. Part of the test setup occurs automatically via
- * [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ * [android.tools.device.flicker.legacy.runner.TransitionRunner],
* including configuring navigation mode, initial orientation and ensuring no
* apps are running before setup
* ```
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplayCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplayCfArm.kt
index daf3e1b18b4b..b7a2c47e3b32 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplayCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplayCfArm.kt
@@ -16,9 +16,9 @@
package com.android.wm.shell.flicker.pip
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/PipAppHelperTv.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/PipAppHelperTv.kt
index 36909dd74245..000ae8f9458e 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/PipAppHelperTv.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/PipAppHelperTv.kt
@@ -17,12 +17,12 @@
package com.android.wm.shell.flicker.pip.tv
import android.app.Instrumentation
+import android.tools.device.traces.parsers.WindowManagerStateHelper
import androidx.test.uiautomator.By
import androidx.test.uiautomator.BySelector
import androidx.test.uiautomator.UiObject2
import androidx.test.uiautomator.Until
import com.android.server.wm.flicker.helpers.PipAppHelper
-import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
/** Helper class for PIP app on AndroidTV */
open class PipAppHelperTv(instrumentation: Instrumentation) : PipAppHelper(instrumentation) {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt
index dc1fe4761757..6104b7bdacba 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt
@@ -20,10 +20,10 @@ import android.app.ActivityManager
import android.app.IActivityManager
import android.app.IProcessObserver
import android.os.SystemClock
+import android.tools.device.helpers.wakeUpAndGoToHomeScreen
+import android.tools.device.traces.parsers.WindowManagerStateHelper
import android.view.Surface.ROTATION_0
import android.view.Surface.rotationToString
-import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
-import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
import com.android.wm.shell.flicker.SYSTEM_UI_PACKAGE_NAME
import org.junit.After
import org.junit.Assert.assertFalse
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt
index 247403a2cbc6..0c9c16153ea3 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt
@@ -19,13 +19,13 @@ package com.android.wm.shell.flicker.splitscreen
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.datatypes.component.EdgeExtensionComponentMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.component.matchers.EdgeExtensionComponentMatcher
import com.android.wm.shell.flicker.SPLIT_SCREEN_DIVIDER_COMPONENT
import com.android.wm.shell.flicker.appWindowIsVisibleAtEnd
import com.android.wm.shell.flicker.appWindowIsVisibleAtStart
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByDivider.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByDivider.kt
index d3c68207bf97..1b55f3975e1c 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByDivider.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByDivider.kt
@@ -20,12 +20,12 @@ import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.helpers.WindowUtils
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.helpers.WindowUtils
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import com.android.wm.shell.flicker.appWindowBecomesInvisible
import com.android.wm.shell.flicker.appWindowIsVisibleAtEnd
import com.android.wm.shell.flicker.layerBecomesInvisible
@@ -104,14 +104,12 @@ class DismissSplitScreenByDivider(flicker: FlickerTest) : SplitScreenBase(flicke
@Test
fun secondaryAppBoundsIsFullscreenAtEnd() {
flicker.assertLayers {
- this.isVisible(secondaryApp)
- .then()
- .isInvisible(secondaryApp)
- .then()
- .invoke("secondaryAppBoundsIsFullscreenAtEnd") {
- val displayBounds = WindowUtils.getDisplayBounds(flicker.scenario.endRotation)
- it.visibleRegion(secondaryApp).coversExactly(displayBounds)
- }
+ this.isVisible(secondaryApp).then().isInvisible(secondaryApp).then().invoke(
+ "secondaryAppBoundsIsFullscreenAtEnd"
+ ) {
+ val displayBounds = WindowUtils.getDisplayBounds(flicker.scenario.endRotation)
+ it.visibleRegion(secondaryApp).coversExactly(displayBounds)
+ }
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByGoHome.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByGoHome.kt
index b44b681704ba..bd2ffc1a018d 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByGoHome.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByGoHome.kt
@@ -19,11 +19,11 @@ package com.android.wm.shell.flicker.splitscreen
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import com.android.wm.shell.flicker.appWindowBecomesInvisible
import com.android.wm.shell.flicker.layerBecomesInvisible
import com.android.wm.shell.flicker.splitAppLayerBoundsBecomesInvisible
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt
index 514365fbd71a..7db5ecc484ad 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt
@@ -19,12 +19,12 @@ package com.android.wm.shell.flicker.splitscreen
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import com.android.wm.shell.flicker.SPLIT_SCREEN_DIVIDER_COMPONENT
import com.android.wm.shell.flicker.appWindowIsVisibleAtEnd
import com.android.wm.shell.flicker.appWindowIsVisibleAtStart
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromAllApps.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromAllApps.kt
index 4e36c367f226..ffdb87f190d5 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromAllApps.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromAllApps.kt
@@ -19,13 +19,13 @@ package com.android.wm.shell.flicker.splitscreen
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
+import android.tools.common.NavBar
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.service.PlatformConsts
import com.android.wm.shell.flicker.SPLIT_SCREEN_DIVIDER_COMPONENT
import com.android.wm.shell.flicker.appWindowBecomesVisible
import com.android.wm.shell.flicker.appWindowIsVisibleAtEnd
@@ -186,7 +186,7 @@ class EnterSplitScreenByDragFromAllApps(flicker: FlickerTest) : SplitScreenBase(
fun getParams(): List<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
// TODO(b/176061063):The 3 buttons of nav bar do not exist in the hierarchy.
- supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL)
+ supportedNavigationModes = listOf(NavBar.MODE_GESTURAL)
)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromNotification.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromNotification.kt
index 5d37e858c15f..792e2b03522f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromNotification.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromNotification.kt
@@ -19,13 +19,13 @@ package com.android.wm.shell.flicker.splitscreen
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
+import android.tools.common.NavBar
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.service.PlatformConsts
import com.android.wm.shell.flicker.SPLIT_SCREEN_DIVIDER_COMPONENT
import com.android.wm.shell.flicker.appWindowIsVisibleAtEnd
import com.android.wm.shell.flicker.layerBecomesVisible
@@ -208,7 +208,7 @@ class EnterSplitScreenByDragFromNotification(flicker: FlickerTest) : SplitScreen
fun getParams(): List<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
// TODO(b/176061063):The 3 buttons of nav bar do not exist in the hierarchy.
- supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL)
+ supportedNavigationModes = listOf(NavBar.MODE_GESTURAL)
)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromShortcut.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromShortcut.kt
index d086f7e04486..c1977e9e82f7 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromShortcut.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromShortcut.kt
@@ -19,12 +19,12 @@ package com.android.wm.shell.flicker.splitscreen
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Presubmit
+import android.tools.common.NavBar
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.service.PlatformConsts
import com.android.wm.shell.flicker.appWindowIsVisibleAtEnd
import com.android.wm.shell.flicker.layerBecomesVisible
import com.android.wm.shell.flicker.layerIsVisibleAtEnd
@@ -136,7 +136,7 @@ class EnterSplitScreenByDragFromShortcut(flicker: FlickerTest) : SplitScreenBase
fun getParams(): List<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
// TODO(b/176061063):The 3 buttons of nav bar do not exist in the hierarchy.
- supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL)
+ supportedNavigationModes = listOf(NavBar.MODE_GESTURAL)
)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromTaskbar.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromTaskbar.kt
index 795a2c4f43ba..da80c6f46976 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromTaskbar.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromTaskbar.kt
@@ -19,13 +19,13 @@ package com.android.wm.shell.flicker.splitscreen
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
+import android.tools.common.NavBar
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.service.PlatformConsts
import com.android.wm.shell.flicker.SPLIT_SCREEN_DIVIDER_COMPONENT
import com.android.wm.shell.flicker.appWindowBecomesVisible
import com.android.wm.shell.flicker.appWindowIsVisibleAtEnd
@@ -205,7 +205,7 @@ class EnterSplitScreenByDragFromTaskbar(flicker: FlickerTest) : SplitScreenBase(
@JvmStatic
fun getParams(): List<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL)
+ supportedNavigationModes = listOf(NavBar.MODE_GESTURAL)
)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenFromOverview.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenFromOverview.kt
index a9cbb7419417..c45387722a49 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenFromOverview.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenFromOverview.kt
@@ -19,11 +19,11 @@ package com.android.wm.shell.flicker.splitscreen
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import com.android.wm.shell.flicker.appWindowBecomesVisible
import com.android.wm.shell.flicker.layerBecomesVisible
import com.android.wm.shell.flicker.layerIsVisibleAtEnd
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenBase.kt
index 8c0a303189e1..7abdc06820d6 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenBase.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenBase.kt
@@ -17,8 +17,8 @@
package com.android.wm.shell.flicker.splitscreen
import android.content.Context
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
import com.android.server.wm.flicker.helpers.setRotation
import com.android.wm.shell.flicker.BaseTest
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenUtils.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenUtils.kt
index 4f8cfca5c872..7901f7502e2c 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenUtils.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenUtils.kt
@@ -19,6 +19,12 @@ package com.android.wm.shell.flicker.splitscreen
import android.app.Instrumentation
import android.graphics.Point
import android.os.SystemClock
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.datatypes.component.IComponentMatcher
+import android.tools.common.datatypes.component.IComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.traces.parsers.WindowManagerStateHelper
+import android.tools.device.traces.parsers.toFlickerComponent
import android.view.InputDevice
import android.view.MotionEvent
import android.view.ViewConfiguration
@@ -32,16 +38,9 @@ import com.android.server.wm.flicker.helpers.ImeAppHelper
import com.android.server.wm.flicker.helpers.NonResizeableAppHelper
import com.android.server.wm.flicker.helpers.NotificationAppHelper
import com.android.server.wm.flicker.helpers.SimpleAppHelper
-import com.android.server.wm.flicker.helpers.StandardAppHelper
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.component.matchers.IComponentMatcher
-import com.android.server.wm.traces.common.component.matchers.IComponentNameMatcher
-import com.android.server.wm.traces.parser.toFlickerComponent
-import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
import com.android.wm.shell.flicker.LAUNCHER_UI_PACKAGE_NAME
import com.android.wm.shell.flicker.SYSTEM_UI_PACKAGE_NAME
-import java.util.Collections
import org.junit.Assert.assertNotNull
internal object SplitScreenUtils {
@@ -129,18 +128,12 @@ internal object SplitScreenUtils {
// Find the second task in the upper right corner in split select mode by sorting
// 'left' in descending order and 'top' in ascending order.
- Collections.sort(
- snapshots,
- { t1: UiObject2, t2: UiObject2 ->
- t2.getVisibleBounds().left - t1.getVisibleBounds().left
- }
- )
- Collections.sort(
- snapshots,
- { t1: UiObject2, t2: UiObject2 ->
- t1.getVisibleBounds().top - t2.getVisibleBounds().top
- }
- )
+ snapshots.sortWith { t1: UiObject2, t2: UiObject2 ->
+ t2.getVisibleBounds().left - t1.getVisibleBounds().left
+ }
+ snapshots.sortWith { t1: UiObject2, t2: UiObject2 ->
+ t1.getVisibleBounds().top - t2.getVisibleBounds().top
+ }
snapshots[0].click()
} else {
tapl.workspace
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt
index c7b81d924a9b..fbb7c7159234 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt
@@ -19,14 +19,15 @@ package com.android.wm.shell.flicker.splitscreen
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
+import android.tools.common.NavBar
+import android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.helpers.WindowUtils
+import android.tools.device.traces.parsers.WindowManagerStateHelper
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.helpers.WindowUtils
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.service.PlatformConsts
-import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
import com.android.wm.shell.flicker.SPLIT_SCREEN_DIVIDER_COMPONENT
import com.android.wm.shell.flicker.appWindowIsVisibleAtEnd
import com.android.wm.shell.flicker.appWindowIsVisibleAtStart
@@ -133,7 +134,7 @@ class SwitchAppByDoubleTapDivider(flicker: FlickerTest) : SplitScreenBase(flicke
.waitForAndVerify()
}
- private fun isLandscape(rotation: PlatformConsts.Rotation): Boolean {
+ private fun isLandscape(rotation: Rotation): Boolean {
val displayBounds = WindowUtils.getDisplayBounds(rotation)
return displayBounds.width > displayBounds.height
}
@@ -205,7 +206,7 @@ class SwitchAppByDoubleTapDivider(flicker: FlickerTest) : SplitScreenBase(flicke
fun getParams(): List<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
// TODO(b/176061063):The 3 buttons of nav bar do not exist in the hierarchy.
- supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL)
+ supportedNavigationModes = listOf(NavBar.MODE_GESTURAL)
)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromAnotherApp.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromAnotherApp.kt
index 940e0e93d524..d675bfb0119d 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromAnotherApp.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromAnotherApp.kt
@@ -19,12 +19,12 @@ package com.android.wm.shell.flicker.splitscreen
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Presubmit
+import android.tools.common.NavBar
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.service.PlatformConsts
import com.android.wm.shell.flicker.appWindowBecomesVisible
import com.android.wm.shell.flicker.layerBecomesVisible
import com.android.wm.shell.flicker.splitAppLayerBoundsIsVisibleAtEnd
@@ -166,7 +166,7 @@ class SwitchBackToSplitFromAnotherApp(flicker: FlickerTest) : SplitScreenBase(fl
fun getParams(): List<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
// TODO(b/176061063):The 3 buttons of nav bar do not exist in the hierarchy.
- supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL)
+ supportedNavigationModes = listOf(NavBar.MODE_GESTURAL)
)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromHome.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromHome.kt
index 8c3bea8e6297..2855c71518eb 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromHome.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromHome.kt
@@ -19,13 +19,13 @@ package com.android.wm.shell.flicker.splitscreen
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Presubmit
+import android.tools.common.NavBar
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.service.PlatformConsts
import com.android.wm.shell.flicker.appWindowBecomesVisible
import com.android.wm.shell.flicker.layerBecomesVisible
import com.android.wm.shell.flicker.splitAppLayerBoundsIsVisibleAtEnd
@@ -179,7 +179,7 @@ class SwitchBackToSplitFromHome(flicker: FlickerTest) : SplitScreenBase(flicker)
fun getParams(): List<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
// TODO(b/176061063):The 3 buttons of nav bar do not exist in the hierarchy.
- supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL)
+ supportedNavigationModes = listOf(NavBar.MODE_GESTURAL)
)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromRecent.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromRecent.kt
index 06a1449f75ee..c29a917c4e7c 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromRecent.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromRecent.kt
@@ -19,13 +19,13 @@ package com.android.wm.shell.flicker.splitscreen
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Presubmit
+import android.tools.common.NavBar
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.service.PlatformConsts
import com.android.wm.shell.flicker.appWindowBecomesVisible
import com.android.wm.shell.flicker.layerBecomesVisible
import com.android.wm.shell.flicker.splitAppLayerBoundsIsVisibleAtEnd
@@ -179,7 +179,7 @@ class SwitchBackToSplitFromRecent(flicker: FlickerTest) : SplitScreenBase(flicke
fun getParams(): List<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
// TODO(b/176061063):The 3 buttons of nav bar do not exist in the hierarchy.
- supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL)
+ supportedNavigationModes = listOf(NavBar.MODE_GESTURAL)
)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairs.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairs.kt
index 193ab98cf191..4c96b3a319d5 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairs.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairs.kt
@@ -19,11 +19,11 @@ package com.android.wm.shell.flicker.splitscreen
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import com.android.wm.shell.flicker.SPLIT_SCREEN_DIVIDER_COMPONENT
import com.android.wm.shell.flicker.appWindowBecomesInvisible
import com.android.wm.shell.flicker.appWindowBecomesVisible
diff --git a/libs/WindowManager/Shell/tests/unittest/AndroidManifest.xml b/libs/WindowManager/Shell/tests/unittest/AndroidManifest.xml
index fac04614d945..47a116be1b66 100644
--- a/libs/WindowManager/Shell/tests/unittest/AndroidManifest.xml
+++ b/libs/WindowManager/Shell/tests/unittest/AndroidManifest.xml
@@ -20,6 +20,7 @@
package="com.android.wm.shell.tests">
<uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
+ <uses-permission android:name="android.permission.VIBRATE"/>
<application android:debuggable="true" android:largeHeap="true">
<uses-library android:name="android.test.mock" />
diff --git a/libs/WindowManager/Shell/tests/unittest/res/values/dimen.xml b/libs/WindowManager/Shell/tests/unittest/res/values/dimen.xml
index 27d40b2b25b2..aa1b24189274 100644
--- a/libs/WindowManager/Shell/tests/unittest/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/tests/unittest/res/values/dimen.xml
@@ -24,4 +24,6 @@
<dimen name="test_window_decor_bottom_outset">40dp</dimen>
<dimen name="test_window_decor_shadow_radius">5dp</dimen>
<dimen name="test_window_decor_resize_handle">10dp</dimen>
+ <dimen name="test_caption_menu_shadow_radius">4dp</dimen>
+ <dimen name="test_caption_menu_corner_radius">20dp</dimen>
</resources> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
index 8a5b4901ed96..5a4a44fde58d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
@@ -25,7 +25,6 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
@@ -40,7 +39,6 @@ import android.graphics.Point;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
-import android.os.IBinder;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.provider.Settings;
@@ -341,8 +339,7 @@ public class BackAnimationControllerTest extends ShellTestCase {
mController.setTriggerBack(true); // Fake trigger back
// In case the focus has been changed.
- IBinder token = mock(IBinder.class);
- mController.mFocusObserver.focusLost(token);
+ mController.mNavigationObserver.sendResult(null);
mShellExecutor.flushAll();
verify(mAnimatorCallback).onBackCancelled();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
index e8784d77be1b..bc0d93a6810a 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
@@ -475,6 +475,36 @@ public class CompatUIControllerTest extends ShellTestCase {
verify(mMockRestartDialogLayout).updateVisibility(true);
}
+ @Test
+ public void testRestartLayoutRecreatedIfNeeded() {
+ final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID,
+ /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN);
+ doReturn(true).when(mMockRestartDialogLayout)
+ .needsToBeRecreated(any(TaskInfo.class),
+ any(ShellTaskOrganizer.TaskListener.class));
+
+ mController.onCompatInfoChanged(taskInfo, mMockTaskListener);
+ mController.onCompatInfoChanged(taskInfo, mMockTaskListener);
+
+ verify(mMockRestartDialogLayout, times(2))
+ .createLayout(anyBoolean());
+ }
+
+ @Test
+ public void testRestartLayoutNotRecreatedIfNotNeeded() {
+ final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID,
+ /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN);
+ doReturn(false).when(mMockRestartDialogLayout)
+ .needsToBeRecreated(any(TaskInfo.class),
+ any(ShellTaskOrganizer.TaskListener.class));
+
+ mController.onCompatInfoChanged(taskInfo, mMockTaskListener);
+ mController.onCompatInfoChanged(taskInfo, mMockTaskListener);
+
+ verify(mMockRestartDialogLayout, times(1))
+ .createLayout(anyBoolean());
+ }
+
private static TaskInfo createTaskInfo(int displayId, int taskId, boolean hasSizeCompat,
@CameraCompatControlState int cameraCompatControlState) {
RunningTaskInfo taskInfo = new RunningTaskInfo();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java
index b6dbcf204364..523cb6629d9a 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java
@@ -48,7 +48,6 @@ import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ShellExecutor;
-import com.android.wm.shell.splitscreen.SplitScreenController;
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
@@ -82,7 +81,7 @@ public class DragAndDropControllerTest extends ShellTestCase {
@Mock
private ShellExecutor mMainExecutor;
@Mock
- private SplitScreenController mSplitScreenController;
+ private WindowManager mWindowManager;
private DragAndDropController mController;
@@ -100,11 +99,6 @@ public class DragAndDropControllerTest extends ShellTestCase {
}
@Test
- public void instantiateController_registerConfigChangeListener() {
- verify(mShellController, times(1)).addConfigurationChangeListener(any());
- }
-
- @Test
public void testIgnoreNonDefaultDisplays() {
final int nonDefaultDisplayId = 12345;
final View dragLayout = mock(View.class);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
index ed0ac5f1cdca..3901dabcaec8 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
@@ -284,41 +284,6 @@ public class SplitTransitionTests extends ShellTestCase {
@Test
@UiThreadTest
- public void testDismissFromBeingOccluded() {
- enterSplit();
-
- ActivityManager.RunningTaskInfo normalTask = new TestRunningTaskInfoBuilder()
- .setWindowingMode(WINDOWING_MODE_FULLSCREEN)
- .build();
-
- // Create a request to bring a normal task forward
- TransitionRequestInfo request =
- new TransitionRequestInfo(TRANSIT_TO_FRONT, normalTask, null);
- IBinder transition = mock(IBinder.class);
- WindowContainerTransaction result = mStageCoordinator.handleRequest(transition, request);
-
- assertTrue(containsSplitExit(result));
-
- // make sure we haven't made any local changes yet (need to wait until transition is ready)
- assertTrue(mStageCoordinator.isSplitScreenVisible());
-
- // simulate the transition
- TransitionInfo info = new TransitionInfoBuilder(TRANSIT_TO_FRONT, 0)
- .addChange(TRANSIT_TO_FRONT, normalTask)
- .addChange(TRANSIT_TO_BACK, mMainChild)
- .addChange(TRANSIT_TO_BACK, mSideChild)
- .build();
- mMainStage.onTaskVanished(mMainChild);
- mSideStage.onTaskVanished(mSideChild);
- mStageCoordinator.startAnimation(transition, info,
- mock(SurfaceControl.Transaction.class),
- mock(SurfaceControl.Transaction.class),
- mock(Transitions.TransitionFinishCallback.class));
- assertFalse(mStageCoordinator.isSplitScreenVisible());
- }
-
- @Test
- @UiThreadTest
public void testDismissFromMultiWindowSupport() {
enterSplit();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
index 0bb809d354dc..2e2e49e40030 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
@@ -134,6 +134,7 @@ public class StageCoordinatorTests extends ShellTestCase {
when(mSplitLayout.getBounds2()).thenReturn(mBounds2);
when(mSplitLayout.getRootBounds()).thenReturn(mRootBounds);
when(mSplitLayout.isLandscape()).thenReturn(false);
+ when(mSplitLayout.applyTaskChanges(any(), any(), any())).thenReturn(true);
mRootTask = new TestRunningTaskInfoBuilder().build();
mRootLeash = new SurfaceControl.Builder(mSurfaceSession).setName("test").build();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
index bf62acfc47a1..11fda8bf7bbc 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
@@ -24,8 +24,8 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
-import static com.android.wm.shell.startingsurface.SplashscreenContentDrawer.MAX_ANIMATION_DURATION;
-import static com.android.wm.shell.startingsurface.SplashscreenContentDrawer.MINIMAL_ANIMATION_DURATION;
+import static com.android.wm.shell.startingsurface.StartingSurfaceDrawer.MAX_ANIMATION_DURATION;
+import static com.android.wm.shell.startingsurface.StartingSurfaceDrawer.MINIMAL_ANIMATION_DURATION;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
@@ -56,9 +56,11 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.UserHandle;
import android.testing.TestableContext;
+import android.view.Display;
import android.view.IWindowSession;
import android.view.InsetsState;
import android.view.Surface;
+import android.view.View;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.WindowMetrics;
@@ -104,7 +106,36 @@ public class StartingSurfaceDrawerTests extends ShellTestCase {
private ShellExecutor mTestExecutor;
private final TestableContext mTestContext = new TestContext(
InstrumentationRegistry.getInstrumentation().getTargetContext());
- StartingSurfaceDrawer mStartingSurfaceDrawer;
+ TestStartingSurfaceDrawer mStartingSurfaceDrawer;
+
+ static final class TestStartingSurfaceDrawer extends StartingSurfaceDrawer{
+ int mAddWindowForTask = 0;
+
+ TestStartingSurfaceDrawer(Context context, ShellExecutor splashScreenExecutor,
+ IconProvider iconProvider, TransactionPool pool) {
+ super(context, splashScreenExecutor, iconProvider, pool);
+ }
+
+ @Override
+ protected boolean addWindow(int taskId, IBinder appToken, View view, Display display,
+ WindowManager.LayoutParams params, int suggestType) {
+ // listen for addView
+ mAddWindowForTask = taskId;
+ saveSplashScreenRecord(appToken, taskId, view, suggestType);
+ // Do not wait for background color
+ return false;
+ }
+
+ @Override
+ protected void removeWindowSynced(StartingWindowRemovalInfo removalInfo,
+ boolean immediately) {
+ // listen for removeView
+ if (mAddWindowForTask == removalInfo.taskId) {
+ mAddWindowForTask = 0;
+ }
+ mStartingWindowRecords.remove(removalInfo.taskId);
+ }
+ }
private static class TestContext extends TestableContext {
TestContext(Context context) {
@@ -134,51 +165,44 @@ public class StartingSurfaceDrawerTests extends ShellTestCase {
doReturn(metrics).when(mMockWindowManager).getMaximumWindowMetrics();
doNothing().when(mMockWindowManager).addView(any(), any());
mTestExecutor = new HandlerExecutor(mTestHandler);
- mStartingSurfaceDrawer = new StartingSurfaceDrawer(mTestContext, mTestExecutor,
- mIconProvider, mTransactionPool);
mStartingSurfaceDrawer = spy(
- new StartingSurfaceDrawer(mTestContext, mTestExecutor, mIconProvider,
+ new TestStartingSurfaceDrawer(mTestContext, mTestExecutor, mIconProvider,
mTransactionPool));
- spyOn(mStartingSurfaceDrawer.mSplashscreenWindowCreator);
- spyOn(mStartingSurfaceDrawer.mWindowRecords);
- spyOn(mStartingSurfaceDrawer.mWindowlessRecords);
}
@Test
public void testAddSplashScreenSurface() {
final int taskId = 1;
final StartingWindowInfo windowInfo =
- createWindowInfo(taskId, android.R.style.Theme, mBinder);
- mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo,
+ createWindowInfo(taskId, android.R.style.Theme);
+ mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder,
STARTING_WINDOW_TYPE_SPLASH_SCREEN);
waitHandlerIdle(mTestHandler);
- verify(mStartingSurfaceDrawer.mSplashscreenWindowCreator).addWindow(
- eq(taskId), eq(mBinder), any(), any(), any(),
+ verify(mStartingSurfaceDrawer).addWindow(eq(taskId), eq(mBinder), any(), any(), any(),
eq(STARTING_WINDOW_TYPE_SPLASH_SCREEN));
+ assertEquals(mStartingSurfaceDrawer.mAddWindowForTask, taskId);
StartingWindowRemovalInfo removalInfo = new StartingWindowRemovalInfo();
removalInfo.taskId = windowInfo.taskInfo.taskId;
mStartingSurfaceDrawer.removeStartingWindow(removalInfo);
waitHandlerIdle(mTestHandler);
- verify(mStartingSurfaceDrawer.mWindowRecords).removeWindow(any(), eq(false));
- assertEquals(mStartingSurfaceDrawer.mWindowRecords.recordSize(), 0);
+ verify(mStartingSurfaceDrawer).removeWindowSynced(any(), eq(false));
+ assertEquals(mStartingSurfaceDrawer.mAddWindowForTask, 0);
}
@Test
public void testFallbackDefaultTheme() {
final int taskId = 1;
final StartingWindowInfo windowInfo =
- createWindowInfo(taskId, 0, mBinder);
+ createWindowInfo(taskId, 0);
final int[] theme = new int[1];
doAnswer(invocation -> theme[0] = (Integer) invocation.callRealMethod())
- .when(mStartingSurfaceDrawer.mSplashscreenWindowCreator)
- .getSplashScreenTheme(eq(0), any());
+ .when(mStartingSurfaceDrawer).getSplashScreenTheme(eq(0), any());
- mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo,
+ mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder,
STARTING_WINDOW_TYPE_SPLASH_SCREEN);
waitHandlerIdle(mTestHandler);
- verify(mStartingSurfaceDrawer.mSplashscreenWindowCreator)
- .getSplashScreenTheme(eq(0), any());
+ verify(mStartingSurfaceDrawer).getSplashScreenTheme(eq(0), any());
assertNotEquals(theme[0], 0);
}
@@ -217,7 +241,7 @@ public class StartingSurfaceDrawerTests extends ShellTestCase {
public void testRemoveTaskSnapshotWithImeSurfaceWhenOnImeDrawn() throws Exception {
final int taskId = 1;
final StartingWindowInfo windowInfo =
- createWindowInfo(taskId, android.R.style.Theme, mBinder);
+ createWindowInfo(taskId, android.R.style.Theme);
TaskSnapshot snapshot = createTaskSnapshot(100, 100, new Point(100, 100),
new Rect(0, 0, 0, 50), true /* hasImeSurface */);
final IWindowSession session = WindowManagerGlobal.getWindowSession();
@@ -246,7 +270,7 @@ public class StartingSurfaceDrawerTests extends ShellTestCase {
when(TaskSnapshotWindow.create(eq(windowInfo), eq(mBinder), eq(snapshot), any(),
any())).thenReturn(mockSnapshotWindow);
// Simulate a task snapshot window created with IME snapshot shown.
- mStartingSurfaceDrawer.makeTaskSnapshotWindow(windowInfo, snapshot);
+ mStartingSurfaceDrawer.makeTaskSnapshotWindow(windowInfo, mBinder, snapshot);
waitHandlerIdle(mTestHandler);
// Verify the task snapshot with IME snapshot will be removed when received the real IME
@@ -254,36 +278,27 @@ public class StartingSurfaceDrawerTests extends ShellTestCase {
// makeTaskSnapshotWindow shall call removeWindowSynced before there add a new
// StartingWindowRecord for the task.
mStartingSurfaceDrawer.onImeDrawnOnTask(1);
- verify(mStartingSurfaceDrawer.mWindowRecords, times(2))
- .removeWindow(any(), eq(true));
+ verify(mStartingSurfaceDrawer, times(2))
+ .removeWindowSynced(any(), eq(true));
}
}
@Test
public void testClearAllWindows() {
final int taskId = 1;
- mStartingSurfaceDrawer.mWindowRecords.addRecord(taskId,
- new StartingSurfaceDrawer.StartingWindowRecord() {
- @Override
- public void removeIfPossible(StartingWindowRemovalInfo info,
- boolean immediately) {
-
- }
- });
- mStartingSurfaceDrawer.mWindowlessRecords.addRecord(taskId,
- new StartingSurfaceDrawer.StartingWindowRecord() {
- @Override
- public void removeIfPossible(StartingWindowRemovalInfo info,
- boolean immediately) {
+ final StartingWindowInfo windowInfo =
+ createWindowInfo(taskId, android.R.style.Theme);
+ mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder,
+ STARTING_WINDOW_TYPE_SPLASH_SCREEN);
+ waitHandlerIdle(mTestHandler);
+ verify(mStartingSurfaceDrawer).addWindow(eq(taskId), eq(mBinder), any(), any(), any(),
+ eq(STARTING_WINDOW_TYPE_SPLASH_SCREEN));
+ assertEquals(mStartingSurfaceDrawer.mAddWindowForTask, taskId);
- }
- });
mStartingSurfaceDrawer.clearAllWindows();
waitHandlerIdle(mTestHandler);
- verify(mStartingSurfaceDrawer.mWindowRecords).removeWindow(any(), eq(true));
- assertEquals(mStartingSurfaceDrawer.mWindowRecords.recordSize(), 0);
- verify(mStartingSurfaceDrawer.mWindowlessRecords).removeWindow(any(), eq(true));
- assertEquals(mStartingSurfaceDrawer.mWindowlessRecords.recordSize(), 0);
+ verify(mStartingSurfaceDrawer).removeWindowSynced(any(), eq(true));
+ assertEquals(mStartingSurfaceDrawer.mStartingWindowRecords.size(), 0);
}
@Test
@@ -336,7 +351,7 @@ public class StartingSurfaceDrawerTests extends ShellTestCase {
longAppDuration, longAppDuration));
}
- private StartingWindowInfo createWindowInfo(int taskId, int themeResId, IBinder appToken) {
+ private StartingWindowInfo createWindowInfo(int taskId, int themeResId) {
StartingWindowInfo windowInfo = new StartingWindowInfo();
final ActivityInfo info = new ActivityInfo();
info.applicationInfo = new ApplicationInfo();
@@ -345,7 +360,6 @@ public class StartingSurfaceDrawerTests extends ShellTestCase {
final ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo();
taskInfo.topActivityInfo = info;
taskInfo.taskId = taskId;
- windowInfo.appToken = appToken;
windowInfo.targetActivityInfo = info;
windowInfo.taskInfo = taskInfo;
windowInfo.topOpaqueWindowInsetsState = new InsetsState();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
index 6c9b186b7ede..e63bbeb05575 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
@@ -563,6 +563,33 @@ public class ShellTransitionTests extends ShellTestCase {
assertEquals(0, mDefaultHandler.activeCount());
}
+
+ @Test
+ public void testTransitionMergingOnFinish() {
+ final Transitions transitions = createTestTransitions();
+ transitions.replaceDefaultHandlerForTest(mDefaultHandler);
+
+ // The current transition.
+ final IBinder transitToken1 = new Binder();
+ requestStartTransition(transitions, transitToken1);
+ onTransitionReady(transitions, transitToken1);
+
+ // The next ready transition.
+ final IBinder transitToken2 = new Binder();
+ requestStartTransition(transitions, transitToken2);
+ onTransitionReady(transitions, transitToken2);
+
+ // The non-ready merge candidate.
+ final IBinder transitTokenNotReady = new Binder();
+ requestStartTransition(transitions, transitTokenNotReady);
+
+ mDefaultHandler.setSimulateMerge(true);
+ mDefaultHandler.mFinishes.get(0).onTransitionFinished(null /* wct */, null /* wctCB */);
+
+ // Make sure that the non-ready transition is not merged.
+ assertEquals(0, mDefaultHandler.mergeCount());
+ }
+
@Test
public void testTransitionOrderMatchesCore() {
Transitions transitions = createTestTransitions();
@@ -1036,6 +1063,21 @@ public class ShellTransitionTests extends ShellTestCase {
}
}
+ private static void requestStartTransition(Transitions transitions, IBinder token) {
+ transitions.requestStartTransition(token,
+ new TransitionRequestInfo(TRANSIT_OPEN, null /* trigger */, null /* remote */));
+ }
+
+ private static void onTransitionReady(Transitions transitions, IBinder token) {
+ transitions.onTransitionReady(token, createTransitionInfo(),
+ mock(SurfaceControl.Transaction.class), mock(SurfaceControl.Transaction.class));
+ }
+
+ private static TransitionInfo createTransitionInfo() {
+ return new TransitionInfoBuilder(TRANSIT_OPEN)
+ .addChange(TRANSIT_OPEN).addChange(TRANSIT_CLOSE).build();
+ }
+
private static SurfaceControl createMockSurface(boolean valid) {
SurfaceControl sc = mock(SurfaceControl.class);
doReturn(valid).when(sc).isValid();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java
index 355072116cb1..1d1aa795173c 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java
@@ -49,6 +49,7 @@ import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.desktopmode.DesktopModeController;
import com.android.wm.shell.desktopmode.DesktopTasksController;
+import com.android.wm.shell.splitscreen.SplitScreenController;
import org.junit.Before;
import org.junit.Test;
@@ -73,6 +74,7 @@ public class DesktopModeWindowDecorViewModelTests extends ShellTestCase {
@Mock private Choreographer mMainChoreographer;
@Mock private ShellTaskOrganizer mTaskOrganizer;
@Mock private DisplayController mDisplayController;
+ @Mock private SplitScreenController mSplitScreenController;
@Mock private SyncTransactionQueue mSyncQueue;
@Mock private DesktopModeController mDesktopModeController;
@Mock private DesktopTasksController mDesktopTasksController;
@@ -98,6 +100,7 @@ public class DesktopModeWindowDecorViewModelTests extends ShellTestCase {
mSyncQueue,
Optional.of(mDesktopModeController),
Optional.of(mDesktopTasksController),
+ Optional.of(mSplitScreenController),
mDesktopModeWindowDecorFactory,
mMockInputMonitorFactory
);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/TaskPositionerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/TaskPositionerTest.kt
index f185a8a80719..8f66f4e7e47b 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/TaskPositionerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/TaskPositionerTest.kt
@@ -8,6 +8,8 @@ import android.testing.AndroidTestingRunner
import android.window.WindowContainerToken
import android.window.WindowContainerTransaction.Change.CHANGE_DRAG_RESIZING
import androidx.test.filters.SmallTest
+import com.android.wm.shell.common.DisplayController
+import com.android.wm.shell.common.DisplayLayout
import com.android.wm.shell.ShellTaskOrganizer
import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.windowdecor.TaskPositioner.CTRL_TYPE_RIGHT
@@ -45,6 +47,11 @@ class TaskPositionerTest : ShellTestCase() {
@Mock
private lateinit var taskBinder: IBinder
+ @Mock
+ private lateinit var mockDisplayController: DisplayController
+ @Mock
+ private lateinit var mockDisplayLayout: DisplayLayout
+
private lateinit var taskPositioner: TaskPositioner
@Before
@@ -54,12 +61,21 @@ class TaskPositionerTest : ShellTestCase() {
taskPositioner = TaskPositioner(
mockShellTaskOrganizer,
mockWindowDecoration,
+ mockDisplayController,
mockDragStartListener
)
+
`when`(taskToken.asBinder()).thenReturn(taskBinder)
+ `when`(mockDisplayController.getDisplayLayout(DISPLAY_ID)).thenReturn(mockDisplayLayout)
+ `when`(mockDisplayLayout.densityDpi()).thenReturn(DENSITY_DPI)
+
mockWindowDecoration.mTaskInfo = ActivityManager.RunningTaskInfo().apply {
taskId = TASK_ID
token = taskToken
+ minWidth = MIN_WIDTH
+ minHeight = MIN_HEIGHT
+ defaultMinSize = DEFAULT_MIN
+ displayId = DISPLAY_ID
configuration.windowConfiguration.bounds = STARTING_BOUNDS
}
}
@@ -209,8 +225,239 @@ class TaskPositionerTest : ShellTestCase() {
})
}
+ @Test
+ fun testDragResize_resize_setBoundsDoesNotChangeHeightWhenLessThanMin() {
+ taskPositioner.onDragPositioningStart(
+ CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, // Resize right and top
+ STARTING_BOUNDS.right.toFloat(),
+ STARTING_BOUNDS.top.toFloat()
+ )
+
+ // Resize to width of 95px and height of 5px with min width of 10px
+ val newX = STARTING_BOUNDS.right.toFloat() - 5
+ val newY = STARTING_BOUNDS.top.toFloat() + 95
+ taskPositioner.onDragPositioningMove(
+ newX,
+ newY
+ )
+
+ taskPositioner.onDragPositioningEnd(newX, newY)
+
+ verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
+ return@argThat wct.changes.any { (token, change) ->
+ token == taskBinder &&
+ ((change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS)
+ != 0) && change.configuration.windowConfiguration.bounds.top ==
+ STARTING_BOUNDS.top &&
+ change.configuration.windowConfiguration.bounds.bottom ==
+ STARTING_BOUNDS.bottom
+ }
+ })
+ }
+
+ @Test
+ fun testDragResize_resize_setBoundsDoesNotChangeWidthWhenLessThanMin() {
+ taskPositioner.onDragPositioningStart(
+ CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, // Resize right and top
+ STARTING_BOUNDS.right.toFloat(),
+ STARTING_BOUNDS.top.toFloat()
+ )
+
+ // Resize to height of 95px and width of 5px with min width of 10px
+ val newX = STARTING_BOUNDS.right.toFloat() - 95
+ val newY = STARTING_BOUNDS.top.toFloat() + 5
+ taskPositioner.onDragPositioningMove(
+ newX,
+ newY
+ )
+
+ taskPositioner.onDragPositioningEnd(newX, newY)
+
+ verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
+ return@argThat wct.changes.any { (token, change) ->
+ token == taskBinder &&
+ ((change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS)
+ != 0) && change.configuration.windowConfiguration.bounds.right ==
+ STARTING_BOUNDS.right &&
+ change.configuration.windowConfiguration.bounds.left ==
+ STARTING_BOUNDS.left
+ }
+ })
+ }
+
+ @Test
+ fun testDragResize_resize_setBoundsDoesNotChangeHeightWhenNegative() {
+ taskPositioner.onDragPositioningStart(
+ CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, // Resize right and top
+ STARTING_BOUNDS.right.toFloat(),
+ STARTING_BOUNDS.top.toFloat()
+ )
+
+ // Resize to height of -5px and width of 95px
+ val newX = STARTING_BOUNDS.right.toFloat() - 5
+ val newY = STARTING_BOUNDS.top.toFloat() + 105
+ taskPositioner.onDragPositioningMove(
+ newX,
+ newY
+ )
+
+ taskPositioner.onDragPositioningEnd(newX, newY)
+
+ verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
+ return@argThat wct.changes.any { (token, change) ->
+ token == taskBinder &&
+ ((change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS)
+ != 0) && change.configuration.windowConfiguration.bounds.top ==
+ STARTING_BOUNDS.top &&
+ change.configuration.windowConfiguration.bounds.bottom ==
+ STARTING_BOUNDS.bottom
+ }
+ })
+ }
+
+ @Test
+ fun testDragResize_resize_setBoundsDoesNotChangeWidthWhenNegative() {
+ taskPositioner.onDragPositioningStart(
+ CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, // Resize right and top
+ STARTING_BOUNDS.right.toFloat(),
+ STARTING_BOUNDS.top.toFloat()
+ )
+
+ // Resize to width of -5px and height of 95px
+ val newX = STARTING_BOUNDS.right.toFloat() - 105
+ val newY = STARTING_BOUNDS.top.toFloat() + 5
+ taskPositioner.onDragPositioningMove(
+ newX,
+ newY
+ )
+
+ taskPositioner.onDragPositioningEnd(newX, newY)
+
+ verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
+ return@argThat wct.changes.any { (token, change) ->
+ token == taskBinder &&
+ ((change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS)
+ != 0) && change.configuration.windowConfiguration.bounds.right ==
+ STARTING_BOUNDS.right &&
+ change.configuration.windowConfiguration.bounds.left ==
+ STARTING_BOUNDS.left
+ }
+ })
+ }
+
+ @Test
+ fun testDragResize_resize_setBoundsRunsWhenResizeBoundsValid() {
+ taskPositioner.onDragPositioningStart(
+ CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, // Resize right and top
+ STARTING_BOUNDS.right.toFloat(),
+ STARTING_BOUNDS.top.toFloat()
+ )
+
+ // Shrink to height 20px and width 20px with both min height/width equal to 10px
+ val newX = STARTING_BOUNDS.right.toFloat() - 80
+ val newY = STARTING_BOUNDS.top.toFloat() + 80
+ taskPositioner.onDragPositioningMove(
+ newX,
+ newY
+ )
+
+ taskPositioner.onDragPositioningEnd(newX, newY)
+
+ verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
+ return@argThat wct.changes.any { (token, change) ->
+ token == taskBinder &&
+ ((change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0)
+ }
+ })
+ }
+
+ @Test
+ fun testDragResize_resize_setBoundsDoesNotRunWithNegativeHeightAndWidth() {
+ taskPositioner.onDragPositioningStart(
+ CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, // Resize right and top
+ STARTING_BOUNDS.right.toFloat(),
+ STARTING_BOUNDS.top.toFloat()
+ )
+
+ // Shrink to height 5px and width 5px with both min height/width equal to 10px
+ val newX = STARTING_BOUNDS.right.toFloat() - 95
+ val newY = STARTING_BOUNDS.top.toFloat() + 95
+ taskPositioner.onDragPositioningMove(
+ newX,
+ newY
+ )
+
+ taskPositioner.onDragPositioningEnd(newX, newY)
+
+ verify(mockShellTaskOrganizer, never()).applyTransaction(argThat { wct ->
+ return@argThat wct.changes.any { (token, change) ->
+ token == taskBinder &&
+ ((change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0)
+ }
+ })
+ }
+
+ @Test
+ fun testDragResize_resize_useDefaultMinWhenMinWidthInvalid() {
+ mockWindowDecoration.mTaskInfo.minWidth = -1
+
+ taskPositioner.onDragPositioningStart(
+ CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, // Resize right and top
+ STARTING_BOUNDS.right.toFloat(),
+ STARTING_BOUNDS.top.toFloat()
+ )
+
+ // Shrink to width and height of 3px with invalid minWidth = -1 and defaultMinSize = 5px
+ val newX = STARTING_BOUNDS.right.toFloat() - 97
+ val newY = STARTING_BOUNDS.top.toFloat() + 97
+ taskPositioner.onDragPositioningMove(
+ newX,
+ newY
+ )
+
+ taskPositioner.onDragPositioningEnd(newX, newY)
+
+ verify(mockShellTaskOrganizer, never()).applyTransaction(argThat { wct ->
+ return@argThat wct.changes.any { (token, change) ->
+ token == taskBinder &&
+ ((change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0)
+ }
+ })
+ }
+
+ @Test
+ fun testDragResize_resize_useMinWidthWhenValid() {
+ taskPositioner.onDragPositioningStart(
+ CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, // Resize right and top
+ STARTING_BOUNDS.right.toFloat(),
+ STARTING_BOUNDS.top.toFloat()
+ )
+
+ // Shrink to width and height of 7px with valid minWidth = 10px and defaultMinSize = 5px
+ val newX = STARTING_BOUNDS.right.toFloat() - 93
+ val newY = STARTING_BOUNDS.top.toFloat() + 93
+ taskPositioner.onDragPositioningMove(
+ newX,
+ newY
+ )
+
+ taskPositioner.onDragPositioningEnd(newX, newY)
+
+ verify(mockShellTaskOrganizer, never()).applyTransaction(argThat { wct ->
+ return@argThat wct.changes.any { (token, change) ->
+ token == taskBinder &&
+ ((change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0)
+ }
+ })
+ }
+
companion object {
private const val TASK_ID = 5
+ private const val MIN_WIDTH = 10
+ private const val MIN_HEIGHT = 10
+ private const val DENSITY_DPI = 20
+ private const val DEFAULT_MIN = 40
+ private const val DISPLAY_ID = 1
private val STARTING_BOUNDS = Rect(0, 0, 100, 100)
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
index b80edcece512..7e39b5b8f2ce 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
@@ -108,6 +108,8 @@ public class WindowDecorationTests extends ShellTestCase {
private SurfaceControl.Transaction mMockSurfaceControlAddWindowT;
private WindowDecoration.RelayoutParams mRelayoutParams = new WindowDecoration.RelayoutParams();
private int mCaptionMenuWidthId;
+ private int mCaptionMenuShadowRadiusId;
+ private int mCaptionMenuCornerRadiusId;
@Before
public void setUp() {
@@ -118,6 +120,8 @@ public class WindowDecorationTests extends ShellTestCase {
mRelayoutParams.mLayoutResId = 0;
mRelayoutParams.mCaptionHeightId = R.dimen.test_freeform_decor_caption_height;
mCaptionMenuWidthId = R.dimen.test_freeform_decor_caption_menu_width;
+ mCaptionMenuShadowRadiusId = R.dimen.test_caption_menu_shadow_radius;
+ mCaptionMenuCornerRadiusId = R.dimen.test_caption_menu_corner_radius;
mRelayoutParams.mShadowRadiusId = R.dimen.test_window_decor_shadow_radius;
doReturn(mMockSurfaceControlViewHost).when(mMockSurfaceControlViewHostFactory)
@@ -431,7 +435,19 @@ public class WindowDecorationTests extends ShellTestCase {
verify(additionalWindowSurfaceBuilder).setParent(decorContainerSurface);
verify(additionalWindowSurfaceBuilder).build();
verify(mMockSurfaceControlAddWindowT).setPosition(additionalWindowSurface, 20, 40);
- verify(mMockSurfaceControlAddWindowT).setWindowCrop(additionalWindowSurface, 442, 74);
+ final int width = WindowDecoration.loadDimensionPixelSize(
+ mContext.getResources(), mCaptionMenuWidthId);
+ final int height = WindowDecoration.loadDimensionPixelSize(
+ mContext.getResources(), mRelayoutParams.mCaptionHeightId);
+ verify(mMockSurfaceControlAddWindowT).setWindowCrop(additionalWindowSurface, width, height);
+ final int shadowRadius = WindowDecoration.loadDimensionPixelSize(mContext.getResources(),
+ mCaptionMenuShadowRadiusId);
+ verify(mMockSurfaceControlAddWindowT)
+ .setShadowRadius(additionalWindowSurface, shadowRadius);
+ final int cornerRadius = WindowDecoration.loadDimensionPixelSize(mContext.getResources(),
+ mCaptionMenuCornerRadiusId);
+ verify(mMockSurfaceControlAddWindowT)
+ .setCornerRadius(additionalWindowSurface, cornerRadius);
verify(mMockSurfaceControlAddWindowT).show(additionalWindowSurface);
verify(mMockSurfaceControlViewHostFactory, Mockito.times(2))
.create(any(), eq(defaultDisplay), any());
@@ -559,13 +575,15 @@ public class WindowDecorationTests extends ShellTestCase {
int y = mRelayoutParams.mCaptionY;
int width = loadDimensionPixelSize(resources, mCaptionMenuWidthId);
int height = loadDimensionPixelSize(resources, mRelayoutParams.mCaptionHeightId);
+ int shadowRadius = loadDimensionPixelSize(resources, mCaptionMenuShadowRadiusId);
+ int cornerRadius = loadDimensionPixelSize(resources, mCaptionMenuCornerRadiusId);
String name = "Test Window";
WindowDecoration.AdditionalWindow additionalWindow =
addWindow(R.layout.desktop_mode_decor_handle_menu, name,
mMockSurfaceControlAddWindowT,
x - mRelayoutResult.mDecorContainerOffsetX,
y - mRelayoutResult.mDecorContainerOffsetY,
- width, height, 10);
+ width, height, shadowRadius, cornerRadius);
return additionalWindow;
}
}
diff --git a/libs/dream/OWNERS b/libs/dream/OWNERS
new file mode 100644
index 000000000000..a4b0127d23b1
--- /dev/null
+++ b/libs/dream/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/dreams/OWNERS \ No newline at end of file
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index bcbe706d71a3..7228b895ebc4 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -332,11 +332,13 @@ cc_defaults {
"jni/android_graphics_Matrix.cpp",
"jni/android_graphics_Picture.cpp",
"jni/android_graphics_DisplayListCanvas.cpp",
+ "jni/android_graphics_Mesh.cpp",
"jni/android_graphics_RenderNode.cpp",
"jni/android_nio_utils.cpp",
"jni/android_util_PathParser.cpp",
"jni/Bitmap.cpp",
+ "jni/BufferUtils.cpp",
"jni/HardwareBufferHelpers.cpp",
"jni/BitmapFactory.cpp",
"jni/ByteBufferStreamAdaptor.cpp",
@@ -351,7 +353,6 @@ cc_defaults {
"jni/ImageDecoder.cpp",
"jni/Interpolator.cpp",
"jni/MeshSpecification.cpp",
- "jni/Mesh.cpp",
"jni/MaskFilter.cpp",
"jni/NinePatch.cpp",
"jni/NinePatchPeeker.cpp",
@@ -374,6 +375,7 @@ cc_defaults {
"jni/text/LineBreaker.cpp",
"jni/text/MeasuredText.cpp",
"jni/text/TextShaper.cpp",
+ "jni/text/GraphemeBreak.cpp",
],
header_libs: [
@@ -538,6 +540,7 @@ cc_defaults {
"Interpolator.cpp",
"LightingInfo.cpp",
"Matrix.cpp",
+ "Mesh.cpp",
"MemoryPolicy.cpp",
"PathParser.cpp",
"Properties.cpp",
diff --git a/libs/hwui/DisplayListOps.in b/libs/hwui/DisplayListOps.in
index e2127efca716..a18ba1c633b9 100644
--- a/libs/hwui/DisplayListOps.in
+++ b/libs/hwui/DisplayListOps.in
@@ -52,4 +52,5 @@ X(DrawShadowRec)
X(DrawVectorDrawable)
X(DrawRippleDrawable)
X(DrawWebView)
-X(DrawMesh)
+X(DrawSkMesh)
+X(DrawMesh) \ No newline at end of file
diff --git a/libs/hwui/MemoryPolicy.h b/libs/hwui/MemoryPolicy.h
index 2f0f7f506447..41ced8cebf83 100644
--- a/libs/hwui/MemoryPolicy.h
+++ b/libs/hwui/MemoryPolicy.h
@@ -53,8 +53,8 @@ struct MemoryPolicy {
// Whether or not to only purge scratch resources when triggering UI Hidden or background
// collection
bool purgeScratchOnly = true;
- // Whether or not to trigger releasing GPU context when all contexts are stopped
- bool releaseContextOnStoppedOnly = true;
+ // EXPERIMENTAL: Whether or not to trigger releasing GPU context when all contexts are stopped
+ bool releaseContextOnStoppedOnly = false;
};
const MemoryPolicy& loadMemoryPolicy();
diff --git a/libs/hwui/Mesh.cpp b/libs/hwui/Mesh.cpp
new file mode 100644
index 000000000000..e59bc9565a59
--- /dev/null
+++ b/libs/hwui/Mesh.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Mesh.h"
+
+#include <GLES/gl.h>
+#include <SkMesh.h>
+
+#include "SafeMath.h"
+
+static size_t min_vcount_for_mode(SkMesh::Mode mode) {
+ switch (mode) {
+ case SkMesh::Mode::kTriangles:
+ return 3;
+ case SkMesh::Mode::kTriangleStrip:
+ return 3;
+ }
+}
+
+// Re-implementation of SkMesh::validate to validate user side that their mesh is valid.
+std::tuple<bool, SkString> Mesh::validate() {
+#define FAIL_MESH_VALIDATE(...) return std::make_tuple(false, SkStringPrintf(__VA_ARGS__))
+ if (!mMeshSpec) {
+ FAIL_MESH_VALIDATE("MeshSpecification is required.");
+ }
+ if (mVertexBufferData.empty()) {
+ FAIL_MESH_VALIDATE("VertexBuffer is required.");
+ }
+
+ auto meshStride = mMeshSpec->stride();
+ auto meshMode = SkMesh::Mode(mMode);
+ SafeMath sm;
+ size_t vsize = sm.mul(meshStride, mVertexCount);
+ if (sm.add(vsize, mVertexOffset) > mVertexBufferData.size()) {
+ FAIL_MESH_VALIDATE(
+ "The vertex buffer offset and vertex count reads beyond the end of the"
+ " vertex buffer.");
+ }
+
+ if (mVertexOffset % meshStride != 0) {
+ FAIL_MESH_VALIDATE("The vertex offset (%zu) must be a multiple of the vertex stride (%zu).",
+ mVertexOffset, meshStride);
+ }
+
+ if (size_t uniformSize = mMeshSpec->uniformSize()) {
+ if (!mBuilder->fUniforms || mBuilder->fUniforms->size() < uniformSize) {
+ FAIL_MESH_VALIDATE("The uniform data is %zu bytes but must be at least %zu.",
+ mBuilder->fUniforms->size(), uniformSize);
+ }
+ }
+
+ auto modeToStr = [](SkMesh::Mode m) {
+ switch (m) {
+ case SkMesh::Mode::kTriangles:
+ return "triangles";
+ case SkMesh::Mode::kTriangleStrip:
+ return "triangle-strip";
+ }
+ };
+ if (!mIndexBufferData.empty()) {
+ if (mIndexCount < min_vcount_for_mode(meshMode)) {
+ FAIL_MESH_VALIDATE("%s mode requires at least %zu indices but index count is %zu.",
+ modeToStr(meshMode), min_vcount_for_mode(meshMode), mIndexCount);
+ }
+ size_t isize = sm.mul(sizeof(uint16_t), mIndexCount);
+ if (sm.add(isize, mIndexOffset) > mIndexBufferData.size()) {
+ FAIL_MESH_VALIDATE(
+ "The index buffer offset and index count reads beyond the end of the"
+ " index buffer.");
+ }
+ // If we allow 32 bit indices then this should enforce 4 byte alignment in that case.
+ if (!SkIsAlign2(mIndexOffset)) {
+ FAIL_MESH_VALIDATE("The index offset must be a multiple of 2.");
+ }
+ } else {
+ if (mVertexCount < min_vcount_for_mode(meshMode)) {
+ FAIL_MESH_VALIDATE("%s mode requires at least %zu vertices but vertex count is %zu.",
+ modeToStr(meshMode), min_vcount_for_mode(meshMode), mVertexCount);
+ }
+ SkASSERT(!fICount);
+ SkASSERT(!fIOffset);
+ }
+
+ if (!sm.ok()) {
+ FAIL_MESH_VALIDATE("Overflow");
+ }
+#undef FAIL_MESH_VALIDATE
+ return {true, {}};
+}
diff --git a/libs/hwui/Mesh.h b/libs/hwui/Mesh.h
new file mode 100644
index 000000000000..13e3c8e7bf77
--- /dev/null
+++ b/libs/hwui/Mesh.h
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MESH_H_
+#define MESH_H_
+
+#include <GrDirectContext.h>
+#include <SkMesh.h>
+#include <jni.h>
+#include <log/log.h>
+
+#include <utility>
+
+class MeshUniformBuilder {
+public:
+ struct MeshUniform {
+ template <typename T>
+ std::enable_if_t<std::is_trivially_copyable<T>::value, MeshUniform> operator=(
+ const T& val) {
+ if (!fVar) {
+ LOG_FATAL("Assigning to missing variable");
+ } else if (sizeof(val) != fVar->sizeInBytes()) {
+ LOG_FATAL("Incorrect value size");
+ } else {
+ void* dst = reinterpret_cast<void*>(
+ reinterpret_cast<uint8_t*>(fOwner->writableUniformData()) + fVar->offset);
+ memcpy(dst, &val, sizeof(val));
+ }
+ }
+
+ MeshUniform& operator=(const SkMatrix& val) {
+ if (!fVar) {
+ LOG_FATAL("Assigning to missing variable");
+ } else if (fVar->sizeInBytes() != 9 * sizeof(float)) {
+ LOG_FATAL("Incorrect value size");
+ } else {
+ float* data = reinterpret_cast<float*>(
+ reinterpret_cast<uint8_t*>(fOwner->writableUniformData()) + fVar->offset);
+ data[0] = val.get(0);
+ data[1] = val.get(3);
+ data[2] = val.get(6);
+ data[3] = val.get(1);
+ data[4] = val.get(4);
+ data[5] = val.get(7);
+ data[6] = val.get(2);
+ data[7] = val.get(5);
+ data[8] = val.get(8);
+ }
+ return *this;
+ }
+
+ template <typename T>
+ bool set(const T val[], const int count) {
+ static_assert(std::is_trivially_copyable<T>::value, "Value must be trivial copyable");
+ if (!fVar) {
+ LOG_FATAL("Assigning to missing variable");
+ return false;
+ } else if (sizeof(T) * count != fVar->sizeInBytes()) {
+ LOG_FATAL("Incorrect value size");
+ return false;
+ } else {
+ void* dst = reinterpret_cast<void*>(
+ reinterpret_cast<uint8_t*>(fOwner->writableUniformData()) + fVar->offset);
+ memcpy(dst, val, sizeof(T) * count);
+ }
+ return true;
+ }
+
+ MeshUniformBuilder* fOwner;
+ const SkRuntimeEffect::Uniform* fVar;
+ };
+ MeshUniform uniform(std::string_view name) { return {this, fMeshSpec->findUniform(name)}; }
+
+ explicit MeshUniformBuilder(sk_sp<SkMeshSpecification> meshSpec) {
+ fMeshSpec = sk_sp(meshSpec);
+ fUniforms = (SkData::MakeZeroInitialized(meshSpec->uniformSize()));
+ }
+
+ sk_sp<SkData> fUniforms;
+
+private:
+ void* writableUniformData() {
+ if (!fUniforms->unique()) {
+ fUniforms = SkData::MakeWithCopy(fUniforms->data(), fUniforms->size());
+ }
+ return fUniforms->writable_data();
+ }
+
+ sk_sp<SkMeshSpecification> fMeshSpec;
+};
+
+class Mesh {
+public:
+ Mesh(const sk_sp<SkMeshSpecification>& meshSpec, int mode,
+ std::vector<uint8_t>&& vertexBufferData, jint vertexCount, jint vertexOffset,
+ std::unique_ptr<MeshUniformBuilder> builder, const SkRect& bounds)
+ : mMeshSpec(meshSpec)
+ , mMode(mode)
+ , mVertexBufferData(std::move(vertexBufferData))
+ , mVertexCount(vertexCount)
+ , mVertexOffset(vertexOffset)
+ , mBuilder(std::move(builder))
+ , mBounds(bounds) {}
+
+ Mesh(const sk_sp<SkMeshSpecification>& meshSpec, int mode,
+ std::vector<uint8_t>&& vertexBufferData, jint vertexCount, jint vertexOffset,
+ std::vector<uint8_t>&& indexBuffer, jint indexCount, jint indexOffset,
+ std::unique_ptr<MeshUniformBuilder> builder, const SkRect& bounds)
+ : mMeshSpec(meshSpec)
+ , mMode(mode)
+ , mVertexBufferData(std::move(vertexBufferData))
+ , mVertexCount(vertexCount)
+ , mVertexOffset(vertexOffset)
+ , mIndexBufferData(std::move(indexBuffer))
+ , mIndexCount(indexCount)
+ , mIndexOffset(indexOffset)
+ , mBuilder(std::move(builder))
+ , mBounds(bounds) {}
+
+ Mesh(Mesh&&) = default;
+
+ Mesh& operator=(Mesh&&) = default;
+
+ [[nodiscard]] std::tuple<bool, SkString> validate();
+
+ void updateSkMesh(GrDirectContext* context) const {
+ GrDirectContext::DirectContextID genId = GrDirectContext::DirectContextID();
+ if (context) {
+ genId = context->directContextID();
+ }
+
+ if (mIsDirty || genId != mGenerationId) {
+ auto vb = SkMesh::MakeVertexBuffer(
+ context, reinterpret_cast<const void*>(mVertexBufferData.data()),
+ mVertexBufferData.size());
+ auto meshMode = SkMesh::Mode(mMode);
+ if (!mIndexBufferData.empty()) {
+ auto ib = SkMesh::MakeIndexBuffer(
+ context, reinterpret_cast<const void*>(mIndexBufferData.data()),
+ mIndexBufferData.size());
+ mMesh = SkMesh::MakeIndexed(mMeshSpec, meshMode, vb, mVertexCount, mVertexOffset,
+ ib, mIndexCount, mIndexOffset, mBuilder->fUniforms,
+ mBounds)
+ .mesh;
+ } else {
+ mMesh = SkMesh::Make(mMeshSpec, meshMode, vb, mVertexCount, mVertexOffset,
+ mBuilder->fUniforms, mBounds)
+ .mesh;
+ }
+ mIsDirty = false;
+ mGenerationId = genId;
+ }
+ }
+
+ SkMesh& getSkMesh() const {
+ LOG_FATAL_IF(mIsDirty,
+ "Attempt to obtain SkMesh when Mesh is dirty, did you "
+ "forget to call updateSkMesh with a GrDirectContext? "
+ "Defensively creating a CPU mesh");
+ return mMesh;
+ }
+
+ void markDirty() { mIsDirty = true; }
+
+ MeshUniformBuilder* uniformBuilder() { return mBuilder.get(); }
+
+private:
+ sk_sp<SkMeshSpecification> mMeshSpec;
+ int mMode = 0;
+
+ std::vector<uint8_t> mVertexBufferData;
+ size_t mVertexCount = 0;
+ size_t mVertexOffset = 0;
+
+ std::vector<uint8_t> mIndexBufferData;
+ size_t mIndexCount = 0;
+ size_t mIndexOffset = 0;
+
+ std::unique_ptr<MeshUniformBuilder> mBuilder;
+ SkRect mBounds{};
+
+ mutable SkMesh mMesh{};
+ mutable bool mIsDirty = true;
+ mutable GrDirectContext::DirectContextID mGenerationId = GrDirectContext::DirectContextID();
+};
+#endif // MESH_H_
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 659aec0fdf58..0b58406516e3 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -24,6 +24,7 @@
#include <experimental/type_traits>
#include <utility>
+#include "Mesh.h"
#include "SkAndroidFrameworkUtils.h"
#include "SkBlendMode.h"
#include "SkCanvas.h"
@@ -502,14 +503,14 @@ struct DrawVertices final : Op {
c->drawVertices(vertices, mode, paint);
}
};
-struct DrawMesh final : Op {
- static const auto kType = Type::DrawMesh;
- DrawMesh(const SkMesh& mesh, sk_sp<SkBlender> blender, const SkPaint& paint)
+struct DrawSkMesh final : Op {
+ static const auto kType = Type::DrawSkMesh;
+ DrawSkMesh(const SkMesh& mesh, sk_sp<SkBlender> blender, const SkPaint& paint)
: cpuMesh(mesh), blender(std::move(blender)), paint(paint) {
isGpuBased = false;
}
- SkMesh cpuMesh;
+ const SkMesh& cpuMesh;
mutable SkMesh gpuMesh;
sk_sp<SkBlender> blender;
SkPaint paint;
@@ -517,6 +518,7 @@ struct DrawMesh final : Op {
mutable GrDirectContext::DirectContextID contextId;
void draw(SkCanvas* c, const SkMatrix&) const {
GrDirectContext* directContext = c->recordingContext()->asDirectContext();
+
GrDirectContext::DirectContextID id = directContext->directContextID();
if (!isGpuBased || contextId != id) {
sk_sp<SkMesh::VertexBuffer> vb =
@@ -543,6 +545,18 @@ struct DrawMesh final : Op {
c->drawMesh(gpuMesh, blender, paint);
}
};
+
+struct DrawMesh final : Op {
+ static const auto kType = Type::DrawMesh;
+ DrawMesh(const Mesh& mesh, sk_sp<SkBlender> blender, const SkPaint& paint)
+ : mesh(mesh), blender(std::move(blender)), paint(paint) {}
+
+ const Mesh& mesh;
+ sk_sp<SkBlender> blender;
+ SkPaint paint;
+
+ void draw(SkCanvas* c, const SkMatrix&) const { c->drawMesh(mesh.getSkMesh(), blender, paint); }
+};
struct DrawAtlas final : Op {
static const auto kType = Type::DrawAtlas;
DrawAtlas(const SkImage* atlas, int count, SkBlendMode mode, const SkSamplingOptions& sampling,
@@ -859,6 +873,10 @@ void DisplayListData::drawVertices(const SkVertices* vert, SkBlendMode mode, con
}
void DisplayListData::drawMesh(const SkMesh& mesh, const sk_sp<SkBlender>& blender,
const SkPaint& paint) {
+ this->push<DrawSkMesh>(0, mesh, blender, paint);
+}
+void DisplayListData::drawMesh(const Mesh& mesh, const sk_sp<SkBlender>& blender,
+ const SkPaint& paint) {
this->push<DrawMesh>(0, mesh, blender, paint);
}
void DisplayListData::drawAtlas(const SkImage* atlas, const SkRSXform xforms[], const SkRect texs[],
@@ -1205,6 +1223,9 @@ void RecordingCanvas::onDrawMesh(const SkMesh& mesh, sk_sp<SkBlender> blender,
const SkPaint& paint) {
fDL->drawMesh(mesh, blender, paint);
}
+void RecordingCanvas::drawMesh(const Mesh& mesh, sk_sp<SkBlender> blender, const SkPaint& paint) {
+ fDL->drawMesh(mesh, blender, paint);
+}
void RecordingCanvas::onDrawAtlas2(const SkImage* atlas, const SkRSXform xforms[],
const SkRect texs[], const SkColor colors[], int count,
SkBlendMode bmode, const SkSamplingOptions& sampling,
@@ -1223,5 +1244,14 @@ void RecordingCanvas::drawWebView(skiapipeline::FunctorDrawable* drawable) {
fDL->drawWebView(drawable);
}
+[[nodiscard]] const SkMesh& DrawMeshPayload::getSkMesh() const {
+ LOG_FATAL_IF(!meshWrapper && !mesh, "One of Mesh or Mesh must be non-null");
+ if (meshWrapper) {
+ return meshWrapper->getSkMesh();
+ } else {
+ return *mesh;
+ }
+}
+
} // namespace uirenderer
} // namespace android
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index 8409e136b57b..1f4ba5d6d557 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -28,6 +28,7 @@
#include <log/log.h>
#include <cstdlib>
+#include <utility>
#include <vector>
#include "CanvasTransform.h"
@@ -40,6 +41,7 @@
enum class SkBlendMode;
class SkRRect;
+class Mesh;
namespace android {
namespace uirenderer {
@@ -66,6 +68,18 @@ struct DisplayListOp {
static_assert(sizeof(DisplayListOp) == 4);
+class DrawMeshPayload {
+public:
+ explicit DrawMeshPayload(const SkMesh* mesh) : mesh(mesh) {}
+ explicit DrawMeshPayload(const Mesh* meshWrapper) : meshWrapper(meshWrapper) {}
+
+ [[nodiscard]] const SkMesh& getSkMesh() const;
+
+private:
+ const SkMesh* mesh = nullptr;
+ const Mesh* meshWrapper = nullptr;
+};
+
struct DrawImagePayload {
explicit DrawImagePayload(Bitmap& bitmap)
: image(bitmap.makeImage()), palette(bitmap.palette()) {
@@ -143,6 +157,7 @@ private:
void drawDRRect(const SkRRect&, const SkRRect&, const SkPaint&);
void drawMesh(const SkMesh&, const sk_sp<SkBlender>&, const SkPaint&);
+ void drawMesh(const Mesh&, const sk_sp<SkBlender>&, const SkPaint&);
void drawAnnotation(const SkRect&, const char*, SkData*);
void drawDrawable(SkDrawable*, const SkMatrix*);
@@ -247,6 +262,7 @@ public:
SkBlendMode, const SkSamplingOptions&, const SkRect*, const SkPaint*) override;
void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&) override;
+ void drawMesh(const Mesh& mesh, sk_sp<SkBlender> blender, const SkPaint& paint);
void drawVectorDrawable(VectorDrawableRoot* tree);
void drawWebView(skiapipeline::FunctorDrawable*);
diff --git a/libs/hwui/SafeMath.h b/libs/hwui/SafeMath.h
new file mode 100644
index 000000000000..4d6adf55c0cb
--- /dev/null
+++ b/libs/hwui/SafeMath.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkSafeMath_DEFINED
+#define SkSafeMath_DEFINED
+
+#include <cstddef>
+#include <cstdint>
+#include <limits>
+
+// Copy of Skia's SafeMath API used to validate Mesh parameters to support
+// deferred creation of SkMesh instances on RenderThread.
+// SafeMath always check that a series of operations do not overflow.
+// This must be correct for all platforms, because this is a check for safety at runtime.
+
+class SafeMath {
+public:
+ SafeMath() = default;
+
+ bool ok() const { return fOK; }
+ explicit operator bool() const { return fOK; }
+
+ size_t mul(size_t x, size_t y) {
+ return sizeof(size_t) == sizeof(uint64_t) ? mul64(x, y) : mul32(x, y);
+ }
+
+ size_t add(size_t x, size_t y) {
+ size_t result = x + y;
+ fOK &= result >= x;
+ return result;
+ }
+
+ /**
+ * Return a + b, unless this result is an overflow/underflow. In those cases, fOK will
+ * be set to false, and it is undefined what this returns.
+ */
+ int addInt(int a, int b) {
+ if (b < 0 && a < std::numeric_limits<int>::min() - b) {
+ fOK = false;
+ return a;
+ } else if (b > 0 && a > std::numeric_limits<int>::max() - b) {
+ fOK = false;
+ return a;
+ }
+ return a + b;
+ }
+
+ // These saturate to their results
+ static size_t Add(size_t x, size_t y) {
+ SafeMath tmp;
+ size_t sum = tmp.add(x, y);
+ return tmp.ok() ? sum : SIZE_MAX;
+ }
+
+ static size_t Mul(size_t x, size_t y) {
+ SafeMath tmp;
+ size_t prod = tmp.mul(x, y);
+ return tmp.ok() ? prod : SIZE_MAX;
+ }
+
+private:
+ uint32_t mul32(uint32_t x, uint32_t y) {
+ uint64_t bx = x;
+ uint64_t by = y;
+ uint64_t result = bx * by;
+ fOK &= result >> 32 == 0;
+ // Overflow information is capture in fOK. Return the result modulo 2^32.
+ return (uint32_t)result;
+ }
+
+ uint64_t mul64(uint64_t x, uint64_t y) {
+ if (x <= std::numeric_limits<uint64_t>::max() >> 32 &&
+ y <= std::numeric_limits<uint64_t>::max() >> 32) {
+ return x * y;
+ } else {
+ auto hi = [](uint64_t x) { return x >> 32; };
+ auto lo = [](uint64_t x) { return x & 0xFFFFFFFF; };
+
+ uint64_t lx_ly = lo(x) * lo(y);
+ uint64_t hx_ly = hi(x) * lo(y);
+ uint64_t lx_hy = lo(x) * hi(y);
+ uint64_t hx_hy = hi(x) * hi(y);
+ uint64_t result = 0;
+ result = this->add(lx_ly, (hx_ly << 32));
+ result = this->add(result, (lx_hy << 32));
+ fOK &= (hx_hy + (hx_ly >> 32) + (lx_hy >> 32)) == 0;
+
+ return result;
+ }
+ }
+ bool fOK = true;
+};
+
+#endif // SkSafeMath_DEFINED
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index d0124f5d4bad..7a1276982d0a 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -39,21 +39,22 @@
#include <SkShader.h>
#include <SkTextBlob.h>
#include <SkVertices.h>
+#include <log/log.h>
+#include <ui/FatVector.h>
#include <memory>
#include <optional>
#include <utility>
#include "CanvasProperty.h"
+#include "Mesh.h"
#include "NinePatchUtils.h"
#include "VectorDrawable.h"
#include "hwui/Bitmap.h"
#include "hwui/MinikinUtils.h"
#include "hwui/PaintFilter.h"
-#include <log/log.h>
#include "pipeline/skia/AnimatedDrawables.h"
#include "pipeline/skia/HolePunch.h"
-#include <ui/FatVector.h>
namespace android {
@@ -572,8 +573,14 @@ void SkiaCanvas::drawVertices(const SkVertices* vertices, SkBlendMode mode, cons
applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawVertices(vertices, mode, p); });
}
-void SkiaCanvas::drawMesh(const SkMesh& mesh, sk_sp<SkBlender> blender, const SkPaint& paint) {
- mCanvas->drawMesh(mesh, blender, paint);
+void SkiaCanvas::drawMesh(const Mesh& mesh, sk_sp<SkBlender> blender, const Paint& paint) {
+ GrDirectContext* context = nullptr;
+ auto recordingContext = mCanvas->recordingContext();
+ if (recordingContext) {
+ context = recordingContext->asDirectContext();
+ }
+ mesh.updateSkMesh(context);
+ mCanvas->drawMesh(mesh.getSkMesh(), blender, paint);
}
// ----------------------------------------------------------------------------
diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h
index f2c286a4fb46..b785989f35cb 100644
--- a/libs/hwui/SkiaCanvas.h
+++ b/libs/hwui/SkiaCanvas.h
@@ -129,8 +129,7 @@ public:
float sweepAngle, bool useCenter, const Paint& paint) override;
virtual void drawPath(const SkPath& path, const Paint& paint) override;
virtual void drawVertices(const SkVertices*, SkBlendMode, const Paint& paint) override;
- virtual void drawMesh(const SkMesh& mesh, sk_sp<SkBlender> blender,
- const SkPaint& paint) override;
+ virtual void drawMesh(const Mesh& mesh, sk_sp<SkBlender> blender, const Paint& paint) override;
virtual void drawBitmap(Bitmap& bitmap, float left, float top, const Paint* paint) override;
virtual void drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const Paint* paint) override;
diff --git a/libs/hwui/apex/LayoutlibLoader.cpp b/libs/hwui/apex/LayoutlibLoader.cpp
index b7a15633ff6d..770822a049b7 100644
--- a/libs/hwui/apex/LayoutlibLoader.cpp
+++ b/libs/hwui/apex/LayoutlibLoader.cpp
@@ -66,6 +66,7 @@ extern int register_android_graphics_fonts_FontFamily(JNIEnv* env);
extern int register_android_graphics_text_LineBreaker(JNIEnv* env);
extern int register_android_graphics_text_MeasuredText(JNIEnv* env);
extern int register_android_graphics_text_TextShaper(JNIEnv* env);
+extern int register_android_graphics_text_GraphemeBreak(JNIEnv* env);
extern int register_android_util_PathParser(JNIEnv* env);
extern int register_android_view_DisplayListCanvas(JNIEnv* env);
@@ -125,6 +126,8 @@ static const std::unordered_map<std::string, RegJNIRec> gRegJNIMap = {
{"android.graphics.text.MeasuredText",
REG_JNI(register_android_graphics_text_MeasuredText)},
{"android.graphics.text.TextRunShaper", REG_JNI(register_android_graphics_text_TextShaper)},
+ {"android.graphics.text.GraphemeBreak",
+ REG_JNI(register_android_graphics_text_GraphemeBreak)},
{"android.util.PathParser", REG_JNI(register_android_util_PathParser)},
};
diff --git a/libs/hwui/apex/jni_runtime.cpp b/libs/hwui/apex/jni_runtime.cpp
index c509ed4dfd21..09ae7e78fe23 100644
--- a/libs/hwui/apex/jni_runtime.cpp
+++ b/libs/hwui/apex/jni_runtime.cpp
@@ -77,6 +77,7 @@ extern int register_android_graphics_pdf_PdfRenderer(JNIEnv* env);
extern int register_android_graphics_text_MeasuredText(JNIEnv* env);
extern int register_android_graphics_text_LineBreaker(JNIEnv *env);
extern int register_android_graphics_text_TextShaper(JNIEnv *env);
+extern int register_android_graphics_text_GraphemeBreak(JNIEnv* env);
extern int register_android_graphics_MeshSpecification(JNIEnv* env);
extern int register_android_graphics_Mesh(JNIEnv* env);
@@ -148,6 +149,7 @@ extern int register_android_graphics_HardwareBufferRenderer(JNIEnv* env);
REG_JNI(register_android_graphics_text_MeasuredText),
REG_JNI(register_android_graphics_text_LineBreaker),
REG_JNI(register_android_graphics_text_TextShaper),
+ REG_JNI(register_android_graphics_text_GraphemeBreak),
REG_JNI(register_android_graphics_MeshSpecification),
REG_JNI(register_android_graphics_Mesh),
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index ecf6cfc05444..b3eaa0ce5979 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -463,6 +463,13 @@ bool Bitmap::compress(JavaCompressFormat format, int32_t quality, SkWStream* str
if (hasGainmap() && format == JavaCompressFormat::Jpeg) {
SkBitmap baseBitmap = getSkBitmap();
SkBitmap gainmapBitmap = gainmap()->bitmap->getSkBitmap();
+ if (gainmapBitmap.colorType() == SkColorType::kAlpha_8_SkColorType) {
+ SkBitmap greyGainmap;
+ auto greyInfo = gainmapBitmap.info().makeColorType(SkColorType::kGray_8_SkColorType);
+ greyGainmap.setInfo(greyInfo, gainmapBitmap.rowBytes());
+ greyGainmap.setPixelRef(sk_ref_sp(gainmapBitmap.pixelRef()), 0, 0);
+ gainmapBitmap = std::move(greyGainmap);
+ }
SkJpegEncoder::Options options{.fQuality = quality};
return SkJpegGainmapEncoder::EncodeHDRGM(stream, baseBitmap.pixmap(), options,
gainmapBitmap.pixmap(), options, gainmap()->info);
diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h
index 2a2019199bda..44ee31d34d23 100644
--- a/libs/hwui/hwui/Canvas.h
+++ b/libs/hwui/hwui/Canvas.h
@@ -16,25 +16,25 @@
#pragma once
+#include <SaveFlags.h>
+#include <SkBitmap.h>
+#include <SkCanvas.h>
+#include <SkMatrix.h>
+#include <androidfw/ResourceTypes.h>
#include <cutils/compiler.h>
#include <utils/Functor.h>
-#include <SaveFlags.h>
-#include <androidfw/ResourceTypes.h>
#include "Properties.h"
#include "pipeline/skia/AnimatedDrawables.h"
#include "utils/Macros.h"
-#include <SkBitmap.h>
-#include <SkCanvas.h>
-#include <SkMatrix.h>
-
class SkAnimatedImage;
enum class SkBlendMode;
class SkCanvasState;
class SkRRect;
class SkRuntimeShaderBuilder;
class SkVertices;
+class Mesh;
namespace minikin {
class Font;
@@ -227,7 +227,7 @@ public:
float sweepAngle, bool useCenter, const Paint& paint) = 0;
virtual void drawPath(const SkPath& path, const Paint& paint) = 0;
virtual void drawVertices(const SkVertices*, SkBlendMode, const Paint& paint) = 0;
- virtual void drawMesh(const SkMesh& mesh, sk_sp<SkBlender>, const SkPaint& paint) = 0;
+ virtual void drawMesh(const Mesh& mesh, sk_sp<SkBlender>, const Paint& paint) = 0;
// Bitmap-based
virtual void drawBitmap(Bitmap& bitmap, float left, float top, const Paint* paint) = 0;
diff --git a/libs/hwui/jni/BufferUtils.cpp b/libs/hwui/jni/BufferUtils.cpp
new file mode 100644
index 000000000000..3eb08d7552da
--- /dev/null
+++ b/libs/hwui/jni/BufferUtils.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2023 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 "BufferUtils.h"
+
+#include "graphics_jni_helpers.h"
+
+static void copyToVector(std::vector<uint8_t>& dst, const void* src, size_t srcSize) {
+ if (src) {
+ dst.resize(srcSize);
+ memcpy(dst.data(), src, srcSize);
+ }
+}
+
+/**
+ * This code is taken and modified from com_google_android_gles_jni_GLImpl.cpp to extract data
+ * from a java.nio.Buffer.
+ */
+static void* getDirectBufferPointer(JNIEnv* env, jobject buffer) {
+ if (buffer == nullptr) {
+ return nullptr;
+ }
+
+ jint position;
+ jint limit;
+ jint elementSizeShift;
+ jlong pointer;
+ pointer = jniGetNioBufferFields(env, buffer, &position, &limit, &elementSizeShift);
+ if (pointer == 0) {
+ jniThrowException(env, "java/lang/IllegalArgumentException",
+ "Must use a native order direct Buffer");
+ return nullptr;
+ }
+ pointer += position << elementSizeShift;
+ return reinterpret_cast<void*>(pointer);
+}
+
+static void releasePointer(JNIEnv* env, jarray array, void* data, jboolean commit) {
+ env->ReleasePrimitiveArrayCritical(array, data, commit ? 0 : JNI_ABORT);
+}
+
+static void* getPointer(JNIEnv* env, jobject buffer, jarray* array, jint* remaining, jint* offset) {
+ jint position;
+ jint limit;
+ jint elementSizeShift;
+
+ jlong pointer;
+ pointer = jniGetNioBufferFields(env, buffer, &position, &limit, &elementSizeShift);
+ *remaining = (limit - position) << elementSizeShift;
+ if (pointer != 0L) {
+ *array = nullptr;
+ pointer += position << elementSizeShift;
+ return reinterpret_cast<void*>(pointer);
+ }
+
+ *array = jniGetNioBufferBaseArray(env, buffer);
+ *offset = jniGetNioBufferBaseArrayOffset(env, buffer);
+ return nullptr;
+}
+
+/**
+ * This is a copy of
+ * static void android_glBufferData__IILjava_nio_Buffer_2I
+ * from com_google_android_gles_jni_GLImpl.cpp
+ */
+static void setIndirectData(JNIEnv* env, size_t size, jobject data_buf,
+ std::vector<uint8_t>& result) {
+ jint exception = 0;
+ const char* exceptionType = nullptr;
+ const char* exceptionMessage = nullptr;
+ jarray array = nullptr;
+ jint bufferOffset = 0;
+ jint remaining;
+ void* data = 0;
+ char* dataBase = nullptr;
+
+ if (data_buf) {
+ data = getPointer(env, data_buf, (jarray*)&array, &remaining, &bufferOffset);
+ if (remaining < size) {
+ exception = 1;
+ exceptionType = "java/lang/IllegalArgumentException";
+ exceptionMessage = "remaining() < size < needed";
+ goto exit;
+ }
+ }
+ if (data_buf && data == nullptr) {
+ dataBase = (char*)env->GetPrimitiveArrayCritical(array, (jboolean*)0);
+ data = (void*)(dataBase + bufferOffset);
+ }
+
+ copyToVector(result, data, size);
+
+exit:
+ if (array) {
+ releasePointer(env, array, (void*)dataBase, JNI_FALSE);
+ }
+ if (exception) {
+ jniThrowException(env, exceptionType, exceptionMessage);
+ }
+}
+
+std::vector<uint8_t> copyJavaNioBufferToVector(JNIEnv* env, jobject buffer, size_t size,
+ jboolean isDirect) {
+ std::vector<uint8_t> data;
+ if (buffer == nullptr) {
+ jniThrowNullPointerException(env);
+ } else {
+ if (isDirect) {
+ void* directBufferPtr = getDirectBufferPointer(env, buffer);
+ if (directBufferPtr) {
+ copyToVector(data, directBufferPtr, size);
+ }
+ } else {
+ setIndirectData(env, size, buffer, data);
+ }
+ }
+ return data;
+}
diff --git a/libs/hwui/jni/BufferUtils.h b/libs/hwui/jni/BufferUtils.h
new file mode 100644
index 000000000000..b43c320b7771
--- /dev/null
+++ b/libs/hwui/jni/BufferUtils.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+#ifndef BUFFERUTILS_H_
+#define BUFFERUTILS_H_
+
+#include <jni.h>
+
+#include <vector>
+
+/**
+ * Helper method to load a java.nio.Buffer instance into a vector. This handles
+ * both direct and indirect buffers and promptly releases any critical arrays that
+ * have been retrieved in order to avoid potential jni exceptions due to interleaved
+ * jni calls between get/release primitive method invocations.
+ */
+std::vector<uint8_t> copyJavaNioBufferToVector(JNIEnv* env, jobject buffer, size_t size,
+ jboolean isDirect);
+
+#endif // BUFFERUTILS_H_
diff --git a/libs/hwui/jni/GraphicsJNI.h b/libs/hwui/jni/GraphicsJNI.h
index 6b983c10bdca..24f9e82b5340 100644
--- a/libs/hwui/jni/GraphicsJNI.h
+++ b/libs/hwui/jni/GraphicsJNI.h
@@ -46,10 +46,16 @@ public:
static void setJavaVM(JavaVM* javaVM);
- /** returns a pointer to the JavaVM provided when we initialized the module */
+ /**
+ * returns a pointer to the JavaVM provided when we initialized the module
+ * DEPRECATED: Objects should know the JavaVM that created them
+ */
static JavaVM* getJavaVM() { return mJavaVM; }
- /** return a pointer to the JNIEnv for this thread */
+ /**
+ * return a pointer to the JNIEnv for this thread
+ * DEPRECATED: Objects should know the JavaVM that created them
+ */
static JNIEnv* getJNIEnv();
/** create a JNIEnv* for this thread or assert if one already exists */
@@ -337,13 +343,21 @@ public:
JGlobalRefHolder(JavaVM* vm, jobject object) : mVm(vm), mObject(object) {}
virtual ~JGlobalRefHolder() {
- GraphicsJNI::getJNIEnv()->DeleteGlobalRef(mObject);
+ env()->DeleteGlobalRef(mObject);
mObject = nullptr;
}
jobject object() { return mObject; }
JavaVM* vm() { return mVm; }
+ JNIEnv* env() {
+ JNIEnv* env;
+ if (mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+ LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", mVm);
+ }
+ return env;
+ }
+
private:
JGlobalRefHolder(const JGlobalRefHolder&) = delete;
void operator=(const JGlobalRefHolder&) = delete;
diff --git a/libs/hwui/jni/Interpolator.cpp b/libs/hwui/jni/Interpolator.cpp
index fc3d70b87f5a..c71e3085caf5 100644
--- a/libs/hwui/jni/Interpolator.cpp
+++ b/libs/hwui/jni/Interpolator.cpp
@@ -24,12 +24,8 @@ static void Interpolator_setKeyFrame(JNIEnv* env, jobject clazz, jlong interpHan
AutoJavaFloatArray autoValues(env, valueArray);
AutoJavaFloatArray autoBlend(env, blendArray, 4);
-#ifdef SK_SCALAR_IS_FLOAT
SkScalar* scalars = autoValues.ptr();
SkScalar* blend = autoBlend.ptr();
-#else
- #error Need to convert float array to SkScalar array before calling the following function.
-#endif
interp->setKeyFrame(index, msec, scalars, blend);
}
diff --git a/libs/hwui/jni/JvmErrorReporter.h b/libs/hwui/jni/JvmErrorReporter.h
index 5e10b9d93275..3a3587572a1a 100644
--- a/libs/hwui/jni/JvmErrorReporter.h
+++ b/libs/hwui/jni/JvmErrorReporter.h
@@ -30,7 +30,10 @@ public:
JvmErrorReporter(JNIEnv* env) { env->GetJavaVM(&mVm); }
virtual void onError(const std::string& message) override {
- JNIEnv* env = GraphicsJNI::getJNIEnv();
+ JNIEnv* env;
+ if (mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+ LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", mVm);
+ }
jniThrowException(env, "java/lang/IllegalStateException", message.c_str());
}
diff --git a/libs/hwui/jni/Mesh.h b/libs/hwui/jni/Mesh.h
deleted file mode 100644
index 61c2260e3ad1..000000000000
--- a/libs/hwui/jni/Mesh.h
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef FRAMEWORKS_BASE_LIBS_HWUI_JNI_MESH_H_
-#define FRAMEWORKS_BASE_LIBS_HWUI_JNI_MESH_H_
-
-#include <SkMesh.h>
-#include <jni.h>
-
-#include <log/log.h>
-#include <utility>
-
-#include "graphics_jni_helpers.h"
-
-#define gIndexByteSize 2
-
-// A smart pointer that provides read only access to Java.nio.Buffer. This handles both
-// direct and indrect buffers, allowing access to the underlying data in both
-// situations. If passed a null buffer, we will throw NullPointerException,
-// and c_data will return nullptr.
-//
-// This class draws from com_google_android_gles_jni_GLImpl.cpp for Buffer to void *
-// conversion.
-class ScopedJavaNioBuffer {
-public:
- ScopedJavaNioBuffer(JNIEnv* env, jobject buffer, jint size, jboolean isDirect)
- : mEnv(env), mBuffer(buffer) {
- if (buffer == nullptr) {
- mDataBase = nullptr;
- mData = nullptr;
- jniThrowNullPointerException(env);
- } else {
- mArray = (jarray) nullptr;
- if (isDirect) {
- mData = getDirectBufferPointer(mEnv, mBuffer);
- } else {
- mData = setIndirectData(size);
- }
- }
- }
-
- ScopedJavaNioBuffer(ScopedJavaNioBuffer&& rhs) noexcept { *this = std::move(rhs); }
-
- ~ScopedJavaNioBuffer() { reset(); }
-
- void reset() {
- if (mDataBase) {
- releasePointer(mEnv, mArray, mDataBase, JNI_FALSE);
- mDataBase = nullptr;
- }
- }
-
- ScopedJavaNioBuffer& operator=(ScopedJavaNioBuffer&& rhs) noexcept {
- if (this != &rhs) {
- reset();
-
- mEnv = rhs.mEnv;
- mBuffer = rhs.mBuffer;
- mDataBase = rhs.mDataBase;
- mData = rhs.mData;
- mArray = rhs.mArray;
- rhs.mEnv = nullptr;
- rhs.mData = nullptr;
- rhs.mBuffer = nullptr;
- rhs.mArray = nullptr;
- rhs.mDataBase = nullptr;
- }
- return *this;
- }
-
- const void* data() const { return mData; }
-
-private:
- /**
- * This code is taken and modified from com_google_android_gles_jni_GLImpl.cpp to extract data
- * from a java.nio.Buffer.
- */
- void* getDirectBufferPointer(JNIEnv* env, jobject buffer) {
- if (buffer == nullptr) {
- return nullptr;
- }
-
- jint position;
- jint limit;
- jint elementSizeShift;
- jlong pointer;
- pointer = jniGetNioBufferFields(env, buffer, &position, &limit, &elementSizeShift);
- if (pointer == 0) {
- jniThrowException(mEnv, "java/lang/IllegalArgumentException",
- "Must use a native order direct Buffer");
- return nullptr;
- }
- pointer += position << elementSizeShift;
- return reinterpret_cast<void*>(pointer);
- }
-
- static void releasePointer(JNIEnv* env, jarray array, void* data, jboolean commit) {
- env->ReleasePrimitiveArrayCritical(array, data, commit ? 0 : JNI_ABORT);
- }
-
- static void* getPointer(JNIEnv* env, jobject buffer, jarray* array, jint* remaining,
- jint* offset) {
- jint position;
- jint limit;
- jint elementSizeShift;
-
- jlong pointer;
- pointer = jniGetNioBufferFields(env, buffer, &position, &limit, &elementSizeShift);
- *remaining = (limit - position) << elementSizeShift;
- if (pointer != 0L) {
- *array = nullptr;
- pointer += position << elementSizeShift;
- return reinterpret_cast<void*>(pointer);
- }
-
- *array = jniGetNioBufferBaseArray(env, buffer);
- *offset = jniGetNioBufferBaseArrayOffset(env, buffer);
- return nullptr;
- }
-
- /**
- * This is a copy of
- * static void android_glBufferData__IILjava_nio_Buffer_2I
- * from com_google_android_gles_jni_GLImpl.cpp
- */
- void* setIndirectData(jint size) {
- jint exception;
- const char* exceptionType;
- const char* exceptionMessage;
- jint bufferOffset = (jint)0;
- jint remaining;
- void* tempData;
-
- if (mBuffer) {
- tempData =
- (void*)getPointer(mEnv, mBuffer, (jarray*)&mArray, &remaining, &bufferOffset);
- if (remaining < size) {
- exception = 1;
- exceptionType = "java/lang/IllegalArgumentException";
- exceptionMessage = "remaining() < size < needed";
- goto exit;
- }
- }
- if (mBuffer && tempData == nullptr) {
- mDataBase = (char*)mEnv->GetPrimitiveArrayCritical(mArray, (jboolean*)0);
- tempData = (void*)(mDataBase + bufferOffset);
- }
- return tempData;
- exit:
- if (mArray) {
- releasePointer(mEnv, mArray, (void*)(mDataBase), JNI_FALSE);
- }
- if (exception) {
- jniThrowException(mEnv, exceptionType, exceptionMessage);
- }
- return nullptr;
- }
-
- JNIEnv* mEnv;
-
- // Java Buffer data
- void* mData;
- jobject mBuffer;
-
- // Indirect Buffer Data
- jarray mArray;
- char* mDataBase;
-};
-
-class MeshUniformBuilder {
-public:
- struct MeshUniform {
- template <typename T>
- std::enable_if_t<std::is_trivially_copyable<T>::value, MeshUniform> operator=(
- const T& val) {
- if (!fVar) {
- LOG_FATAL("Assigning to missing variable");
- } else if (sizeof(val) != fVar->sizeInBytes()) {
- LOG_FATAL("Incorrect value size");
- } else {
- void* dst = reinterpret_cast<void*>(
- reinterpret_cast<uint8_t*>(fOwner->writableUniformData()) + fVar->offset);
- memcpy(dst, &val, sizeof(val));
- }
- }
-
- MeshUniform& operator=(const SkMatrix& val) {
- if (!fVar) {
- LOG_FATAL("Assigning to missing variable");
- } else if (fVar->sizeInBytes() != 9 * sizeof(float)) {
- LOG_FATAL("Incorrect value size");
- } else {
- float* data = reinterpret_cast<float*>(
- reinterpret_cast<uint8_t*>(fOwner->writableUniformData()) + fVar->offset);
- data[0] = val.get(0);
- data[1] = val.get(3);
- data[2] = val.get(6);
- data[3] = val.get(1);
- data[4] = val.get(4);
- data[5] = val.get(7);
- data[6] = val.get(2);
- data[7] = val.get(5);
- data[8] = val.get(8);
- }
- return *this;
- }
-
- template <typename T>
- bool set(const T val[], const int count) {
- static_assert(std::is_trivially_copyable<T>::value, "Value must be trivial copyable");
- if (!fVar) {
- LOG_FATAL("Assigning to missing variable");
- return false;
- } else if (sizeof(T) * count != fVar->sizeInBytes()) {
- LOG_FATAL("Incorrect value size");
- return false;
- } else {
- void* dst = reinterpret_cast<void*>(
- reinterpret_cast<uint8_t*>(fOwner->writableUniformData()) + fVar->offset);
- memcpy(dst, val, sizeof(T) * count);
- }
- return true;
- }
-
- MeshUniformBuilder* fOwner;
- const SkRuntimeEffect::Uniform* fVar;
- };
- MeshUniform uniform(std::string_view name) { return {this, fMeshSpec->findUniform(name)}; }
-
- explicit MeshUniformBuilder(sk_sp<SkMeshSpecification> meshSpec) {
- fMeshSpec = sk_sp(meshSpec);
- fUniforms = (SkData::MakeZeroInitialized(meshSpec->uniformSize()));
- }
-
- sk_sp<SkData> fUniforms;
-
-private:
- void* writableUniformData() {
- if (!fUniforms->unique()) {
- fUniforms = SkData::MakeWithCopy(fUniforms->data(), fUniforms->size());
- }
- return fUniforms->writable_data();
- }
-
- sk_sp<SkMeshSpecification> fMeshSpec;
-};
-
-struct MeshWrapper {
- SkMesh mesh;
- MeshUniformBuilder builder;
-};
-#endif // FRAMEWORKS_BASE_LIBS_HWUI_JNI_MESH_H_
diff --git a/libs/hwui/jni/Path.cpp b/libs/hwui/jni/Path.cpp
index 3694ce07b972..a5e04763d885 100644
--- a/libs/hwui/jni/Path.cpp
+++ b/libs/hwui/jni/Path.cpp
@@ -182,11 +182,7 @@ public:
SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
SkPathDirection dir = static_cast<SkPathDirection>(dirHandle);
AutoJavaFloatArray afa(env, array, 8);
-#ifdef SK_SCALAR_IS_FLOAT
const float* src = afa.ptr();
-#else
- #error Need to convert float array to SkScalar array before calling the following function.
-#endif
obj->addRoundRect(rect, src, dir);
}
diff --git a/libs/hwui/jni/PathEffect.cpp b/libs/hwui/jni/PathEffect.cpp
index f99bef7b7d58..3dbe1a67f52e 100644
--- a/libs/hwui/jni/PathEffect.cpp
+++ b/libs/hwui/jni/PathEffect.cpp
@@ -35,11 +35,7 @@ public:
jfloatArray intervalArray, jfloat phase) {
AutoJavaFloatArray autoInterval(env, intervalArray);
int count = autoInterval.length() & ~1; // even number
-#ifdef SK_SCALAR_IS_FLOAT
- SkScalar* intervals = autoInterval.ptr();
-#else
- #error Need to convert float array to SkScalar array before calling the following function.
-#endif
+ SkScalar* intervals = autoInterval.ptr();
SkPathEffect* effect = SkDashPathEffect::Make(intervals, count, phase).release();
return reinterpret_cast<jlong>(effect);
}
diff --git a/libs/hwui/jni/Shader.cpp b/libs/hwui/jni/Shader.cpp
index 8a0db1c91d46..75d45e5bd8aa 100644
--- a/libs/hwui/jni/Shader.cpp
+++ b/libs/hwui/jni/Shader.cpp
@@ -52,12 +52,7 @@ static void Color_RGBToHSV(JNIEnv* env, jobject, jint red, jint green, jint blue
static jint Color_HSVToColor(JNIEnv* env, jobject, jint alpha, jfloatArray hsvArray)
{
AutoJavaFloatArray autoHSV(env, hsvArray, 3);
-#ifdef SK_SCALAR_IS_FLOAT
- SkScalar* hsv = autoHSV.ptr();
-#else
- #error Need to convert float array to SkScalar array before calling the following function.
-#endif
-
+ SkScalar* hsv = autoHSV.ptr();
return static_cast<jint>(SkHSVToColor(alpha, hsv));
}
@@ -149,11 +144,7 @@ static jlong LinearGradient_create(JNIEnv* env, jobject, jlong matrixPtr,
std::vector<SkColor4f> colors = convertColorLongs(env, colorArray);
AutoJavaFloatArray autoPos(env, posArray, colors.size());
-#ifdef SK_SCALAR_IS_FLOAT
SkScalar* pos = autoPos.ptr();
-#else
- #error Need to convert float array to SkScalar array before calling the following function.
-#endif
sk_sp<SkShader> shader(SkGradientShader::MakeLinear(pts, &colors[0],
GraphicsJNI::getNativeColorSpace(colorSpaceHandle), pos, colors.size(),
@@ -193,11 +184,7 @@ static jlong RadialGradient_create(JNIEnv* env,
std::vector<SkColor4f> colors = convertColorLongs(env, colorArray);
AutoJavaFloatArray autoPos(env, posArray, colors.size());
-#ifdef SK_SCALAR_IS_FLOAT
SkScalar* pos = autoPos.ptr();
-#else
- #error Need to convert float array to SkScalar array before calling the following function.
-#endif
auto colorSpace = GraphicsJNI::getNativeColorSpace(colorSpaceHandle);
auto skTileMode = static_cast<SkTileMode>(tileMode);
@@ -225,11 +212,7 @@ static jlong SweepGradient_create(JNIEnv* env, jobject, jlong matrixPtr, jfloat
std::vector<SkColor4f> colors = convertColorLongs(env, colorArray);
AutoJavaFloatArray autoPos(env, jpositions, colors.size());
-#ifdef SK_SCALAR_IS_FLOAT
SkScalar* pos = autoPos.ptr();
-#else
- #error Need to convert float array to SkScalar array before calling the following function.
-#endif
sk_sp<SkShader> shader = SkGradientShader::MakeSweep(x, y, &colors[0],
GraphicsJNI::getNativeColorSpace(colorSpaceHandle), pos, colors.size(),
diff --git a/libs/hwui/jni/android_graphics_Canvas.cpp b/libs/hwui/jni/android_graphics_Canvas.cpp
index 8a4d4e17edb1..8ba750372d18 100644
--- a/libs/hwui/jni/android_graphics_Canvas.cpp
+++ b/libs/hwui/jni/android_graphics_Canvas.cpp
@@ -21,7 +21,6 @@
#else
#define __ANDROID_API_P__ 28
#endif
-#include <Mesh.h>
#include <androidfw/ResourceTypes.h>
#include <hwui/Canvas.h>
#include <hwui/Paint.h>
@@ -446,10 +445,10 @@ static void drawVertices(JNIEnv* env, jobject, jlong canvasHandle,
static void drawMesh(JNIEnv* env, jobject, jlong canvasHandle, jlong meshHandle, jint modeHandle,
jlong paintHandle) {
- const SkMesh mesh = reinterpret_cast<MeshWrapper*>(meshHandle)->mesh;
+ const Mesh* mesh = reinterpret_cast<Mesh*>(meshHandle);
SkBlendMode blendMode = static_cast<SkBlendMode>(modeHandle);
- SkPaint* paint = reinterpret_cast<Paint*>(paintHandle);
- get_canvas(canvasHandle)->drawMesh(mesh, SkBlender::Mode(blendMode), *paint);
+ Paint* paint = reinterpret_cast<Paint*>(paintHandle);
+ get_canvas(canvasHandle)->drawMesh(*mesh, SkBlender::Mode(blendMode), *paint);
}
static void drawNinePatch(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
diff --git a/libs/hwui/jni/android_graphics_HardwareBufferRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareBufferRenderer.cpp
index 3e453e65ae92..ae22213f4bf4 100644
--- a/libs/hwui/jni/android_graphics_HardwareBufferRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareBufferRenderer.cpp
@@ -49,7 +49,7 @@ static RenderCallback createRenderCallback(JNIEnv* env, jobject releaseCallback)
auto globalCallbackRef =
std::make_shared<JGlobalRefHolder>(vm, env->NewGlobalRef(releaseCallback));
return [globalCallbackRef](android::base::unique_fd&& fd, int status) {
- GraphicsJNI::getJNIEnv()->CallStaticVoidMethod(
+ globalCallbackRef->env()->CallStaticVoidMethod(
gHardwareBufferRendererClassInfo.clazz,
gHardwareBufferRendererClassInfo.invokeRenderCallback, globalCallbackRef->object(),
reinterpret_cast<jint>(fd.release()), reinterpret_cast<jint>(status));
@@ -172,7 +172,8 @@ static const JNINativeMethod gMethods[] = {
int register_android_graphics_HardwareBufferRenderer(JNIEnv* env) {
jclass hardwareBufferRendererClazz =
FindClassOrDie(env, "android/graphics/HardwareBufferRenderer");
- gHardwareBufferRendererClassInfo.clazz = hardwareBufferRendererClazz;
+ gHardwareBufferRendererClassInfo.clazz =
+ reinterpret_cast<jclass>(env->NewGlobalRef(hardwareBufferRendererClazz));
gHardwareBufferRendererClassInfo.invokeRenderCallback =
GetStaticMethodIDOrDie(env, hardwareBufferRendererClazz, "invokeRenderCallback",
"(Ljava/util/function/Consumer;II)V");
diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
index d6aad7d3eede..6a7411f5d859 100644
--- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
@@ -94,12 +94,21 @@ struct {
jmethodID getDestinationBitmap;
} gCopyRequest;
+static JNIEnv* getenv(JavaVM* vm) {
+ JNIEnv* env;
+ if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+ LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", vm);
+ }
+ return env;
+}
+
typedef ANativeWindow* (*ANW_fromSurface)(JNIEnv* env, jobject surface);
ANW_fromSurface fromSurface;
class FrameCommitWrapper : public LightRefBase<FrameCommitWrapper> {
public:
explicit FrameCommitWrapper(JNIEnv* env, jobject jobject) {
+ env->GetJavaVM(&mVm);
mObject = env->NewGlobalRef(jobject);
LOG_ALWAYS_FATAL_IF(!mObject, "Failed to make global ref");
}
@@ -109,18 +118,19 @@ public:
void onFrameCommit(bool didProduceBuffer) {
if (mObject) {
ATRACE_FORMAT("frameCommit success=%d", didProduceBuffer);
- GraphicsJNI::getJNIEnv()->CallVoidMethod(mObject, gFrameCommitCallback.onFrameCommit,
- didProduceBuffer);
+ getenv(mVm)->CallVoidMethod(mObject, gFrameCommitCallback.onFrameCommit,
+ didProduceBuffer);
releaseObject();
}
}
private:
+ JavaVM* mVm;
jobject mObject;
void releaseObject() {
if (mObject) {
- GraphicsJNI::getJNIEnv()->DeleteGlobalRef(mObject);
+ getenv(mVm)->DeleteGlobalRef(mObject);
mObject = nullptr;
}
}
@@ -541,10 +551,9 @@ static void android_view_ThreadedRenderer_setPictureCapturedCallbackJNI(JNIEnv*
auto pictureState = std::make_shared<PictureCaptureState>();
proxy->setPictureCapturedCallback([globalCallbackRef,
pictureState](sk_sp<SkPicture>&& picture) {
- JNIEnv* env = GraphicsJNI::getJNIEnv();
Picture* wrapper = new PictureWrapper{std::move(picture), pictureState};
- env->CallStaticVoidMethod(gHardwareRenderer.clazz,
- gHardwareRenderer.invokePictureCapturedCallback,
+ globalCallbackRef->env()->CallStaticVoidMethod(
+ gHardwareRenderer.clazz, gHardwareRenderer.invokePictureCapturedCallback,
static_cast<jlong>(reinterpret_cast<intptr_t>(wrapper)),
globalCallbackRef->object());
});
@@ -561,16 +570,14 @@ static void android_view_ThreadedRenderer_setASurfaceTransactionCallback(
LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM");
auto globalCallbackRef = std::make_shared<JGlobalRefHolder>(
vm, env->NewGlobalRef(aSurfaceTransactionCallback));
- proxy->setASurfaceTransactionCallback(
- [globalCallbackRef](int64_t transObj, int64_t scObj, int64_t frameNr) -> bool {
- JNIEnv* env = GraphicsJNI::getJNIEnv();
- jboolean ret = env->CallBooleanMethod(
- globalCallbackRef->object(),
- gASurfaceTransactionCallback.onMergeTransaction,
- static_cast<jlong>(transObj), static_cast<jlong>(scObj),
- static_cast<jlong>(frameNr));
- return ret;
- });
+ proxy->setASurfaceTransactionCallback([globalCallbackRef](int64_t transObj, int64_t scObj,
+ int64_t frameNr) -> bool {
+ jboolean ret = globalCallbackRef->env()->CallBooleanMethod(
+ globalCallbackRef->object(), gASurfaceTransactionCallback.onMergeTransaction,
+ static_cast<jlong>(transObj), static_cast<jlong>(scObj),
+ static_cast<jlong>(frameNr));
+ return ret;
+ });
}
}
@@ -585,9 +592,8 @@ static void android_view_ThreadedRenderer_setPrepareSurfaceControlForWebviewCall
auto globalCallbackRef =
std::make_shared<JGlobalRefHolder>(vm, env->NewGlobalRef(callback));
proxy->setPrepareSurfaceControlForWebviewCallback([globalCallbackRef]() {
- JNIEnv* env = GraphicsJNI::getJNIEnv();
- env->CallVoidMethod(globalCallbackRef->object(),
- gPrepareSurfaceControlForWebviewCallback.prepare);
+ globalCallbackRef->env()->CallVoidMethod(
+ globalCallbackRef->object(), gPrepareSurfaceControlForWebviewCallback.prepare);
});
}
}
@@ -604,7 +610,7 @@ static void android_view_ThreadedRenderer_setFrameCallback(JNIEnv* env,
env->NewGlobalRef(frameCallback));
proxy->setFrameCallback([globalCallbackRef](int32_t syncResult,
int64_t frameNr) -> std::function<void(bool)> {
- JNIEnv* env = GraphicsJNI::getJNIEnv();
+ JNIEnv* env = globalCallbackRef->env();
ScopedLocalRef<jobject> frameCommitCallback(
env, env->CallObjectMethod(
globalCallbackRef->object(), gFrameDrawingCallback.onFrameDraw,
@@ -643,9 +649,8 @@ static void android_view_ThreadedRenderer_setFrameCompleteCallback(JNIEnv* env,
auto globalCallbackRef =
std::make_shared<JGlobalRefHolder>(vm, env->NewGlobalRef(callback));
proxy->setFrameCompleteCallback([globalCallbackRef]() {
- JNIEnv* env = GraphicsJNI::getJNIEnv();
- env->CallVoidMethod(globalCallbackRef->object(),
- gFrameCompleteCallback.onFrameComplete);
+ globalCallbackRef->env()->CallVoidMethod(globalCallbackRef->object(),
+ gFrameCompleteCallback.onFrameComplete);
});
}
}
@@ -656,8 +661,7 @@ public:
: CopyRequest(srcRect), mRefHolder(vm, jCopyRequest) {}
virtual SkBitmap getDestinationBitmap(int srcWidth, int srcHeight) override {
- JNIEnv* env = GraphicsJNI::getJNIEnv();
- jlong bitmapPtr = env->CallLongMethod(
+ jlong bitmapPtr = mRefHolder.env()->CallLongMethod(
mRefHolder.object(), gCopyRequest.getDestinationBitmap, srcWidth, srcHeight);
SkBitmap bitmap;
bitmap::toBitmap(bitmapPtr).getSkBitmap(&bitmap);
@@ -665,9 +669,8 @@ public:
}
virtual void onCopyFinished(CopyResult result) override {
- JNIEnv* env = GraphicsJNI::getJNIEnv();
- env->CallVoidMethod(mRefHolder.object(), gCopyRequest.onCopyFinished,
- static_cast<jint>(result));
+ mRefHolder.env()->CallVoidMethod(mRefHolder.object(), gCopyRequest.onCopyFinished,
+ static_cast<jint>(result));
}
private:
diff --git a/libs/hwui/jni/android_graphics_Matrix.cpp b/libs/hwui/jni/android_graphics_Matrix.cpp
index cf6702e45fff..ca667b0d09bc 100644
--- a/libs/hwui/jni/android_graphics_Matrix.cpp
+++ b/libs/hwui/jni/android_graphics_Matrix.cpp
@@ -23,8 +23,6 @@ namespace android {
static_assert(sizeof(SkMatrix) == 40, "Unexpected sizeof(SkMatrix), "
"update size in Matrix.java#NATIVE_ALLOCATION_SIZE and here");
-static_assert(SK_SCALAR_IS_FLOAT, "SK_SCALAR_IS_FLOAT is false, "
- "only float scalar is supported");
class SkMatrixGlue {
public:
diff --git a/libs/hwui/jni/Mesh.cpp b/libs/hwui/jni/android_graphics_Mesh.cpp
index b13d9bafb417..5cb43e54e499 100644
--- a/libs/hwui/jni/Mesh.cpp
+++ b/libs/hwui/jni/android_graphics_Mesh.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,47 +14,37 @@
* limitations under the License.
*/
-#include <GLES/gl.h>
#include <Mesh.h>
#include <SkMesh.h>
+#include <jni.h>
+#include <utility>
+
+#include "BufferUtils.h"
#include "GraphicsJNI.h"
#include "graphics_jni_helpers.h"
-namespace android {
-
-sk_sp<SkMesh::VertexBuffer> genVertexBuffer(JNIEnv* env, jobject buffer, int size,
- jboolean isDirect) {
- auto buff = ScopedJavaNioBuffer(env, buffer, size, isDirect);
- auto vertexBuffer = SkMesh::MakeVertexBuffer(nullptr, buff.data(), size);
- return vertexBuffer;
-}
+#define gIndexByteSize 2
-sk_sp<SkMesh::IndexBuffer> genIndexBuffer(JNIEnv* env, jobject buffer, int size,
- jboolean isDirect) {
- auto buff = ScopedJavaNioBuffer(env, buffer, size, isDirect);
- auto indexBuffer = SkMesh::MakeIndexBuffer(nullptr, buff.data(), size);
- return indexBuffer;
-}
+namespace android {
static jlong make(JNIEnv* env, jobject, jlong meshSpec, jint mode, jobject vertexBuffer,
jboolean isDirect, jint vertexCount, jint vertexOffset, jfloat left, jfloat top,
jfloat right, jfloat bottom) {
auto skMeshSpec = sk_ref_sp(reinterpret_cast<SkMeshSpecification*>(meshSpec));
- sk_sp<SkMesh::VertexBuffer> skVertexBuffer =
- genVertexBuffer(env, vertexBuffer, vertexCount * skMeshSpec->stride(), isDirect);
+ size_t bufferSize = vertexCount * skMeshSpec->stride();
+ auto buffer = copyJavaNioBufferToVector(env, vertexBuffer, bufferSize, isDirect);
+ if (env->ExceptionCheck()) {
+ return 0;
+ }
auto skRect = SkRect::MakeLTRB(left, top, right, bottom);
- auto meshResult = SkMesh::Make(
- skMeshSpec, SkMesh::Mode(mode), skVertexBuffer, vertexCount, vertexOffset,
- SkData::MakeWithCopy(skMeshSpec->uniforms().data(), skMeshSpec->uniformSize()), skRect);
-
- if (!meshResult.error.isEmpty()) {
- jniThrowException(env, "java/lang/IllegalArgumentException", meshResult.error.c_str());
+ auto meshPtr = new Mesh(skMeshSpec, mode, std::move(buffer), vertexCount, vertexOffset,
+ std::make_unique<MeshUniformBuilder>(skMeshSpec), skRect);
+ auto [valid, msg] = meshPtr->validate();
+ if (!valid) {
+ jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", msg.c_str());
}
-
- auto meshPtr = std::make_unique<MeshWrapper>(
- MeshWrapper{meshResult.mesh, MeshUniformBuilder(skMeshSpec)});
- return reinterpret_cast<jlong>(meshPtr.release());
+ return reinterpret_cast<jlong>(meshPtr);
}
static jlong makeIndexed(JNIEnv* env, jobject, jlong meshSpec, jint mode, jobject vertexBuffer,
@@ -62,41 +52,26 @@ static jlong makeIndexed(JNIEnv* env, jobject, jlong meshSpec, jint mode, jobjec
jobject indexBuffer, jboolean isIndexDirect, jint indexCount,
jint indexOffset, jfloat left, jfloat top, jfloat right, jfloat bottom) {
auto skMeshSpec = sk_ref_sp(reinterpret_cast<SkMeshSpecification*>(meshSpec));
- sk_sp<SkMesh::VertexBuffer> skVertexBuffer =
- genVertexBuffer(env, vertexBuffer, vertexCount * skMeshSpec->stride(), isVertexDirect);
- sk_sp<SkMesh::IndexBuffer> skIndexBuffer =
- genIndexBuffer(env, indexBuffer, indexCount * gIndexByteSize, isIndexDirect);
+ auto vertexBufferSize = vertexCount * skMeshSpec->stride();
+ auto indexBufferSize = indexCount * gIndexByteSize;
+ auto vBuf = copyJavaNioBufferToVector(env, vertexBuffer, vertexBufferSize, isVertexDirect);
+ if (env->ExceptionCheck()) {
+ return 0;
+ }
+ auto iBuf = copyJavaNioBufferToVector(env, indexBuffer, indexBufferSize, isIndexDirect);
+ if (env->ExceptionCheck()) {
+ return 0;
+ }
auto skRect = SkRect::MakeLTRB(left, top, right, bottom);
-
- auto meshResult = SkMesh::MakeIndexed(
- skMeshSpec, SkMesh::Mode(mode), skVertexBuffer, vertexCount, vertexOffset,
- skIndexBuffer, indexCount, indexOffset,
- SkData::MakeWithCopy(skMeshSpec->uniforms().data(), skMeshSpec->uniformSize()), skRect);
-
- if (!meshResult.error.isEmpty()) {
- jniThrowException(env, "java/lang/IllegalArgumentException", meshResult.error.c_str());
+ auto meshPtr = new Mesh(skMeshSpec, mode, std::move(vBuf), vertexCount, vertexOffset,
+ std::move(iBuf), indexCount, indexOffset,
+ std::make_unique<MeshUniformBuilder>(skMeshSpec), skRect);
+ auto [valid, msg] = meshPtr->validate();
+ if (!valid) {
+ jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", msg.c_str());
}
- auto meshPtr = std::make_unique<MeshWrapper>(
- MeshWrapper{meshResult.mesh, MeshUniformBuilder(skMeshSpec)});
- return reinterpret_cast<jlong>(meshPtr.release());
-}
-static void updateMesh(JNIEnv* env, jobject, jlong meshWrapper, jboolean indexed) {
- auto wrapper = reinterpret_cast<MeshWrapper*>(meshWrapper);
- auto mesh = wrapper->mesh;
- if (indexed) {
- wrapper->mesh = SkMesh::MakeIndexed(sk_ref_sp(mesh.spec()), mesh.mode(),
- sk_ref_sp(mesh.vertexBuffer()), mesh.vertexCount(),
- mesh.vertexOffset(), sk_ref_sp(mesh.indexBuffer()),
- mesh.indexCount(), mesh.indexOffset(),
- wrapper->builder.fUniforms, mesh.bounds())
- .mesh;
- } else {
- wrapper->mesh = SkMesh::Make(sk_ref_sp(mesh.spec()), mesh.mode(),
- sk_ref_sp(mesh.vertexBuffer()), mesh.vertexCount(),
- mesh.vertexOffset(), wrapper->builder.fUniforms, mesh.bounds())
- .mesh;
- }
+ return reinterpret_cast<jlong>(meshPtr);
}
static inline int ThrowIAEFmt(JNIEnv* env, const char* fmt, ...) {
@@ -154,19 +129,21 @@ static void nativeUpdateFloatUniforms(JNIEnv* env, MeshUniformBuilder* builder,
static void updateFloatUniforms(JNIEnv* env, jobject, jlong meshWrapper, jstring uniformName,
jfloat value1, jfloat value2, jfloat value3, jfloat value4,
jint count) {
- auto* wrapper = reinterpret_cast<MeshWrapper*>(meshWrapper);
+ auto* wrapper = reinterpret_cast<Mesh*>(meshWrapper);
ScopedUtfChars name(env, uniformName);
const float values[4] = {value1, value2, value3, value4};
- nativeUpdateFloatUniforms(env, &wrapper->builder, name.c_str(), values, count, false);
+ nativeUpdateFloatUniforms(env, wrapper->uniformBuilder(), name.c_str(), values, count, false);
+ wrapper->markDirty();
}
static void updateFloatArrayUniforms(JNIEnv* env, jobject, jlong meshWrapper, jstring jUniformName,
jfloatArray jvalues, jboolean isColor) {
- auto wrapper = reinterpret_cast<MeshWrapper*>(meshWrapper);
+ auto wrapper = reinterpret_cast<Mesh*>(meshWrapper);
ScopedUtfChars name(env, jUniformName);
AutoJavaFloatArray autoValues(env, jvalues, 0, kRO_JNIAccess);
- nativeUpdateFloatUniforms(env, &wrapper->builder, name.c_str(), autoValues.ptr(),
+ nativeUpdateFloatUniforms(env, wrapper->uniformBuilder(), name.c_str(), autoValues.ptr(),
autoValues.length(), isColor);
+ wrapper->markDirty();
}
static void nativeUpdateIntUniforms(JNIEnv* env, MeshUniformBuilder* builder,
@@ -185,22 +162,24 @@ static void nativeUpdateIntUniforms(JNIEnv* env, MeshUniformBuilder* builder,
static void updateIntUniforms(JNIEnv* env, jobject, jlong meshWrapper, jstring uniformName,
jint value1, jint value2, jint value3, jint value4, jint count) {
- auto wrapper = reinterpret_cast<MeshWrapper*>(meshWrapper);
+ auto wrapper = reinterpret_cast<Mesh*>(meshWrapper);
ScopedUtfChars name(env, uniformName);
const int values[4] = {value1, value2, value3, value4};
- nativeUpdateIntUniforms(env, &wrapper->builder, name.c_str(), values, count);
+ nativeUpdateIntUniforms(env, wrapper->uniformBuilder(), name.c_str(), values, count);
+ wrapper->markDirty();
}
static void updateIntArrayUniforms(JNIEnv* env, jobject, jlong meshWrapper, jstring uniformName,
jintArray values) {
- auto wrapper = reinterpret_cast<MeshWrapper*>(meshWrapper);
+ auto wrapper = reinterpret_cast<Mesh*>(meshWrapper);
ScopedUtfChars name(env, uniformName);
AutoJavaIntArray autoValues(env, values, 0);
- nativeUpdateIntUniforms(env, &wrapper->builder, name.c_str(), autoValues.ptr(),
+ nativeUpdateIntUniforms(env, wrapper->uniformBuilder(), name.c_str(), autoValues.ptr(),
autoValues.length());
+ wrapper->markDirty();
}
-static void MeshWrapper_destroy(MeshWrapper* wrapper) {
+static void MeshWrapper_destroy(Mesh* wrapper) {
delete wrapper;
}
@@ -213,7 +192,6 @@ static const JNINativeMethod gMeshMethods[] = {
{"nativeMake", "(JILjava/nio/Buffer;ZIIFFFF)J", (void*)make},
{"nativeMakeIndexed", "(JILjava/nio/Buffer;ZIILjava/nio/ShortBuffer;ZIIFFFF)J",
(void*)makeIndexed},
- {"nativeUpdateMesh", "(JZ)V", (void*)updateMesh},
{"nativeUpdateUniforms", "(JLjava/lang/String;[FZ)V", (void*)updateFloatArrayUniforms},
{"nativeUpdateUniforms", "(JLjava/lang/String;FFFFI)V", (void*)updateFloatUniforms},
{"nativeUpdateUniforms", "(JLjava/lang/String;[I)V", (void*)updateIntArrayUniforms},
@@ -224,4 +202,4 @@ int register_android_graphics_Mesh(JNIEnv* env) {
return 0;
}
-} // namespace android
+} // namespace android \ No newline at end of file
diff --git a/libs/hwui/jni/text/GraphemeBreak.cpp b/libs/hwui/jni/text/GraphemeBreak.cpp
new file mode 100644
index 000000000000..55f03bd9f7b1
--- /dev/null
+++ b/libs/hwui/jni/text/GraphemeBreak.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "GraphemeBreaker"
+
+#include <minikin/GraphemeBreak.h>
+#include <nativehelper/ScopedPrimitiveArray.h>
+
+#include "GraphicsJNI.h"
+
+namespace android {
+
+static void nIsGraphemeBreak(JNIEnv* env, jclass, jfloatArray advances, jcharArray text, jint start,
+ jint end, jbooleanArray isGraphemeBreak) {
+ if (start > end || env->GetArrayLength(advances) < end ||
+ env->GetArrayLength(isGraphemeBreak) < end - start) {
+ doThrowAIOOBE(env);
+ }
+
+ if (start == end) {
+ return;
+ }
+
+ ScopedFloatArrayRO advancesArray(env, advances);
+ ScopedCharArrayRO textArray(env, text);
+ ScopedBooleanArrayRW isGraphemeBreakArray(env, isGraphemeBreak);
+
+ size_t count = end - start;
+ for (size_t offset = 0; offset < count; ++offset) {
+ bool isBreak = minikin::GraphemeBreak::isGraphemeBreak(advancesArray.get(), textArray.get(),
+ start, end, start + offset);
+ isGraphemeBreakArray[offset] = isBreak ? JNI_TRUE : JNI_FALSE;
+ }
+}
+
+static const JNINativeMethod gMethods[] = {
+ {"nIsGraphemeBreak",
+ "("
+ "[F" // advances
+ "[C" // text
+ "I" // start
+ "I" // end
+ "[Z" // isGraphemeBreak
+ ")V",
+ (void*)nIsGraphemeBreak},
+};
+
+int register_android_graphics_text_GraphemeBreak(JNIEnv* env) {
+ return RegisterMethodsOrDie(env, "android/graphics/text/GraphemeBreak", gMethods,
+ NELEM(gMethods));
+}
+
+} // namespace android
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
index fcfc4f82abed..af2d3b34bac7 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
@@ -23,6 +23,7 @@
#else
#include "DamageAccumulator.h"
#endif
+#include "TreeInfo.h"
#include "VectorDrawable.h"
#ifdef __ANDROID__
#include "renderthread/CanvasContext.h"
@@ -102,6 +103,12 @@ bool SkiaDisplayList::prepareListAndChildren(
info.prepareTextures = false;
info.canvasContext.unpinImages();
}
+
+ auto grContext = info.canvasContext.getGrContext();
+ for (auto mesh : mMeshes) {
+ mesh->updateSkMesh(grContext);
+ }
+
#endif
bool hasBackwardProjectedNodesHere = false;
@@ -168,6 +175,7 @@ void SkiaDisplayList::reset() {
mDisplayList.reset();
+ mMeshes.clear();
mMutableImages.clear();
mVectorDrawables.clear();
mAnimatedImages.clear();
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.h b/libs/hwui/pipeline/skia/SkiaDisplayList.h
index 2a677344b7b2..7af31a4dc4c6 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.h
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.h
@@ -18,6 +18,7 @@
#include <deque>
+#include "Mesh.h"
#include "RecordingCanvas.h"
#include "RenderNodeDrawable.h"
#include "TreeInfo.h"
@@ -167,6 +168,7 @@ public:
std::deque<RenderNodeDrawable> mChildNodes;
std::deque<FunctorDrawable*> mChildFunctors;
std::vector<SkImage*> mMutableImages;
+ std::vector<const Mesh*> mMeshes;
private:
std::vector<Pair<VectorDrawableRoot*, SkMatrix>> mVectorDrawables;
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index e1c8877a8b7a..3ca7eeb37a89 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -321,6 +321,11 @@ double SkiaRecordingCanvas::drawAnimatedImage(AnimatedImageDrawable* animatedIma
return 0;
}
+void SkiaRecordingCanvas::drawMesh(const Mesh& mesh, sk_sp<SkBlender> blender, const Paint& paint) {
+ mDisplayList->mMeshes.push_back(&mesh);
+ mRecorder.drawMesh(mesh, blender, paint);
+}
+
} // namespace skiapipeline
} // namespace uirenderer
} // namespace android
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
index 3fd8fa3aa9a9..a8e4580dc200 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
@@ -81,6 +81,7 @@ public:
virtual void drawVectorDrawable(VectorDrawableRoot* vectorDrawable) override;
virtual void enableZ(bool enableZ) override;
+ virtual void drawMesh(const Mesh& mesh, sk_sp<SkBlender> blender, const Paint& paint) override;
virtual void drawLayer(uirenderer::DeferredLayerUpdater* layerHandle) override;
virtual void drawRenderNode(uirenderer::RenderNode* renderNode) override;
diff --git a/location/java/android/location/GnssCapabilities.java b/location/java/android/location/GnssCapabilities.java
index c6f32c2cd387..88f00dc38cb3 100644
--- a/location/java/android/location/GnssCapabilities.java
+++ b/location/java/android/location/GnssCapabilities.java
@@ -123,6 +123,21 @@ public final class GnssCapabilities implements Parcelable {
@Retention(RetentionPolicy.SOURCE)
public @interface SubHalPowerCapabilityFlags {}
+ /** The capability is unknown to be supported or not. */
+ public static final int CAPABILITY_UNKNOWN = 0;
+ /** The capability is supported. */
+ public static final int CAPABILITY_SUPPORTED = 1;
+ /** The capability is not supported. */
+ public static final int CAPABILITY_UNSUPPORTED = 2;
+
+ /** @hide */
+ @IntDef(flag = true, prefix = {"CAPABILITY_"}, value = {CAPABILITY_UNKNOWN,
+ CAPABILITY_SUPPORTED,
+ CAPABILITY_UNSUPPORTED})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CapabilitySupportType {}
+
+
/**
* Returns an empty GnssCapabilities object.
*
@@ -375,30 +390,25 @@ public final class GnssCapabilities implements Parcelable {
}
/**
- * Returns {@code true} if GNSS chipset supports accumulated delta range, {@code false}
- * otherwise.
- *
- * <p>The value is only known if {@link #isAccumulatedDeltaRangeCapabilityKnown()} is
- * true.
+ * Returns {@link #CAPABILITY_SUPPORTED} if GNSS chipset supports accumulated delta
+ * range, {@link #CAPABILITY_UNSUPPORTED} if GNSS chipset does not support accumulated
+ * delta range, and {@link #CAPABILITY_UNKNOWN} if it is unknown, which means GNSS
+ * chipset may or may not support accumulated delta range.
*
* <p>The accumulated delta range information can be queried in
* {@link android.location.GnssMeasurement#getAccumulatedDeltaRangeState()},
* {@link android.location.GnssMeasurement#getAccumulatedDeltaRangeMeters()}, and
* {@link android.location.GnssMeasurement#getAccumulatedDeltaRangeUncertaintyMeters()}.
*/
- public boolean hasAccumulatedDeltaRange() {
+ public @CapabilitySupportType int hasAccumulatedDeltaRange() {
if (!mIsAdrCapabilityKnown) {
- throw new IllegalStateException("Accumulated delta range capability is unknown.");
+ return CAPABILITY_UNKNOWN;
+ }
+ if ((mTopFlags & TOP_HAL_CAPABILITY_ACCUMULATED_DELTA_RANGE) != 0) {
+ return CAPABILITY_SUPPORTED;
+ } else {
+ return CAPABILITY_UNSUPPORTED;
}
- return (mTopFlags & TOP_HAL_CAPABILITY_ACCUMULATED_DELTA_RANGE) != 0;
- }
-
- /**
- * Returns {@code true} if {@link #hasAccumulatedDeltaRange()} is known, {@code false}
- * otherwise.
- */
- public boolean isAccumulatedDeltaRangeCapabilityKnown() {
- return mIsAdrCapabilityKnown;
}
/**
@@ -597,9 +607,9 @@ public final class GnssCapabilities implements Parcelable {
if (hasMeasurementCorrectionsForDriving()) {
builder.append("MEASUREMENT_CORRECTIONS_FOR_DRIVING ");
}
- if (mIsAdrCapabilityKnown && hasAccumulatedDeltaRange()) {
+ if (hasAccumulatedDeltaRange() == CAPABILITY_SUPPORTED) {
builder.append("ACCUMULATED_DELTA_RANGE ");
- } else if (!mIsAdrCapabilityKnown) {
+ } else if (hasAccumulatedDeltaRange() == CAPABILITY_UNKNOWN) {
builder.append("ACCUMULATED_DELTA_RANGE(unknown) ");
}
if (hasMeasurementCorrectionsLosSats()) {
@@ -795,19 +805,17 @@ public final class GnssCapabilities implements Parcelable {
/**
* Sets accumulated delta range capability.
*/
- public @NonNull Builder setHasAccumulatedDeltaRange(boolean capable) {
- mIsAdrCapabilityKnown = true;
- mTopFlags = setFlag(mTopFlags, TOP_HAL_CAPABILITY_ACCUMULATED_DELTA_RANGE,
- capable);
- return this;
- }
-
- /**
- * Clears accumulated delta range capability and sets it as unknown.
- */
- public @NonNull Builder clearIsAccumulatedDeltaRangeCapabilityKnown() {
- mIsAdrCapabilityKnown = false;
- mTopFlags = setFlag(mTopFlags, TOP_HAL_CAPABILITY_ACCUMULATED_DELTA_RANGE, false);
+ public @NonNull Builder setHasAccumulatedDeltaRange(@CapabilitySupportType int capable) {
+ if (capable == CAPABILITY_UNKNOWN) {
+ mIsAdrCapabilityKnown = false;
+ mTopFlags = setFlag(mTopFlags, TOP_HAL_CAPABILITY_ACCUMULATED_DELTA_RANGE, false);
+ } else if (capable == CAPABILITY_SUPPORTED) {
+ mIsAdrCapabilityKnown = true;
+ mTopFlags = setFlag(mTopFlags, TOP_HAL_CAPABILITY_ACCUMULATED_DELTA_RANGE, true);
+ } else if (capable == CAPABILITY_UNSUPPORTED) {
+ mIsAdrCapabilityKnown = true;
+ mTopFlags = setFlag(mTopFlags, TOP_HAL_CAPABILITY_ACCUMULATED_DELTA_RANGE, false);
+ }
return this;
}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index f32cd8e71a1e..4da4c7fc56de 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -16,9 +16,9 @@
package android.media;
-import static android.companion.virtual.VirtualDeviceManager.DEVICE_ID_DEFAULT;
import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT;
import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_AUDIO;
+import static android.content.Context.DEVICE_ID_DEFAULT;
import android.Manifest;
import android.annotation.CallbackExecutor;
@@ -9224,11 +9224,12 @@ public class AudioManager {
// Preferred mixer attributes
/**
- * Returns the {@link AudioMixerAttributes} that can be used to set as preferred mixe
+ * Returns the {@link AudioMixerAttributes} that can be used to set as preferred mixer
* attributes via {@link #setPreferredMixerAttributes(
* AudioAttributes, AudioDeviceInfo, AudioMixerAttributes)}.
- * <p>Note that only USB devices are guaranteed to expose configurable mixer attributes, the
- * returned list may be empty when devices do not allow dynamic configuration.
+ * <p>Note that only USB devices are guaranteed to expose configurable mixer attributes. An
+ * empty list may be returned for all other types of devices as they may not allow dynamic
+ * configuration.
*
* @param device the device to query
* @return a list of {@link AudioMixerAttributes} that can be used as preferred mixer attributes
@@ -9246,9 +9247,8 @@ public class AudioManager {
/**
* Configures the mixer attributes for a particular {@link AudioAttributes} over a given
* {@link AudioDeviceInfo}.
- * <p>When constructing an {@link AudioMixerAttributes} for setting preferred mixer attributes,
- * the mixer format must be constructed from an {@link AudioProfile} that can be used to set
- * preferred mixer attributes.
+ * <p>Call {@link #getSupportedMixerAttributes(AudioDeviceInfo)} to determine which mixer
+ * attributes can be used with the given device.
* <p>The ownership of preferred mixer attributes is recognized by uid. When a playback from the
* same uid is routed to the given audio device when calling this API, the output mixer/stream
* will be configured with the values previously set via this API.
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index b6ab262b60c5..7faa13c80c62 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -16,9 +16,9 @@
package android.media;
-import static android.companion.virtual.VirtualDeviceManager.DEVICE_ID_DEFAULT;
import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT;
import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_AUDIO;
+import static android.content.Context.DEVICE_ID_DEFAULT;
import static android.media.AudioManager.AUDIO_SESSION_ID_GENERATE;
import android.annotation.CallbackExecutor;
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index 0b086816ca4b..faa7f7fa3aa1 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -3049,7 +3049,13 @@ public final class MediaDrm implements AutoCloseable {
/**
- * Gets the {@link LogSessionId}.
+ * Sets the {@link LogSessionId}.
+ *
+ * <p>The implementation of this method varies by DRM provider; Please refer
+ * to your DRM provider documentation for more details on this method.
+ *
+ * @throws UnsupportedOperationException when the vendor plugin does not
+ * implement this method
*/
public void setLogSessionId(@NonNull LogSessionId logSessionId) {
Objects.requireNonNull(logSessionId);
diff --git a/media/java/android/media/PlayerBase.java b/media/java/android/media/PlayerBase.java
index 38115e19d608..3f44b09124e4 100644
--- a/media/java/android/media/PlayerBase.java
+++ b/media/java/android/media/PlayerBase.java
@@ -16,9 +16,9 @@
package android.media;
-import static android.companion.virtual.VirtualDeviceManager.DEVICE_ID_DEFAULT;
import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT;
import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_AUDIO;
+import static android.content.Context.DEVICE_ID_DEFAULT;
import static android.media.AudioManager.AUDIO_SESSION_ID_GENERATE;
import android.annotation.NonNull;
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index 40a4858d30ba..d2b21ae19162 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -849,7 +849,7 @@ public class RingtoneManager {
if (ringtoneUri != null) {
final Uri cacheUri = getCacheForType(type, context.getUserId());
try (InputStream in = openRingtone(context, ringtoneUri);
- OutputStream out = resolver.openOutputStream(cacheUri)) {
+ OutputStream out = resolver.openOutputStream(cacheUri, "wt")) {
FileUtils.copy(in, out);
} catch (IOException e) {
Log.w(TAG, "Failed to cache ringtone: " + e);
diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java b/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java
index afc2bb1ae7d1..6eed4832847f 100644
--- a/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java
+++ b/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java
@@ -190,9 +190,7 @@ public class ITvInteractiveAppSessionWrapper
break;
}
case DO_SEND_TIME_SHIFT_MODE: {
- SomeArgs args = (SomeArgs) msg.obj;
- mSessionImpl.sendTimeShiftMode(args.argi1);
- args.recycle();
+ mSessionImpl.sendTimeShiftMode((Integer) msg.obj);
break;
}
case DO_SEND_AVAILABLE_SPEEDS: {
@@ -447,7 +445,7 @@ public class ITvInteractiveAppSessionWrapper
@Override
public void sendTimeShiftMode(int mode) {
- mCaller.executeOrSendMessage(mCaller.obtainMessageI(DO_SEND_TIME_SHIFT_MODE, mode));
+ mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_SEND_TIME_SHIFT_MODE, mode));
}
@Override
diff --git a/media/java/android/media/tv/tuner/frontend/IptvFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/IptvFrontendSettings.java
index ba751027a3e4..65247a1a9efd 100644
--- a/media/java/android/media/tv/tuner/frontend/IptvFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/IptvFrontendSettings.java
@@ -34,7 +34,7 @@ import java.lang.annotation.RetentionPolicy;
* @hide
*/
@SystemApi
-public class IptvFrontendSettings extends FrontendSettings {
+public final class IptvFrontendSettings extends FrontendSettings {
/** @hide */
@IntDef(prefix = "PROTOCOL_",
value = {PROTOCOL_UNDEFINED, PROTOCOL_UDP, PROTOCOL_RTP})
@@ -181,14 +181,6 @@ public class IptvFrontendSettings extends FrontendSettings {
}
/**
- * Creates a builder for {@link IptvFrontendSettings}.
- */
- @NonNull
- public static Builder builder() {
- return new Builder();
- }
-
- /**
* Builder for {@link IptvFrontendSettings}.
*/
public static final class Builder {
@@ -202,7 +194,7 @@ public class IptvFrontendSettings extends FrontendSettings {
private long mBitrate = 0;
private String mContentUrl = "";
- private Builder() {
+ public Builder() {
}
/**
@@ -309,8 +301,8 @@ public class IptvFrontendSettings extends FrontendSettings {
*/
@NonNull
public IptvFrontendSettings build() {
- return new IptvFrontendSettings(mSrcIpAddress, mDstIpAddress, mSrcPort,
- mDstPort, mFec, mProtocol, mIgmp, mBitrate, mContentUrl);
+ return new IptvFrontendSettings(mSrcIpAddress, mDstIpAddress, mSrcPort, mDstPort,
+ mFec, mProtocol, mIgmp, mBitrate, mContentUrl);
}
}
diff --git a/media/java/android/media/tv/tuner/frontend/IptvFrontendSettingsFec.java b/media/java/android/media/tv/tuner/frontend/IptvFrontendSettingsFec.java
index a70af17c9652..12eebee81bd7 100644
--- a/media/java/android/media/tv/tuner/frontend/IptvFrontendSettingsFec.java
+++ b/media/java/android/media/tv/tuner/frontend/IptvFrontendSettingsFec.java
@@ -31,7 +31,7 @@ import java.lang.annotation.RetentionPolicy;
* @hide
*/
@SystemApi
-public class IptvFrontendSettingsFec {
+public final class IptvFrontendSettingsFec {
/** @hide */
@IntDef(prefix = "FEC_TYPE_",
value = {FEC_TYPE_UNDEFINED, FEC_TYPE_COLUMN, FEC_TYPE_ROW, FEC_TYPE_COLUMN_ROW})
@@ -93,14 +93,6 @@ public class IptvFrontendSettingsFec {
}
/**
- * Creates a builder for {@link IptvFrontendSettingsFec}.
- */
- @NonNull
- public static Builder builder() {
- return new Builder();
- }
-
- /**
* Builder for {@link IptvFrontendSettingsFec}.
*/
public static final class Builder {
@@ -108,7 +100,7 @@ public class IptvFrontendSettingsFec {
private int mFecRowNum;
private int mFecColNum;
- private Builder() {
+ public Builder() {
}
/**
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/AudioManagerUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/AudioManagerUnitTest.java
index 76543f4ce989..6089f4291f3e 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/AudioManagerUnitTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/AudioManagerUnitTest.java
@@ -17,10 +17,10 @@
package com.android.mediaframeworktest.unit;
-import static android.companion.virtual.VirtualDeviceManager.DEVICE_ID_DEFAULT;
import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_CUSTOM;
import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT;
import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_AUDIO;
+import static android.content.Context.DEVICE_ID_DEFAULT;
import static android.media.AudioManager.FX_KEY_CLICK;
import static org.mockito.ArgumentMatchers.anyInt;
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/AudioRecordUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/AudioRecordUnitTest.java
index 9c813c28d7d9..71228e2120c0 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/AudioRecordUnitTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/AudioRecordUnitTest.java
@@ -16,10 +16,10 @@
package com.android.mediaframeworktest.unit;
-import static android.companion.virtual.VirtualDeviceManager.DEVICE_ID_DEFAULT;
import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_CUSTOM;
import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT;
import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_AUDIO;
+import static android.content.Context.DEVICE_ID_DEFAULT;
import static android.media.AudioManager.AUDIO_SESSION_ID_GENERATE;
import static org.junit.Assert.assertEquals;
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/AudioTrackUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/AudioTrackUnitTest.java
index ffed39ac82bf..ac24a1007170 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/AudioTrackUnitTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/AudioTrackUnitTest.java
@@ -16,10 +16,10 @@
package com.android.mediaframeworktest.unit;
-import static android.companion.virtual.VirtualDeviceManager.DEVICE_ID_DEFAULT;
import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_CUSTOM;
import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT;
import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_AUDIO;
+import static android.content.Context.DEVICE_ID_DEFAULT;
import static android.media.AudioManager.AUDIO_SESSION_ID_GENERATE;
import static org.junit.Assert.assertEquals;
diff --git a/packages/AppPredictionLib/Android.bp b/packages/AppPredictionLib/Android.bp
index 5a68fdc9ae75..31c193631602 100644
--- a/packages/AppPredictionLib/Android.bp
+++ b/packages/AppPredictionLib/Android.bp
@@ -25,7 +25,7 @@ android_library {
name: "app_prediction",
sdk_version: "system_current",
- min_sdk_version: "system_current",
+ min_sdk_version: "current",
srcs: [
"src/**/*.java",
diff --git a/packages/CarrierDefaultApp/res/values-af/strings.xml b/packages/CarrierDefaultApp/res/values-af/strings.xml
index 13ae4dad7727..cb911d8f95da 100644
--- a/packages/CarrierDefaultApp/res/values-af/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-af/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Byvoorbeeld, die aanmeldbladsy behoort dalk nie aan die organisasie wat gewys word nie."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Gaan in elk geval deur blaaier voort"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Prestasiehupstoot"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Verbeter jou 5G-ervaring"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s beveel aan dat jy ’n werkverrigtinghupstootpakket koop. Tik om deur %2$s te koop."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Nie nou nie"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Bestuur"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Koop ’n prestasiehupstoot."</string>
diff --git a/packages/CarrierDefaultApp/res/values-am/strings.xml b/packages/CarrierDefaultApp/res/values-am/strings.xml
index e1f91ceb9cc2..edaa2486a6f5 100644
--- a/packages/CarrierDefaultApp/res/values-am/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-am/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ለምሳሌ፣ የመግቢያ ገጹ የሚታየው ድርጅት ላይሆን ይችላል።"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"ለማንኛውም በአሳሽ በኩል ይቀጥሉ"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"የአፈጻጸም ጭማሪ"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"የእርስዎን የ5ጂ ተሞክሮ ያሻሽሉ"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s የአፈጻጸም መጨመሪያ ዕቅድ መግዛትን ይመክራል። በ%2$s ለመግዛት መታ ያድርጉ።"</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"አሁን አይደለም"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"አስተዳድር"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"የአፈጻጸም ጭማሪ ይግዙ።"</string>
diff --git a/packages/CarrierDefaultApp/res/values-ar/strings.xml b/packages/CarrierDefaultApp/res/values-ar/strings.xml
index c2e5ba80db46..9bc5e459f9ce 100644
--- a/packages/CarrierDefaultApp/res/values-ar/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ar/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"على سبيل المثال، قد لا تنتمي صفحة تسجيل الدخول إلى المؤسسة المعروضة."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"المتابعة على أي حال عبر المتصفح"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"تطبيق تعزيز الأداء"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"تحسين تجربة شبكة الجيل الخامس"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"‏هناك اقتراح من ‏\"%1$s\" لشراء خطة لتعزيز الأداء. انقر للشراء من خلال ‏\"%2$s\"."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"لاحقًا"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"إدارة"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"شراء تطبيق تعزيز الأداء"</string>
diff --git a/packages/CarrierDefaultApp/res/values-as/strings.xml b/packages/CarrierDefaultApp/res/values-as/strings.xml
index 8881940ff71a..732c52dc6717 100644
--- a/packages/CarrierDefaultApp/res/values-as/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-as/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"উদাহৰণস্বৰূপে, আপোনাক দেখুওৱা লগ ইনৰ পৃষ্ঠাটো প্ৰতিষ্ঠানটোৰ নিজা নহ\'বও পাৰে।"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"তথাপিও ব্ৰাউজাৰৰ জৰিয়তে অব্যাহত ৰাখক"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"কাৰ্যক্ষমতা পৰিৱৰ্ধন"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"আপোনাৰ 5G অভিজ্ঞতা উন্নত কৰক"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$sএ এখন কাৰ্যক্ষমতা পৰিৱৰ্ধন অঁচনি ক্ৰয় কৰাৰ চুপাৰিছ কৰে। %2$sৰ জৰিয়তে ক্ৰয় কৰিবলৈ টিপক।"</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"এতিয়া নহয়"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"পৰিচালনা কৰক"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"এটা কাৰ্যক্ষমতা পৰিৱৰ্ধন ক্ৰয় কৰক।"</string>
diff --git a/packages/CarrierDefaultApp/res/values-az/strings.xml b/packages/CarrierDefaultApp/res/values-az/strings.xml
index f64fcb62ae95..05c300f5217b 100644
--- a/packages/CarrierDefaultApp/res/values-az/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-az/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Məsələn, giriş səhifəsi göstərilən təşkilata aid olmaya bilər."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Hər bir halda brazuer ilə davam edin"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Performans artırması"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"5G təcrübənizi təkmilləşdirin"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s performans artırma planı almağı tövsiyə edir. %2$s ilə almaq üçün toxunun."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"İndi yox"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"İdarə edin"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Performans artırması alın."</string>
diff --git a/packages/CarrierDefaultApp/res/values-b+sr+Latn/strings.xml b/packages/CarrierDefaultApp/res/values-b+sr+Latn/strings.xml
index 5533bfd1d1e2..deeb5c732c69 100644
--- a/packages/CarrierDefaultApp/res/values-b+sr+Latn/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-b+sr+Latn/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Na primer, stranica za prijavljivanje možda ne pripada prikazanoj organizaciji."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Ipak nastavi preko pregledača"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Poboljšanje učinka"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Poboljšajte 5G doživljaj"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s preporučuje kupovinu paketa za poboljšanje performansi. Dodirnite da biste kupili preko %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ne sada"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Upravljaj"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Kupite poboljšanje učinka."</string>
diff --git a/packages/CarrierDefaultApp/res/values-be/strings.xml b/packages/CarrierDefaultApp/res/values-be/strings.xml
index 0053cdaa70c3..4f820ca296f7 100644
--- a/packages/CarrierDefaultApp/res/values-be/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-be/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Напрыклад, старонка ўваходу можа не належаць указанай арганізацыі."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Усё роўна працягнуць праз браўзер"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Павышэнне прадукцыйнасці"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Пашырце магчымасці 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s рэкамендуе купіць план павышэння прадукцыйнасці. Націсніце, каб купіць праз %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Не цяпер"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Кіраваць"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Аплаціце павышэнне прадукцыйнасці."</string>
diff --git a/packages/CarrierDefaultApp/res/values-bg/strings.xml b/packages/CarrierDefaultApp/res/values-bg/strings.xml
index a37e0a36454e..a32c632e269c 100644
--- a/packages/CarrierDefaultApp/res/values-bg/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-bg/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Например страницата за вход може да не принадлежи на показаната организация."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Продължаване през браузър въпреки това"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Увеличаване на ефективността"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Подобряване на практическата работа с 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s препоръчва да купите план за увеличаване на ефективността. Докоснете, за да купите чрез %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Не сега"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Управление"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Купете пакет за увеличаване на ефективността."</string>
diff --git a/packages/CarrierDefaultApp/res/values-bn/strings.xml b/packages/CarrierDefaultApp/res/values-bn/strings.xml
index f78449c8aa98..ac4fab43dae1 100644
--- a/packages/CarrierDefaultApp/res/values-bn/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-bn/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"যেমন, লগ-ইন পৃষ্ঠাটি যে প্রতিষ্ঠানের পৃষ্ঠা বলে দেখানো আছে, আসলে তা নাও হতে পারে৷"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"যাই হোক, ব্রাউজারের মাধ্যমে চালিয়ে যান"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"পারফর্ম্যান্স বুস্ট"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"আপনার 5G অভিজ্ঞতা উন্নত করুন"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s পারফর্ম্যান্স বুস্ট প্ল্যান কেনার সাজেশন দেয়। %2$s-এর মাধ্যমে কিনতে ট্যাপ করুন।"</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"এখন নয়"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"ম্যানেজ করুন"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"পারফর্ম্যান্স বুস্ট সংক্রান্ত ফিচার কিনুন।"</string>
diff --git a/packages/CarrierDefaultApp/res/values-bs/strings.xml b/packages/CarrierDefaultApp/res/values-bs/strings.xml
index 7be8e2b9d177..cc59f9dbfdde 100644
--- a/packages/CarrierDefaultApp/res/values-bs/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-bs/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Naprimjer, stranica za prijavljivanje možda ne pripada prikazanoj organizaciji."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Ipak nastavi preko preglednika"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Pojačavanje performansi"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Poboljšajte iskustvo s 5G mrežom"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s preporučuje kupovinu paketa za poboljšanje performansi. Dodirnite da kupite koristeći %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ne sada"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Upravljajte"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Kupite pojačavanje performansi."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ca/strings.xml b/packages/CarrierDefaultApp/res/values-ca/strings.xml
index 54c9e6ed43f1..ded2263b3c46 100644
--- a/packages/CarrierDefaultApp/res/values-ca/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ca/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Per exemple, la pàgina d\'inici de sessió podria no pertànyer a l\'organització que es mostra."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continua igualment mitjançant el navegador"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Optimització de rendiment"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Millora l\'experiència 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recomana comprar un pla d\'optimització de rendiment. Toca per comprar-lo mitjançant %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ara no"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gestiona"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Compra una optimització de rendiment."</string>
diff --git a/packages/CarrierDefaultApp/res/values-cs/strings.xml b/packages/CarrierDefaultApp/res/values-cs/strings.xml
index 8a09421cd369..d21c500dcae1 100644
--- a/packages/CarrierDefaultApp/res/values-cs/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-cs/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Přihlašovací stránka například nemusí patřit zobrazované organizaci."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Přesto pokračovat prostřednictvím prohlížeče"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Zvýšení výkonu"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Získejte rychlejší připojení 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s doporučuje zakoupit zvýšení výkonu. Klepnutím ho zakoupíte přes operátora %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Teď ne"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Spravovat"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Kupte si zvýšení výkonu."</string>
diff --git a/packages/CarrierDefaultApp/res/values-da/strings.xml b/packages/CarrierDefaultApp/res/values-da/strings.xml
index cd411c917fb6..192036d10b4f 100644
--- a/packages/CarrierDefaultApp/res/values-da/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-da/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Det er f.eks. ikke sikkert, at loginsiden tilhører den anførte organisation."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Fortsæt alligevel via browseren"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Ydeevneboost"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Få en bedre 5G-oplevelse"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s anbefaler, at du køber et abonnement med ydeevneboost. Tryk for at købe via %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ikke nu"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Administrer"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Køb et ydeevneboost."</string>
diff --git a/packages/CarrierDefaultApp/res/values-de/strings.xml b/packages/CarrierDefaultApp/res/values-de/strings.xml
index d20a1e88fcda..0226d9f70ba8 100644
--- a/packages/CarrierDefaultApp/res/values-de/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-de/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Beispiel: Die Log-in-Seite gehört eventuell nicht zur angezeigten Organisation."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Trotzdem in einem Browser fortfahren"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Leistungs-Boost"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"5G-Nutzung verbessern"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s empfiehlt den Kauf eines Tarifs mit Leistungs-Boost. Du kannst tippen, um über %2$s einen zu kaufen."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Nicht jetzt"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Verwalten"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Leistungs-Boost erwerben."</string>
diff --git a/packages/CarrierDefaultApp/res/values-el/strings.xml b/packages/CarrierDefaultApp/res/values-el/strings.xml
index 0759011f5f39..96e3eb342e4c 100644
--- a/packages/CarrierDefaultApp/res/values-el/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-el/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Για παράδειγμα, η σελίδα σύνδεσης ενδέχεται να μην ανήκει στον οργανισμό που εμφανίζεται."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Συνέχεια ούτως ή άλλως μέσω του προγράμματος περιήγησης"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Ενίσχυση απόδοσης"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Βελτιώστε την εμπειρία 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"Το %1$s προτείνει την αγορά ενός προγράμματος ενίσχυσης απόδοσης. Πατήστε για αγορά μέσω %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Όχι τώρα"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Διαχείριση"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Αγοράστε μια ενίσχυση απόδοσης."</string>
diff --git a/packages/CarrierDefaultApp/res/values-en-rAU/strings.xml b/packages/CarrierDefaultApp/res/values-en-rAU/strings.xml
index 720dbc7fe7c0..aac44fc876a7 100644
--- a/packages/CarrierDefaultApp/res/values-en-rAU/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-en-rAU/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"For example, the login page might not belong to the organisation shown."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continue anyway via browser"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Performance boost"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Improve your 5G experience"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recommends buying a performance boost plan. Tap to buy through %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Not now"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Manage"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Purchase a performance boost."</string>
diff --git a/packages/CarrierDefaultApp/res/values-en-rCA/strings.xml b/packages/CarrierDefaultApp/res/values-en-rCA/strings.xml
index 87978ac33372..d8ec2104098c 100644
--- a/packages/CarrierDefaultApp/res/values-en-rCA/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-en-rCA/strings.xml
@@ -15,8 +15,8 @@
<string name="ssl_error_example" msgid="6188711843183058764">"For example, the login page may not belong to the organization shown."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continue anyway via browser"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Performance boost"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Improve your 5G experience"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recommends buying a performance boost plan. Tap to buy through %2$s."</string>
+ <string name="performance_boost_notification_title" msgid="6091638924925876776">"Improve your app experience"</string>
+ <string name="performance_boost_notification_detail" msgid="86969987181456032">"Tap to visit %s\'s website and learn more."</string>
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Not now"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Manage"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Purchase a performance boost."</string>
diff --git a/packages/CarrierDefaultApp/res/values-en-rGB/strings.xml b/packages/CarrierDefaultApp/res/values-en-rGB/strings.xml
index 720dbc7fe7c0..aac44fc876a7 100644
--- a/packages/CarrierDefaultApp/res/values-en-rGB/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-en-rGB/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"For example, the login page might not belong to the organisation shown."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continue anyway via browser"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Performance boost"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Improve your 5G experience"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recommends buying a performance boost plan. Tap to buy through %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Not now"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Manage"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Purchase a performance boost."</string>
diff --git a/packages/CarrierDefaultApp/res/values-en-rIN/strings.xml b/packages/CarrierDefaultApp/res/values-en-rIN/strings.xml
index 720dbc7fe7c0..aac44fc876a7 100644
--- a/packages/CarrierDefaultApp/res/values-en-rIN/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-en-rIN/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"For example, the login page might not belong to the organisation shown."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continue anyway via browser"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Performance boost"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Improve your 5G experience"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recommends buying a performance boost plan. Tap to buy through %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Not now"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Manage"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Purchase a performance boost."</string>
diff --git a/packages/CarrierDefaultApp/res/values-en-rXC/strings.xml b/packages/CarrierDefaultApp/res/values-en-rXC/strings.xml
index 7324a5bcc1f9..87b007f25650 100644
--- a/packages/CarrierDefaultApp/res/values-en-rXC/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-en-rXC/strings.xml
@@ -15,8 +15,8 @@
<string name="ssl_error_example" msgid="6188711843183058764">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‏‎‎‎‏‎‏‎‏‏‏‎‎‎‏‎‏‎‎‎‎‏‏‏‎‏‎‏‏‎‎‎‏‎‏‏‎‏‏‏‎‏‏‏‏‏‎‏‎‎‏‏‎‎‎For example, the login page may not belong to the organization shown.‎‏‎‎‏‎"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‏‏‎‎‏‏‎‎‏‏‏‎‏‏‏‏‏‏‎‎‏‎‏‏‏‎‏‏‎‎‏‏‏‏‏‎‏‏‏‏‎‏‎‎‎‏‏‏‏‏‏‎‎‎‎‎‎Continue anyway via browser‎‏‎‎‏‎"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‏‏‎‏‏‎‎‏‏‏‏‏‏‎‎‎‎‏‎‏‏‎‏‏‎‎‏‏‎‎‎‎‎‏‎‎‏‎‎‏‏‎‎‏‎‏‎‏‎‎‎‎‎‎Performance boost‎‏‎‎‏‎"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‎‎‏‎‎‎‏‏‏‏‏‎‏‎‎‏‏‏‎‏‎‎‎‎‎‎‏‏‎‏‏‎‎‎‏‎‏‏‎‎‏‎‏‏‏‎‎‎‏‎‎‎‏‎‎‎‎Improve your 5G experience‎‏‎‎‏‎"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‎‎‎‎‎‏‏‏‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‏‎‏‎‏‎‏‏‎‎‏‎‏‏‎‏‎‎‎‏‏‏‎‎‎‎‏‏‏‏‏‎%1$s recommends buying a performance boost plan. Tap to buy through %2$s.‎‏‎‎‏‎"</string>
+ <string name="performance_boost_notification_title" msgid="6091638924925876776">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‎‏‎‎‏‏‏‎‏‏‎‎‏‎‏‎‏‎‎‏‏‏‏‎‎‏‏‎‎‎‎‏‎‎‏‏‎‎‎‏‏‏‎‏‎‎‎‏‎‏‎‎‎‎Improve your app experience‎‏‎‎‏‎"</string>
+ <string name="performance_boost_notification_detail" msgid="86969987181456032">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‎‎‏‏‎‏‎‎‏‏‏‏‏‎‏‎‏‎‏‏‏‏‏‎‎‎‎‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‎‏‎‏‎‏‎‎‎‎‎‎Tap to visit %s\'s website and learn more.‎‏‎‎‏‎"</string>
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‎‎‏‎‏‏‎‏‎‏‎‎‏‎‎‏‏‏‏‎‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‏‏‏‎‏‎‏‎‎‏‏‏‎‎‏‎‎‏‎Not now‎‏‎‎‏‎"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‎‏‎‎‎‏‎‏‎‎‎‏‏‎‎‏‏‎‎‎‎‎‏‎‏‎‎‎‎‎‏‎‎‏‏‏‎‎‎‎‎‏‏‎‎‎‏‎‏‏‎‏‎‏‎Manage‎‏‎‎‏‎"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‎‎‏‏‎‏‎‏‎‎‏‏‎‎‏‎‎‏‎‎‎‎‎‏‎‎‎‎‏‏‏‎‏‎‎‎‎‏‎‎‏‏‏‎‎Purchase a performance boost.‎‏‎‎‏‎"</string>
diff --git a/packages/CarrierDefaultApp/res/values-es-rUS/strings.xml b/packages/CarrierDefaultApp/res/values-es-rUS/strings.xml
index fedf1ac6b54b..1ad775129883 100644
--- a/packages/CarrierDefaultApp/res/values-es-rUS/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-es-rUS/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Por ejemplo, es posible que la página de acceso no pertenezca a la organización que aparece."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continuar de todos modos desde el navegador"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Aumento de rendimiento"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Mejora tu experiencia de 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recomienda que compres un plan de aumento de rendimiento. Presiona para comprar mediante %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ahora no"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Administrar"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Compra un aumento de rendimiento."</string>
diff --git a/packages/CarrierDefaultApp/res/values-es/strings.xml b/packages/CarrierDefaultApp/res/values-es/strings.xml
index 85642b8d7934..972afa9dc4b0 100644
--- a/packages/CarrierDefaultApp/res/values-es/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-es/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Por ejemplo, es posible que la página de inicio de sesión no pertenezca a la organización mostrada."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continuar de todos modos a través del navegador"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Mejora de rendimiento"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Mejora tu experiencia 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recomienda comprar un plan de mejora del rendimiento. Toca para comprarlo mediante %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ahora no"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gestionar"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Comprar una mejora de rendimiento."</string>
diff --git a/packages/CarrierDefaultApp/res/values-et/strings.xml b/packages/CarrierDefaultApp/res/values-et/strings.xml
index 769f24001c68..1ac991cf0c85 100644
--- a/packages/CarrierDefaultApp/res/values-et/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-et/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Näiteks ei pruugi sisselogimisleht kuuluda kuvatavale organisatsioonile."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Jätka siiski brauseris"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Jõudluse võimendus"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Täiustage oma 5G-kogemust"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s soovitab osta jõudluse võimendusega paketi. Puudutage teenuse %2$s kaudu ostmiseks."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Mitte praegu"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Haldamine"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Ostke jõudluse võimendus."</string>
diff --git a/packages/CarrierDefaultApp/res/values-eu/strings.xml b/packages/CarrierDefaultApp/res/values-eu/strings.xml
index 7274bce1b492..fedf29d6563e 100644
--- a/packages/CarrierDefaultApp/res/values-eu/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-eu/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Adibidez, baliteke saioa hasteko orria adierazitako erakundearena ez izatea."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Jarraitu arakatzailearen bidez, halere"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Errendimendu-hobekuntza"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Hobetu 5G bidezko konexioa"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s zerbitzuak errendimendua hobetzeko kidetza bat erostea gomendatzen du. Sakatu hau %2$s bidez erosteko."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Orain ez"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Kudeatu"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Erosi errendimendu-hobekuntza bat."</string>
diff --git a/packages/CarrierDefaultApp/res/values-fa/strings.xml b/packages/CarrierDefaultApp/res/values-fa/strings.xml
index 2cbe29793ada..a9ac1570d44e 100644
--- a/packages/CarrierDefaultApp/res/values-fa/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-fa/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"به عنوان مثال، صفحه ورود به سیستم ممکن است متعلق به سازمان نشان داده شده نباشد."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"درهر صورت ازطریق مرورگر ادامه یابد"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"تقویت‌کننده عملکرد"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"تجربه نسل پنجم شبکه تلفن همراه را بهبود دهید"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"‏%1$s توصیه می‌کند طرح تقویت عملکرد خریداری شود. برای خرید ازطریق %2$s، ضربه بزنید."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"اکنون نه"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"مدیریت"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"تقویت‌کننده عملکرد خریداری کنید."</string>
diff --git a/packages/CarrierDefaultApp/res/values-fi/strings.xml b/packages/CarrierDefaultApp/res/values-fi/strings.xml
index 1a388cdc52ef..e0bf1e768c54 100644
--- a/packages/CarrierDefaultApp/res/values-fi/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-fi/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Kirjautumissivu ei välttämättä kuulu näytetylle organisaatiolle."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Jatka selaimen kautta"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Suorituskykyboosti"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Paranna 5G-kokemusta"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s suosittelee suorituskykyboostipaketin ostamista. Napauta ja tee ostos operaattorilla %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ei nyt"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Muuta"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Osta suorituskykyboosti."</string>
diff --git a/packages/CarrierDefaultApp/res/values-fr-rCA/strings.xml b/packages/CarrierDefaultApp/res/values-fr-rCA/strings.xml
index ad6c794db5f4..a56a4db3adbc 100644
--- a/packages/CarrierDefaultApp/res/values-fr-rCA/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-fr-rCA/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Par exemple, la page de connexion pourrait ne pas appartenir à l\'organisation représentée."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continuer quand même dans un navigateur"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Optimiseur de performances"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Améliorer votre expérience de la 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recommande d\'acheter un forfait d\'amélioration des performances. Touchez pour acheter par l\'intermédiaire de %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Plus tard"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gérer"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Achetez un optimiseur de performances."</string>
diff --git a/packages/CarrierDefaultApp/res/values-fr/strings.xml b/packages/CarrierDefaultApp/res/values-fr/strings.xml
index 92b47bed7065..699d4b330f8c 100644
--- a/packages/CarrierDefaultApp/res/values-fr/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-fr/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Par exemple, la page de connexion peut ne pas appartenir à l\'organisation représentée."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continuer quand même dans le navigateur"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Boost de performances"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Améliorer votre expérience 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recommande d\'acheter un forfait d\'amélioration des performances. Appuyez pour acheter via %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Pas maintenant"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gérer"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Achetez un boost de performances."</string>
diff --git a/packages/CarrierDefaultApp/res/values-gl/strings.xml b/packages/CarrierDefaultApp/res/values-gl/strings.xml
index 2c1be52bdabd..b252b8c4cb17 100644
--- a/packages/CarrierDefaultApp/res/values-gl/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-gl/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Por exemplo, é posible que a páxina de inicio de sesión non pertenza á organización que se mostra."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continuar igualmente co navegador"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Mellora de rendemento"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Mellora a túa experiencia 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recomenda comprar un plan de mellora do rendemento. Toca para realizar a compra a través de %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Agora non"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Xestionar"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Comprar unha mellora de rendemento."</string>
diff --git a/packages/CarrierDefaultApp/res/values-gu/strings.xml b/packages/CarrierDefaultApp/res/values-gu/strings.xml
index af09d1375c10..8f1174a2eebf 100644
--- a/packages/CarrierDefaultApp/res/values-gu/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-gu/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ઉદાહરણ તરીકે, લોગિન પૃષ્ઠ બતાવવામાં આવેલી સંસ્થાનું ન પણ હોય."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"તો પણ બ્રાઉઝર મારફતે ચાલુ રાખો"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"પર્ફોર્મન્સ બૂસ્ટ"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"તમારા 5G અનુભવને બહેતર બનાવો"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s પર્ફોર્મન્સ બૂસ્ટ પ્લાન ખરીદવાનો સુઝાવ આપે છે. %2$s મારફતે ખરીદવા માટે ટૅપ કરો."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"હમણાં નહીં"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"મેનેજ કરો"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"પર્ફોર્મન્સ બૂસ્ટ ખરીદો."</string>
diff --git a/packages/CarrierDefaultApp/res/values-hi/strings.xml b/packages/CarrierDefaultApp/res/values-hi/strings.xml
index e51b1a97dffd..52da32280e17 100644
--- a/packages/CarrierDefaultApp/res/values-hi/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-hi/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"उदाहरण के लिए, हो सकता है कि लॉगिन पेज दिखाए गए संगठन का ना हो."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"ब्राउज़र के ज़रिए किसी भी तरह जारी रखें"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"परफ़ॉर्मेंस बूस्ट"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"5G का बेहतर अनुभव पाएं"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s, परफ़ॉर्मेंस को बेहतर बनाने वाले प्लान को खरीदने का सुझाव देता है. %2$s से प्लान खरीदने के लिए टैप करें."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"अभी नहीं"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"मैनेज करें"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"कोई परफ़ॉर्मेंस बूस्ट खरीदें."</string>
diff --git a/packages/CarrierDefaultApp/res/values-hr/strings.xml b/packages/CarrierDefaultApp/res/values-hr/strings.xml
index 5a22ad54d884..1b601231d738 100644
--- a/packages/CarrierDefaultApp/res/values-hr/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-hr/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Na primjer, stranica za prijavu možda ne pripada prikazanoj organizaciji."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Ipak nastavi putem preglednika"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Poboljšanje izvedbe"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Poboljšajte svoj 5G doživljaj"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s preporučuje kupnju paketa za poboljšanje izvedbe. Dodirnite da biste kupili putem usluge %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ne sad"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Upravljajte"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Kupite poboljšanje izvedbe."</string>
diff --git a/packages/CarrierDefaultApp/res/values-hu/strings.xml b/packages/CarrierDefaultApp/res/values-hu/strings.xml
index a841cb24dc19..026586b893d1 100644
--- a/packages/CarrierDefaultApp/res/values-hu/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-hu/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Például lehetséges, hogy a bejelentkezési oldal nem a megjelenített szervezethez tartozik."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Folytatás ennek ellenére böngészőn keresztül"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Teljesítménynövelés"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Az 5G-élmény javítása"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"A(z) %1$s teljesítménynövelő csomag vásárlását javasolja. Koppintson a(z) %2$s szolgáltatón keresztüli vásárláshoz."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Most nem"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Kezelés"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Vásároljon teljesítménynövelést."</string>
diff --git a/packages/CarrierDefaultApp/res/values-hy/strings.xml b/packages/CarrierDefaultApp/res/values-hy/strings.xml
index 49fbece29a8b..dc93d6e012fc 100644
--- a/packages/CarrierDefaultApp/res/values-hy/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-hy/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Օրինակ՝ մուտքի էջը կարող է ցուցադրված կազմակերպության էջը չլինել:"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Շարունակել դիտարկիչի միջոցով"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Արտադրողականության բարձրացում"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Բարելավեք 5G-ի օգտագործման ձեր փորձառությունը"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s օպերատորը խորհուրդ է տալիս ձեռք բերել արդյունավետությունը բարձրացնող սակագնային պլան։ Հպեք՝ %2$s-ի միջոցով գնելու համար։"</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ոչ հիմա"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Կառավարել"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Բարձրացրեք ցանցի արտադրողականությունը վճարի դիմաց։"</string>
diff --git a/packages/CarrierDefaultApp/res/values-in/strings.xml b/packages/CarrierDefaultApp/res/values-in/strings.xml
index 170bd76ca4e6..56b8b2ea6deb 100644
--- a/packages/CarrierDefaultApp/res/values-in/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-in/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Misalnya, halaman login mungkin bukan milik organisasi yang ditampilkan."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Tetap lanjutkan melalui browser"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Penguat sinyal"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Tingkatkan pengalaman 5G Anda"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s merekomendasikan pembelian paket penguat sinyal. Ketuk untuk membeli melalui %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Lain kali"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Kelola"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Beli penguat sinyal."</string>
diff --git a/packages/CarrierDefaultApp/res/values-is/strings.xml b/packages/CarrierDefaultApp/res/values-is/strings.xml
index 8684ee62d626..510d5fdd986c 100644
--- a/packages/CarrierDefaultApp/res/values-is/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-is/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Til dæmis getur verið að innskráningarsíðan tilheyri ekki fyrirtækinu sem birtist."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Halda samt áfram í vafra"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Afkastaaukning"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Bættu upplifun þína af 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s mælir með að kaupa áskrift sem eykur afköst. Ýttu til að kaupa í gegnum %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ekki núna"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Stjórna"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Kaupa afkastaaukningu."</string>
diff --git a/packages/CarrierDefaultApp/res/values-it/strings.xml b/packages/CarrierDefaultApp/res/values-it/strings.xml
index ea884571303f..324aa4f7ce3e 100644
--- a/packages/CarrierDefaultApp/res/values-it/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-it/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Ad esempio, la pagina di accesso potrebbe non appartenere all\'organizzazione indicata."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continua comunque dal browser"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Aumento di prestazioni"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Migliora la tua esperienza 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s consiglia l\'acquisto di un piano di miglioramento delle prestazioni. Tocca per acquistare tramite %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Non ora"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gestisci"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Acquista un aumento di prestazioni."</string>
diff --git a/packages/CarrierDefaultApp/res/values-iw/strings.xml b/packages/CarrierDefaultApp/res/values-iw/strings.xml
index c7229ba56418..9e2f31cb77d8 100644
--- a/packages/CarrierDefaultApp/res/values-iw/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-iw/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"לדוגמה, ייתכן שדף ההתחברות אינו שייך לארגון המוצג."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"המשך בכל זאת באמצעות דפדפן"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"שיפור ביצועים"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"‏שיפור חווית השימוש ב-5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"‏יש המלצה של %1$s לקנות תוכנית לשיפור הביצועים. אפשר להקיש כדי לקנות דרך %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"לא עכשיו"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"ניהול"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"רכישת שיפור ביצועים."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ja/strings.xml b/packages/CarrierDefaultApp/res/values-ja/strings.xml
index 2fd86c8a805e..833f8a5b1c04 100644
--- a/packages/CarrierDefaultApp/res/values-ja/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ja/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"たとえば、ログインページが表示されている組織に属していない可能性があります。"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"ブラウザから続行"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"パフォーマンス ブースト"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"5G のエクスペリエンスを改善"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s さんがパフォーマンス ブースト プランの購入をおすすめしています。%2$sまでにタップして購入しましょう。"</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"後で"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"管理"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"パフォーマンス ブーストを購入してください。"</string>
diff --git a/packages/CarrierDefaultApp/res/values-ka/strings.xml b/packages/CarrierDefaultApp/res/values-ka/strings.xml
index 76f72737a7df..507e0d9fe378 100644
--- a/packages/CarrierDefaultApp/res/values-ka/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ka/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"მაგალითად, სისტემაში შესვლის გვერდი შეიძლება არ ეკუთვნოდეს ნაჩვენებ ორგანიზაციას."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"მაინც ბრაუზერში გაგრძელება"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"ეფექტურობის გაძლიერება"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"გააუმჯობესეთ თქვენი 5G გამოცდილება"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s-ის მიერ რეკომენდებულია ეფექტურობის გაძლიერების გეგმის შეძენა. შეეხეთ %2$s-ის დახმარებით შესაძენად."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ახლა არა"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"მართვა"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"ეფექტურობის გაძლიერების შეძენა."</string>
diff --git a/packages/CarrierDefaultApp/res/values-kk/strings.xml b/packages/CarrierDefaultApp/res/values-kk/strings.xml
index 4a895f47e461..32eae44a3fc9 100644
--- a/packages/CarrierDefaultApp/res/values-kk/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-kk/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Мысалы, кіру беті көрсетілген ұйымға тиесілі болмауы мүмкін."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Бәрібір браузер арқылы жалғастыру"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Өнімділікті арттыру"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"5G желісімен жұмысыңызды жақсартыңыз"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s өнімділікті арттыру жоспарын сатып алуды ұсынады. %2$s операторынан сатып алу үшін түртіңіз."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Қазір емес"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Басқару"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Өнімділікті арттыру құралын сатып алыңыз."</string>
diff --git a/packages/CarrierDefaultApp/res/values-km/strings.xml b/packages/CarrierDefaultApp/res/values-km/strings.xml
index 51a51ff9698f..531226fcfa07 100644
--- a/packages/CarrierDefaultApp/res/values-km/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-km/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ឧទាហរណ៍៖ ទំព័រចូលនេះអាចនឹងមិនមែនជាកម្មសិទ្ធិរបស់ស្ថាប័នដែលបានបង្ហាញនេះទេ។"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"យ៉ាងណាក៏ដោយនៅតែបន្តតាមរយៈកម្មវិធីរុករកតាមអ៊ីនធឺណិត"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"ការបង្កើនប្រតិបត្តិការ"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"កែលម្អបទពិសោធន៍ប្រើ 5G របស់អ្នក"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s ណែនាំឱ្យទិញផែនការជំរុញប្រតិបត្តិការ។ ចុចដើម្បីទិញតាមរយៈ %2$s។"</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"កុំទាន់"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"គ្រប់គ្រង"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"ទិញការបង្កើនប្រតិបត្តិការ។"</string>
diff --git a/packages/CarrierDefaultApp/res/values-kn/strings.xml b/packages/CarrierDefaultApp/res/values-kn/strings.xml
index c97d6f011e0b..4335d0c8285f 100644
--- a/packages/CarrierDefaultApp/res/values-kn/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-kn/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ಉದಾಹರಣೆಗೆ, ಲಾಗಿನ್ ಪುಟವು ತೋರಿಸಲಾಗಿರುವ ಸಂಸ್ಥೆಗೆ ಸಂಬಂಧಿಸಿಲ್ಲದಿರಬಹುದು."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"ಪರವಾಗಿಲ್ಲ, ಬ್ರೌಸರ್ ಮೂಲಕ ಮುಂದುವರಿಸಿ"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"ಕಾರ್ಯಕ್ಷಮತೆ ಬೂಸ್ಟ್"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"ನಿಮ್ಮ 5G ಅನುಭವವನ್ನು ಸುಧಾರಿಸಿ"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"ಕಾರ್ಯಕ್ಷಮತೆಯನ್ನು ಹೆಚ್ಚಿಸುವ ಪ್ಲಾನ್ ಅನ್ನು ಖರೀದಿಸಲು %1$s ಶಿಫಾರಸು ಮಾಡುತ್ತದೆ. %2$s ಮೂಲಕ ಖರೀದಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ಈಗ ಬೇಡ"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"ನಿರ್ವಹಿಸಿ"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"ಕಾರ್ಯಕ್ಷಮತೆ ಬೂಸ್ಟ್ ಅನ್ನು ಖರೀದಿಸಿ."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ko/strings.xml b/packages/CarrierDefaultApp/res/values-ko/strings.xml
index 395627da1571..3bb5628a680c 100644
--- a/packages/CarrierDefaultApp/res/values-ko/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ko/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"예를 들어 로그인 페이지가 표시된 조직에 속하지 않을 수 있습니다."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"브라우저를 통해 계속하기"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"성능 향상"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"5G 사용 환경 개선"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s에서 성능 향상 계획 구매를 추천합니다. %2$s을(를) 통해 구매하려면 탭하세요."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"나중에"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"관리"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"성능 향상 구매"</string>
diff --git a/packages/CarrierDefaultApp/res/values-ky/strings.xml b/packages/CarrierDefaultApp/res/values-ky/strings.xml
index b3970e394b42..07bb61844531 100644
--- a/packages/CarrierDefaultApp/res/values-ky/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ky/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Мисалы, аккаунтка кирүү баракчасы көрсөтүлгөн уюмга таандык эмес болушу мүмкүн."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Баары бир серепчи аркылуу улантуу"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Иштин майнаптуулугун жогорулатуу"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"5G менен оңой иштеңиз"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s майнаптуулугун жогорулата турган тарифтик планды сатып алууну сунуштайт. %2$s аркылуу сатып алуу үчүн таптаңыз."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Азыр эмес"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Тескөө"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Иштин майнаптуулугун жогорулатууну сатып алыңыз."</string>
diff --git a/packages/CarrierDefaultApp/res/values-lo/strings.xml b/packages/CarrierDefaultApp/res/values-lo/strings.xml
index 70d88885008c..480a7ce78751 100644
--- a/packages/CarrierDefaultApp/res/values-lo/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-lo/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ຕົວຢ່າງ, ໜ້າເຂົ້າສູ່ລະບົບອາດຈະບໍ່ແມ່ນຂອງອົງກອນທີ່ປາກົດ."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"ດຳເນີນການຕໍ່ຜ່ານໂປຣແກຣມທ່ອງເວັບ"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"ເລັ່ງປະສິດທິພາບ"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"ປັບປຸງປະສົບການ 5G ຂອງທ່ານ"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s ແນະນຳໃຫ້ຊື້ແຜນການເລັ່ງປະສິດທິພາບ. ແຕະເພື່ອຊື້ຜ່ານ %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ບໍ່ຟ້າວເທື່ອ"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"ຈັດການ"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"ຊື້ການເລັ່ງປະສິດທິພາບ."</string>
diff --git a/packages/CarrierDefaultApp/res/values-lt/strings.xml b/packages/CarrierDefaultApp/res/values-lt/strings.xml
index 80684169317a..1f4a4339471b 100644
--- a/packages/CarrierDefaultApp/res/values-lt/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-lt/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Pavyzdžiui, prisijungimo puslapis gali nepriklausyti rodomai organizacijai."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Vis tiek tęsti naudojant naršyklę"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Našumo pagerinimas"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Pagerinkite 5G ryšį"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"„%1$s“ rekomenduoja įsigyti našumo pagerinimo planą. Palieskite, kad įsigytumėte naudodamiesi „%2$s“ paslaugomis."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ne dabar"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Tvarkyti"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Įsigykite našumo pagerinimo paslaugą."</string>
diff --git a/packages/CarrierDefaultApp/res/values-lv/strings.xml b/packages/CarrierDefaultApp/res/values-lv/strings.xml
index 1fefe92669b1..2fd983775444 100644
--- a/packages/CarrierDefaultApp/res/values-lv/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-lv/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Piemēram, pieteikšanās lapa, iespējams, nepieder norādītajai organizācijai."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Tomēr turpināt, izmantojot pārlūkprogrammu"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Veiktspējas uzlabojums"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Uzlabojiet 5G iespējas"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s iesaka iegādāties veiktspējas uzlabošanas plānu. Pieskarieties, lai to iegādātos no %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Vēlāk"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Pārvaldīt"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Iegādājieties veiktspējas uzlabojumu."</string>
diff --git a/packages/CarrierDefaultApp/res/values-mk/strings.xml b/packages/CarrierDefaultApp/res/values-mk/strings.xml
index 425edfc493e1..6eca2b50a4ba 100644
--- a/packages/CarrierDefaultApp/res/values-mk/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-mk/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"На пример, страницата за најавување може да не припаѓа на прикажаната организација."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Сепак продолжи преку прелистувач"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Засилување на изведбата"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Подобрете го вашето доживување со 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s препорачува да купите пакет за засилување на изведбата. Допрете за да купите преку %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Не сега"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Управувајте"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Купете засилување на изведбата."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ml/strings.xml b/packages/CarrierDefaultApp/res/values-ml/strings.xml
index f2584118516d..2577a144b247 100644
--- a/packages/CarrierDefaultApp/res/values-ml/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ml/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ഉദാഹരണത്തിന്, കാണിച്ചിരിക്കുന്ന ഓർഗനൈസേഷന്റേതായിരിക്കില്ല ലോഗിൻ പേജ്."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"എന്തായാലും ബ്രൗസർ വഴി തുടരുക"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"പ്രകടന ബൂസ്റ്റ്"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"നിങ്ങളുടെ 5G അനുഭവം മെച്ചപ്പെടുത്തുക"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"പ്രകടന ബൂസ്റ്റ് പ്ലാൻ വാങ്ങാൻ %1$s നിർദ്ദേശിക്കുന്നു. %2$s വഴി വാങ്ങാൻ ടാപ്പ് ചെയ്യുക."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ഇപ്പോൾ വേണ്ട"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"മാനേജ് ചെയ്യുക"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"പ്രകടന ബൂസ്റ്റ് വാങ്ങൂ."</string>
diff --git a/packages/CarrierDefaultApp/res/values-mn/strings.xml b/packages/CarrierDefaultApp/res/values-mn/strings.xml
index 12e17194ffae..f0fc546cacb4 100644
--- a/packages/CarrierDefaultApp/res/values-mn/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-mn/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Жишээлбэл нэвтрэх хуудас нь харагдаж буй байгууллагынх биш байж болно."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Ямар ч тохиолдолд хөтчөөр үргэлжлүүлэх"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Гүйцэтгэлийн идэвхжүүлэлт"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"5G-н хэрэглээгээ сайжруулах"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s гүйцэтгэл нэмэгдүүлэх багцыг худалдаж авахыг зөвлөж байна. %2$s-р дамжуулан худалдан авах бол товшино уу."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Одоо биш"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Удирдах"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Гүйцэтгэлийн идэвхжүүлэлтийг худалдаж аваарай."</string>
diff --git a/packages/CarrierDefaultApp/res/values-mr/strings.xml b/packages/CarrierDefaultApp/res/values-mr/strings.xml
index a48c60518be1..75cbb1be3e6a 100644
--- a/packages/CarrierDefaultApp/res/values-mr/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-mr/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"उदाहरणार्थ, लॉग इन पृष्‍ठ दर्शवलेल्या संस्थेच्या मालकीचे नसू शकते."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"तरीही ब्राउझरद्वारे सुरू ठेवा"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"परफॉर्मन्स बूस्ट"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"तुमच्या 5G अनुभवामध्ये सुधारणा करा"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s हे परफॉर्मन्स बूस्ट प्लॅन खरेदी करण्याची शिफारस करते. %2$s वरून खरेदी करण्यासाठी टॅप करा."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"आता नको"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"व्यवस्थापित करा"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"परफॉर्मन्स बूस्ट खरेदी करा."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ms/strings.xml b/packages/CarrierDefaultApp/res/values-ms/strings.xml
index 85651f42b4b3..14842335e668 100644
--- a/packages/CarrierDefaultApp/res/values-ms/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ms/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Contohnya, halaman log masuk mungkin bukan milik organisasi yang ditunjukkan."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Teruskan juga melalui penyemak imbas"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Peningkatan prestasi"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Tingkatkan pengalaman 5G anda"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s mengesyorkan pembelian pelan peningkatan prestasi. Ketik untuk membeli melalui %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Bukan sekarang"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Urus"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Beli perangsang prestasi."</string>
diff --git a/packages/CarrierDefaultApp/res/values-my/strings.xml b/packages/CarrierDefaultApp/res/values-my/strings.xml
index 34c54b9ea835..e7a860e30ab5 100644
--- a/packages/CarrierDefaultApp/res/values-my/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-my/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ဥပမာ− ဝင်ရောက်ရန် စာမျက်နှာသည် ပြသထားသည့် အဖွဲ့အစည်းနှင့် သက်ဆိုင်မှုမရှိခြင်း ဖြစ်နိုင်ပါသည်။"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"မည်သို့ပင်ဖြစ်စေ ဘရောက်ဇာမှတစ်ဆင့် ရှေ့ဆက်ရန်"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"စွမ်းဆောင်ရည် မြှင့်တင်အက်ပ်"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"5G အသုံးပြုမှု ပိုမိုကောင်းမွန်စေခြင်း"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s သည် စွမ်းဆောင်ရည်မြှင့်တင်သော အစီအစဉ်ဝယ်ရန် အကြံပြုပါသည်။ %2$s မှတစ်ဆင့် ဝယ်ရန် တို့ပါ။"</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ယခုမလုပ်ပါ"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"စီမံရန်"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"စွမ်းဆောင်ရည် မြှင့်တင်အက်ပ် ဝယ်ယူရန်။"</string>
diff --git a/packages/CarrierDefaultApp/res/values-nb/strings.xml b/packages/CarrierDefaultApp/res/values-nb/strings.xml
index b30e3d9783fe..f0d0d7e95256 100644
--- a/packages/CarrierDefaultApp/res/values-nb/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-nb/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Det er for eksempel mulig at påloggingssiden ikke tilhører organisasjonen som vises."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Fortsett likevel via nettleseren"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Bedre ytelse"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Få en bedre 5G-opplevelse"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s anbefaler at du kjøper et abonnement for bedre ytelse. Trykk for å kjøpe via %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ikke nå"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Administrer"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Kjøp bedre ytelse."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ne/strings.xml b/packages/CarrierDefaultApp/res/values-ne/strings.xml
index 4dccdb91f209..f2b0f6efd220 100644
--- a/packages/CarrierDefaultApp/res/values-ne/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ne/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"उदाहरणका लागि, लग इन पृष्ठ देखाइएको संस्थाको नहुन सक्छ।"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"जे भए पनि ब्राउजर मार्फत जारी राख्नुहोस्"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"पर्फर्मेन्स बुस्ट"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"5G प्रयोग गर्दा अझ राम्रो सुविधा पाउनुहोस्"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s ले पर्फर्मेन्स बुस्ट योजना खरिद गर्न सिफारिस गर्छ। %2$s मार्फत खरिद गर्न ट्याप गर्नुहोस्।"</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"अहिले होइन"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"व्यवस्थापन गर्नुहोस्"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"पर्फर्मेन्स बुस्ट किन्नुहोस्।"</string>
diff --git a/packages/CarrierDefaultApp/res/values-nl/strings.xml b/packages/CarrierDefaultApp/res/values-nl/strings.xml
index 6a4642c618dd..f8ff38ad035a 100644
--- a/packages/CarrierDefaultApp/res/values-nl/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-nl/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Zo hoort de weergegeven inlogpagina misschien niet bij de weergegeven organisatie."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Toch doorgaan via browser"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Prestatieboost"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Verbeter je 5G-functionaliteit"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s beveelt je aan een prestatieboostabonnement te kopen. Tik om er een te kopen via %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Niet nu"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Beheren"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Koop een prestatieboost."</string>
diff --git a/packages/CarrierDefaultApp/res/values-or/strings.xml b/packages/CarrierDefaultApp/res/values-or/strings.xml
index f7349f9e68a7..bbe6f25c2b34 100644
--- a/packages/CarrierDefaultApp/res/values-or/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-or/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ଉଦାହରଣସ୍ୱରୂପ, ଲଗଇନ୍‍ ପୃଷ୍ଠା ଦେଖାଯାଇଥିବା ସଂସ୍ଥାର ହୋଇନଥାଇପାରେ।"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"ବ୍ରାଉଜର୍‍ ଜରିଆରେ ଯେମିତିବି ହେଉ ଜାରି ରଖନ୍ତୁ"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"ପରଫରମାନ୍ସ ବୁଷ୍ଟ"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"ଆପଣଙ୍କ 5G ଅନୁଭୂତିକୁ ଉନ୍ନତ କରନ୍ତୁ"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s ଏକ ପରଫରମାନ୍ସ ବୁଷ୍ଟ ପ୍ଲାନ କିଣିବା ପାଇଁ ସୁପାରିଶ କରେ। %2$s ମାଧ୍ୟମରେ କିଣିବା ପାଇଁ ଟାପ କରନ୍ତୁ।"</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ବର୍ତ୍ତମାନ ନୁହେଁ"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"ପରିଚାଳନା କରନ୍ତୁ"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"ଏକ ପରଫରମାନ୍ସ ବୁଷ୍ଟ କିଣନ୍ତୁ।"</string>
diff --git a/packages/CarrierDefaultApp/res/values-pa/strings.xml b/packages/CarrierDefaultApp/res/values-pa/strings.xml
index 540a54cc267e..811eca91280f 100644
--- a/packages/CarrierDefaultApp/res/values-pa/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-pa/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ਉਦਾਹਰਣ ਵੱਜੋਂ, ਲੌਗ-ਇਨ ਪੰਨਾ ਦਿਖਾਈ ਗਈ ਸੰਸਥਾ ਨਾਲ ਸੰਬੰਧਿਤ ਨਹੀਂ ਹੋ ਸਕਦਾ ਹੈ।"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"ਬ੍ਰਾਊਜ਼ਰ ਰਾਹੀਂ ਫਿਰ ਵੀ ਜਾਰੀ ਰੱਖੋ"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"ਕਾਰਗੁਜ਼ਾਰੀ ਬੂਸਟ"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"ਆਪਣਾ 5G ਅਨੁਭਵ ਬਿਹਤਰ ਬਣਾਓ"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s ਵੱਲੋਂ ਕਾਰਗੁਜ਼ਾਰੀ ਬੂਸਟ ਪਲਾਨ ਖਰੀਦਣ ਦੀ ਸਿਫ਼ਾਰਸ਼ ਕੀਤੀ ਜਾਂਦੀ ਹੈ। %2$s ਰਾਹੀਂ ਖਰੀਦਣ ਲਈ ਟੈਪ ਕਰੋ।"</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ਹੁਣੇ ਨਹੀਂ"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"ਪ੍ਰਬੰਧਨ ਕਰੋ"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"ਕਾਰਗੁਜ਼ਾਰੀ ਬੂਸਟ ਖਰੀਦੋ।"</string>
diff --git a/packages/CarrierDefaultApp/res/values-pl/strings.xml b/packages/CarrierDefaultApp/res/values-pl/strings.xml
index de957a934d5e..3cd32972ad3e 100644
--- a/packages/CarrierDefaultApp/res/values-pl/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-pl/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Na przykład strona logowania może nie należeć do wyświetlanej organizacji."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Kontynuuj mimo to w przeglądarce"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Zwiększenie wydajności"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Lepiej wykorzystaj potencjał 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"Operator %1$s zaleca zakup abonamentu o zwiększonej wydajności. Kliknij, aby kupić u operatora %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Nie teraz"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Zarządzaj"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Kup wzmocnienie wydajności"</string>
diff --git a/packages/CarrierDefaultApp/res/values-pt-rBR/strings.xml b/packages/CarrierDefaultApp/res/values-pt-rBR/strings.xml
index 4a144be2a214..85f049d11399 100644
--- a/packages/CarrierDefaultApp/res/values-pt-rBR/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-pt-rBR/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Por exemplo, a página de login pode não pertencer à organização mostrada."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continuar mesmo assim pelo navegador"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Aumento de performance"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Melhore sua experiência 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recomenda a compra de um plano para aumento de desempenho. Toque para comprar em %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Agora não"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gerenciar"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Comprar um aumento de performance."</string>
diff --git a/packages/CarrierDefaultApp/res/values-pt-rPT/strings.xml b/packages/CarrierDefaultApp/res/values-pt-rPT/strings.xml
index 56e0c2d70e55..981cc5f3eaf6 100644
--- a/packages/CarrierDefaultApp/res/values-pt-rPT/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-pt-rPT/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Por exemplo, a página de início de sessão pode não pertencer à entidade apresentada."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continuar mesmo assim através do navegador"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Aumento do desempenho"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Melhore a sua experiência 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recomenda comprar um plano de melhoria do desempenho. Toque para comprar através do %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Agora não"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gerir"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Compre um aumento do desempenho."</string>
diff --git a/packages/CarrierDefaultApp/res/values-pt/strings.xml b/packages/CarrierDefaultApp/res/values-pt/strings.xml
index 4a144be2a214..85f049d11399 100644
--- a/packages/CarrierDefaultApp/res/values-pt/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-pt/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Por exemplo, a página de login pode não pertencer à organização mostrada."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continuar mesmo assim pelo navegador"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Aumento de performance"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Melhore sua experiência 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recomenda a compra de um plano para aumento de desempenho. Toque para comprar em %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Agora não"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gerenciar"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Comprar um aumento de performance."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ro/strings.xml b/packages/CarrierDefaultApp/res/values-ro/strings.xml
index f8611379188c..287be5ae4b8b 100644
--- a/packages/CarrierDefaultApp/res/values-ro/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ro/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"De exemplu, este posibil ca pagina de conectare să nu aparțină organizației afișate."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continuă oricum prin browser"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Boost de performanță"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Îmbunătățește-ți experiența cu tehnologia 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recomandă cumpărarea unui plan pentru îmbunătățirea performanței. Atinge pentru a cumpăra de la %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Nu acum"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gestionează"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Achiziționează un boost de performanță."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ru/strings.xml b/packages/CarrierDefaultApp/res/values-ru/strings.xml
index f0bff17dbaef..fd1328a3e25e 100644
--- a/packages/CarrierDefaultApp/res/values-ru/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ru/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Например, страница входа в аккаунт может быть фиктивной."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Продолжить в браузере"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Повышение производительности"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Сделайте работу с 5G удобнее"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"\"%1$s\" рекомендует купить тарифный план, повышающий производительность. Чтобы приобрести тариф у оператора \"%2$s\", коснитесь экрана."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Не сейчас"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Настроить"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Повысьте производительность сети за плату."</string>
diff --git a/packages/CarrierDefaultApp/res/values-si/strings.xml b/packages/CarrierDefaultApp/res/values-si/strings.xml
index 166af5a86a7c..a1cd21d4a6e3 100644
--- a/packages/CarrierDefaultApp/res/values-si/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-si/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"උදාහරණයක් ලෙස, පුරනය වන පිටුව පෙන්වා ඇති සංවිධානයට අයිති නැති විය හැක."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"කෙසේ වුවත් බ්‍රවුසරය හරහා ඉදිරියට යන්න"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"කාර්ය සාධනය ඉහළ නැංවීම"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"ඔබේ 5G අත්දැකීම වැඩි දියුණු කරන්න"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s කාර්ය සාධනය වැඩි කිරීමේ සැලසුමක් මිල දී ගැනීම නිර්දේශ කරයි. %2$s හරහා මිල දී ගැනීමට තට්ටු කරන්න."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"දැන් නොවේ"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"කළමනාකරණය කරන්න"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"කාර්ය සාධනය ඉහළ නැංවීමක් මිල දී ගන්න."</string>
diff --git a/packages/CarrierDefaultApp/res/values-sk/strings.xml b/packages/CarrierDefaultApp/res/values-sk/strings.xml
index a58bd06491c5..265506547d08 100644
--- a/packages/CarrierDefaultApp/res/values-sk/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-sk/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Napríklad prihlasovacia stránka nemusí patriť uvedenej organizácii."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Pokračovať pomocou prehliadača"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Zvýšenie výkonu"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Zlepšite svoje prostredie 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s odporúča zakúpiť tarifu na zvýšenie výkonnosti. Klepnutím kúpte cez %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Teraz nie"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Spravovať"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Kúpte si zvýšenie výkonu."</string>
diff --git a/packages/CarrierDefaultApp/res/values-sl/strings.xml b/packages/CarrierDefaultApp/res/values-sl/strings.xml
index 3c1fd3ec80f4..32c26599206b 100644
--- a/packages/CarrierDefaultApp/res/values-sl/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-sl/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Stran za prijavo na primer morda ne pripada prikazani organizaciji."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Vseeno nadaljuj v brskalniku"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Ojačevalnik zmogljivosti"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Izboljšajte izkušnjo omrežja 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s priporoča nakup paketa ojačevalnika zmogljivosti. Dotaknite se za nakup prek »%2$s«."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ne zdaj"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Upravljanje"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Kupite ojačevalnik zmogljivosti."</string>
diff --git a/packages/CarrierDefaultApp/res/values-sq/strings.xml b/packages/CarrierDefaultApp/res/values-sq/strings.xml
index 618e33573486..f72af39fcd8e 100644
--- a/packages/CarrierDefaultApp/res/values-sq/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-sq/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"për shembull, faqja e identifikimit mund të mos i përkasë organizatës së shfaqur."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Vazhdo gjithsesi nëpërmjet shfletuesit"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Përforcimi i performancës"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Përmirëso përvojën tënde 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s rekomandon blerjen e një plani të përforcimit të performancës. Trokit për të blerë nëpërmjet %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Jo tani"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Menaxho"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Bli një paketë përforcimi të performancës."</string>
diff --git a/packages/CarrierDefaultApp/res/values-sr/strings.xml b/packages/CarrierDefaultApp/res/values-sr/strings.xml
index d28bacca1a07..466e38cffa52 100644
--- a/packages/CarrierDefaultApp/res/values-sr/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-sr/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"На пример, страница за пријављивање можда не припада приказаној организацији."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Ипак настави преко прегледача"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Побољшање учинка"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Побољшајте 5G доживљај"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s препоручује куповину пакета за побољшање перформанси. Додирните да бисте купили преко %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Не сада"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Управљај"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Купите побољшање учинка."</string>
diff --git a/packages/CarrierDefaultApp/res/values-sv/strings.xml b/packages/CarrierDefaultApp/res/values-sv/strings.xml
index ac044ec517b9..ff438b3c74a4 100644
--- a/packages/CarrierDefaultApp/res/values-sv/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-sv/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Det kan t.ex. hända att inloggningssidan inte tillhör den organisation som visas."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Fortsätt ändå via webbläsaren"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Prestandahöjning"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Förbättra din 5G-upplevelse"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s rekommenderar att du köper en prenumeration som kan höja prestandan. Tryck för att köpa via %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Inte nu"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Hantera"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Köp en prestandahöjning."</string>
diff --git a/packages/CarrierDefaultApp/res/values-sw/strings.xml b/packages/CarrierDefaultApp/res/values-sw/strings.xml
index 1c72f30bbc45..17bcc0fca430 100644
--- a/packages/CarrierDefaultApp/res/values-sw/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-sw/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Kwa mfano, ukurasa wa kuingia katika akaunti unaweza usiwe unamilikiwa na shirika lililoonyeshwa."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Endelea hata hivyo kupitia kivinjari"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Kuongeza utendaji"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Boresha hali yako ya utumiaji wa 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s anapendekeza ununue mpango wa kuongeza utendaji. Gusa ili ununue kupitia %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Si sasa"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Dhibiti"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Nunua programu ya kuongeza utendaji."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ta/strings.xml b/packages/CarrierDefaultApp/res/values-ta/strings.xml
index cfc46e869515..3c347e116a25 100644
--- a/packages/CarrierDefaultApp/res/values-ta/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ta/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"எடுத்துக்காட்டாக, உள்நுழைவுப் பக்கமானது காட்டப்படும் அமைப்பிற்குச் சொந்தமானதாக இல்லாமல் இருக்கலாம்."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"பரவாயில்லை, உலாவி வழியாகத் தொடர்க"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"பெர்ஃபார்மென்ஸ் பூஸ்ட்"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"உங்கள் 5G அனுபவத்தை மேம்படுத்துங்கள்"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"செயல்திறன் மேம்பாட்டுத் திட்டத்தை வாங்க %1$s பரிந்துரைக்கிறது. %2$s மூலம் வாங்க தட்டவும்."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"இப்போது வேண்டாம்"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"நிர்வகியுங்கள்"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"ஒரு பெர்ஃபார்மென்ஸ் பூஸ்ட்டைப் பர்ச்சேஸ் செய்யுங்கள்."</string>
diff --git a/packages/CarrierDefaultApp/res/values-te/strings.xml b/packages/CarrierDefaultApp/res/values-te/strings.xml
index f31291e6ae7f..003df39d41d7 100644
--- a/packages/CarrierDefaultApp/res/values-te/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-te/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ఉదాహరణకు, లాగిన్ పేజీ చూపిన సంస్థకు చెందినది కాకపోవచ్చు."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"ఏదేమైనా బ్రౌజర్ ద్వారా కొనసాగించండి"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"పనితీరు బూస్ట్"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"మీ 5G అనుభవాన్ని మెరుగుపరుచుకోండి"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"పనితీరును బూస్ట్ చేసే ప్లాన్‌ను కొనుగోలు చేయమని %1$s సిఫార్సు చేస్తున్నారు. %2$s ద్వారా కొనుగోలు చేయడానికి ట్యాప్ చేయండి."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ఇప్పుడు కాదు"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"మేనేజ్ చేయండి"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"పనితీరు బూస్ట్‌ను కొనుగోలు చేయండి."</string>
diff --git a/packages/CarrierDefaultApp/res/values-th/strings.xml b/packages/CarrierDefaultApp/res/values-th/strings.xml
index f20346e5f399..16705d453110 100644
--- a/packages/CarrierDefaultApp/res/values-th/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-th/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ตัวอย่างเช่น หน้าเข้าสู่ระบบอาจไม่ใช่ขององค์กรที่แสดงไว้"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"ดำเนินการต่อผ่านเบราว์เซอร์"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"การเพิ่มประสิทธิภาพ"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"ปรับปรุงประสบการณ์การใช้งาน 5G ของคุณ"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s แนะนำให้ซื้อแพ็กเกจเพิ่มประสิทธิภาพ แตะเพื่อซื้อผ่าน %2$s"</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ไว้ทีหลัง"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"จัดการ"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"ซื้อการเพิ่มประสิทธิภาพ"</string>
diff --git a/packages/CarrierDefaultApp/res/values-tl/strings.xml b/packages/CarrierDefaultApp/res/values-tl/strings.xml
index 9e8029aeaf3d..28cd237d8cc1 100644
--- a/packages/CarrierDefaultApp/res/values-tl/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-tl/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Halimbawa, maaaring hindi pag-aari ng ipinapakitang organisasyon ang page ng login."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Magpatuloy pa rin sa pamamagitan ng browser"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Pag-boost ng performance"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Pagandahin ang iyong karanasan sa 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"Inirerekomenda ng %1$s na bumili ng plan sa performance boost. I-tap para bumili sa pamamagitan ng %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Huwag muna"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Pamahalaan"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Bumili ng pang-boost ng performance."</string>
diff --git a/packages/CarrierDefaultApp/res/values-tr/strings.xml b/packages/CarrierDefaultApp/res/values-tr/strings.xml
index c8fb73b42da2..d35db1de4c97 100644
--- a/packages/CarrierDefaultApp/res/values-tr/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-tr/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Örneğin, giriş sayfası, gösterilen kuruluşa ait olmayabilir."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Yine de tarayıcıyla devam et"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Performans artışı"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"5G deneyiminizi iyileştirin"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s, performans artırma planı satın almanızı öneriyor. %2$s aracılığıyla satın almak için dokunun."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Şimdi değil"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Yönet"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Performans artışı satın alın."</string>
diff --git a/packages/CarrierDefaultApp/res/values-uk/strings.xml b/packages/CarrierDefaultApp/res/values-uk/strings.xml
index 9927ea05bb3f..5d6e34a45bfa 100644
--- a/packages/CarrierDefaultApp/res/values-uk/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-uk/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Наприклад, сторінка входу може не належати вказаній організації."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Усе одно продовжити у веб-переглядачі"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Підвищення продуктивності"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Покращте продуктивність свого з’єднання 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s рекомендує придбати тарифний план для підвищення продуктивності. Натисніть, щоб придбати через оператора %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Не зараз"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Керувати"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Придбайте підвищення продуктивності."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ur/strings.xml b/packages/CarrierDefaultApp/res/values-ur/strings.xml
index 681998bbecbd..466b6c85a27a 100644
--- a/packages/CarrierDefaultApp/res/values-ur/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ur/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"مثال کے طور پر ہو سکتا ہے کہ لاگ ان صفحہ دکھائی گئی تنظیم سے تعلق نہ رکھتا ہو۔"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"براؤزر کے ذریعے بہرحال جاری رکھیں"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"پرفارمینس بوسٹ"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"‏اپنے 5G تجربے کو بہتر بنائیں"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"‏%1$s ایک پرفارمنس بوسٹ پلان کی تجویز کرتا ہے۔ %2$s استعمال کر کے خریدنے کے لیے تھپتھپائیں۔"</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ابھی نہیں"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"نظم کریں"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"پرفارمینس بوسٹ خریدیں۔"</string>
diff --git a/packages/CarrierDefaultApp/res/values-uz/strings.xml b/packages/CarrierDefaultApp/res/values-uz/strings.xml
index 47006f680e29..82da958c63aa 100644
--- a/packages/CarrierDefaultApp/res/values-uz/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-uz/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Masalan, tizimga kirish sahifasi ko‘rsatilgan tashkilotga tegishli bo‘lmasligi mumkin."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Brauzerda davom ettirish"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Unumdorlikni kuchaytirish"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"5G bilan ishlashni qulaylashtiring"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s unumdorlikni oshiradigan tarif rejasini xarid qilishni tavsiya etadi. %2$s orqali xarid qilish uchun bosing."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Hozir emas"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Boshqarish"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Unumdorlikni kuchaytirish xizmatini xarid qiling."</string>
diff --git a/packages/CarrierDefaultApp/res/values-vi/strings.xml b/packages/CarrierDefaultApp/res/values-vi/strings.xml
index 968b6e19e769..225e07b99468 100644
--- a/packages/CarrierDefaultApp/res/values-vi/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-vi/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Ví dụ: trang đăng nhập có thể không thuộc về tổ chức được hiển thị."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Vẫn tiếp tục qua trình duyệt"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Tăng hiệu suất"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Cải thiện trải nghiệm sử dụng 5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s đề xuất bạn mua gói tăng cường hiệu suất. Nhấn để mua thông qua %2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Để sau"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Quản lý"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Mua gói tăng hiệu suất."</string>
diff --git a/packages/CarrierDefaultApp/res/values-zh-rCN/strings.xml b/packages/CarrierDefaultApp/res/values-zh-rCN/strings.xml
index 563117f83aab..5be55bc8d5d7 100644
--- a/packages/CarrierDefaultApp/res/values-zh-rCN/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-zh-rCN/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"例如,登录页面可能并不属于页面上显示的单位。"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"仍然通过浏览器继续操作"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"性能提升方案"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"改善 5G 体验"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s建议购买性能提升计划。点按即可通过%2$s进行购买。"</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"以后再说"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"管理"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"购买一份性能提升方案。"</string>
diff --git a/packages/CarrierDefaultApp/res/values-zh-rHK/strings.xml b/packages/CarrierDefaultApp/res/values-zh-rHK/strings.xml
index 7ed0c3c03897..92f53d3cc36a 100644
--- a/packages/CarrierDefaultApp/res/values-zh-rHK/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-zh-rHK/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"例如,登入頁面可能並不屬於所顯示的機構。"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"仍要透過瀏覽器繼續操作"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"效能提升服務"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"改善 5G 體驗"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"「%1$s」建議購買效能提升服務計劃。輕按即可透過「%2$s」購買。"</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"暫時不要"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"管理"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"購買效能提升服務。"</string>
diff --git a/packages/CarrierDefaultApp/res/values-zh-rTW/strings.xml b/packages/CarrierDefaultApp/res/values-zh-rTW/strings.xml
index 332ab9c809dd..6cb4b943f1b5 100644
--- a/packages/CarrierDefaultApp/res/values-zh-rTW/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-zh-rTW/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"例如,登入網頁中顯示的機構可能並非該網頁實際隸屬的機構。"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"仍要透過瀏覽器繼續操作"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"效能提升方案"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"改善 5G 體驗"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"「%1$s」建議購買效能提升方案,輕觸即可透過「%2$s」購買。"</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"暫時不要"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"管理"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"購買效能提升方案。"</string>
diff --git a/packages/CarrierDefaultApp/res/values-zu/strings.xml b/packages/CarrierDefaultApp/res/values-zu/strings.xml
index ae846955bb0d..f8bc50ceb446 100644
--- a/packages/CarrierDefaultApp/res/values-zu/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-zu/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Isibonelo, ikhasi lokungena ngemvume kungenzeka lingelenhlangano ebonisiwe."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Qhubeka noma kunjalo ngesiphequluli"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"I-boost yokusebenza"</string>
- <string name="performance_boost_notification_title" msgid="946857427149305992">"Thuthukisa umuzwa wakho we-5G"</string>
- <string name="performance_boost_notification_detail" msgid="362407668982648351">"I-%1$s incoma ukuthenga uhlelo lokuthuthukisa ukusebenza. Thepha ukuze uthenge nge-%2$s."</string>
+ <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Hhayi manje"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Phatha"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Thenga i-boost yokusebenza."</string>
diff --git a/packages/CarrierDefaultApp/res/values/strings.xml b/packages/CarrierDefaultApp/res/values/strings.xml
index 720e46dc9b8c..e91d35bf6979 100644
--- a/packages/CarrierDefaultApp/res/values/strings.xml
+++ b/packages/CarrierDefaultApp/res/values/strings.xml
@@ -19,7 +19,7 @@
<!-- Notification title text for the performance boost notification. -->
<string name="performance_boost_notification_title">Improve your app experience</string>
<!-- Notification detail text for the performance boost notification. -->
- <string name="performance_boost_notification_detail">Tap to visit %s\'s website and learn more.</string>
+ <string name="performance_boost_notification_detail">Tap to visit %s\'s website and learn more</string>
<!-- Notification button text to cancel the performance boost notification. -->
<string name="performance_boost_notification_button_not_now">Not now</string>
<!-- Notification button text to manage the performance boost notification. -->
diff --git a/packages/CompanionDeviceManager/res/values-am/strings.xml b/packages/CompanionDeviceManager/res/values-am/strings.xml
index 86d86527f74a..679dc33a03f4 100644
--- a/packages/CompanionDeviceManager/res/values-am/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-am/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"አጃቢ የመሣሪያ አስተዳዳሪ"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;ን እንዲደርስ ይፍቀዱለት"</string>
<string name="profile_name_watch" msgid="576290739483672360">"ሰዓት"</string>
<string name="chooser_title" msgid="2262294130493605839">"በ&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; የሚተዳደር <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ይምረጡ"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"የእርስዎን <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ለማስተዳደር መተግበሪያው ያስፈልጋል። <xliff:g id="APP_NAME">%2$s</xliff:g> እንደ የሚደውል ሰው ስም፣ ከማሳወቂያዎችዎ ጋር መስተጋብር እንዲፈጥር እና የእርስዎን ስልክ፣ ኤስኤምኤስ፣ ዕውቅያዎች፣ የቀን መቁጠሪያ፣ የጥሪ ምዝግብ ማስታወሻዎች እና በአቅራቢያ ያሉ መሣሪያዎችን መድረስ ያሉ መረጃዎችን እንዲያሰምር ይፈቀድለታል።"</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"የእርስዎን <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ለማስተዳደር መተግበሪያው ያስፈልጋል። <xliff:g id="APP_NAME">%2$s</xliff:g> እንደ የሚደውል ሰው ስም እና እነዚህን ፈቃዶች መድረስ ያሉ መረጃዎችን እንዲያሰምር ይፈቀድለታል፦"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"መነጽሮች"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"ይህ መተግበሪያ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>ን ለማስተዳደር ያስፈልጋል። <xliff:g id="APP_NAME">%2$s</xliff:g> ከማሳወቂያዎችዎ ጋር መስተጋብር እንዲፈጥር እና የእርስዎን ስልክ፣ ኤስኤምኤስ፣ ዕውቂያዎች፣ ማይክሮፎን እና በአቅራቢያ ያሉ መሣሪያዎች ፈቃዶችን እንዲደርስ ይፈቀድለታል።"</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"ይህ መተግበሪያ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>ን ለማስተዳደር ያስፈልጋል። <xliff:g id="APP_NAME">%2$s</xliff:g> ከእነዚህ ፈቃዶች ጋር መስተጋብር እንዲፈጥር ይፈቀድለታል፦"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ይህን መረጃ ከስልክዎ እንዲደርስበት ይፍቀዱለት"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"መሣሪያ ተሻጋሪ አገልግሎቶች"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> በእርስዎ መሣሪያዎች መካከል መተግበሪያዎችን በዥረት ለመልቀቅ የእርስዎን <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ወክሎ ፈቃድ እየጠየቀ ነው"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"መሣሪያ ተሻጋሪ አገልግሎቶች"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> በአቅራቢያ ወዳሉ መሣሪያዎች ይዘትን በዥረት ለመልቀቅ የእርስዎን <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ወክሎ ፈቃድ እየጠየቀ ነው"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"መሣሪያ"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"ይህ መተግበሪያ እንደ የሚደውል ሰው ስም ያለ መረጃን በስልክዎ እና <xliff:g id="DEVICE_NAME">%1$s</xliff:g> መካከል ማስመር ይችላል።"</string>
+ <string name="summary_generic" msgid="4988130802522924650">"ይህ መተግበሪያ እንደ የሚደውል ሰው ስም ያለ መረጃን በስልክዎ እና በተመረጠው መሣሪያ መካከል ማስመር ይችላል።"</string>
<string name="consent_yes" msgid="8344487259618762872">"ፍቀድ"</string>
<string name="consent_no" msgid="2640796915611404382">"አትፍቀድ"</string>
<string name="consent_back" msgid="2560683030046918882">"ተመለስ"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ar/strings.xml b/packages/CompanionDeviceManager/res/values-ar/strings.xml
index 5864ec993485..154a200a4fec 100644
--- a/packages/CompanionDeviceManager/res/values-ar/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ar/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"تطبيق \"مدير الجهاز المصاحب\""</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"‏السماح لتطبيق &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; بالوصول إلى &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
<string name="profile_name_watch" msgid="576290739483672360">"الساعة"</string>
<string name="chooser_title" msgid="2262294130493605839">"‏اختَر <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ليديرها تطبيق &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"يجب توفّر التطبيق لإدارة \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". سيتم السماح لتطبيق \"<xliff:g id="APP_NAME">%2$s</xliff:g>\" بمزامنة المعلومات، مثلاً اسم المتصل، والتفاعل مع الإشعارات والوصول إلى هاتفك، والرسائل القصيرة، وجهات الاتصال، والتقويم، وسجلات المكالمات وأذونات الأجهزة المجاورة."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"يجب توفّر التطبيق لإدارة \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". سيتم السماح لتطبيق \"<xliff:g id="APP_NAME">%2$s</xliff:g>\" بمزامنة المعلومات، مثلاً اسم المتصل، والوصول إلى الأذونات التالية:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"النظارة"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"يجب توفّر هذا التطبيق لإدارة \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". سيتم السماح لتطبيق \"<xliff:g id="APP_NAME">%2$s</xliff:g>\" بالتفاعل مع الإشعارات والوصول إلى أذونات الهاتف والرسائل القصيرة وجهات الاتصال والميكروفون والأجهزة المجاورة."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"يجب توفّر التطبيق لإدارة \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". سيتم السماح للتطبيق \"<xliff:g id="APP_NAME">%2$s</xliff:g>\" بالتفاعل مع هذه الأذونات."</string>
<string name="title_app_streaming" msgid="2270331024626446950">"‏السماح لتطبيق &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; بالوصول إلى هذه المعلومات من هاتفك"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"الخدمات التي تعمل بين الأجهزة"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"يطلب تطبيق <xliff:g id="APP_NAME">%1$s</xliff:g> الحصول على إذن نيابةً عن <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> لمشاركة التطبيقات بين أجهزتك."</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"خدمات تعمل على عدة أجهزة"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"يطلب \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" الحصول على إذن نيابةً عن \"<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>\" لبثّ محتوى إلى أجهزتك المجاورة."</string>
<string name="profile_name_generic" msgid="6851028682723034988">"جهاز"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"سيتمكن هذا التطبيق من مزامنة المعلومات، مثلاً اسم المتصل، بين هاتفك و\"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\"."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"سيتمكن هذا التطبيق من مزامنة المعلومات، مثلاً اسم المتصل، بين هاتفك والجهاز المحدد."</string>
<string name="consent_yes" msgid="8344487259618762872">"السماح"</string>
<string name="consent_no" msgid="2640796915611404382">"عدم السماح"</string>
<string name="consent_back" msgid="2560683030046918882">"رجوع"</string>
diff --git a/packages/CompanionDeviceManager/res/values-as/strings.xml b/packages/CompanionDeviceManager/res/values-as/strings.xml
index 38be80f9d9ad..cb2d2e0987ce 100644
--- a/packages/CompanionDeviceManager/res/values-as/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-as/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"কম্পেনিয়ন ডিভাইচ মেনেজাৰ"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;ক &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; এক্সেছ কৰিবলৈ দিয়ক"</string>
<string name="profile_name_watch" msgid="576290739483672360">"ঘড়ী"</string>
<string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;এ পৰিচালনা কৰিব লগা এটা <xliff:g id="PROFILE_NAME">%1$s</xliff:g> বাছনি কৰক"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"আপোনাৰ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> পৰিচালনা কৰিবলৈ এপ্‌টোৰ আৱশ্যক। <xliff:g id="APP_NAME">%2$s</xliff:g>ক কল কৰোঁতাৰ নামৰ দৰে তথ্য ছিংক কৰিবলৈ, আপোনাৰ জাননীৰ সৈতে ভাব-বিনিময় কৰিবলৈ আৰু আপোনাৰ ফ’ন, এছএমএছ, সম্পৰ্ক, কেলেণ্ডাৰ, কল লগ আৰু নিকটৱৰ্তী ডিভাইচৰ অনুমতিসমূহ এক্সেছ কৰিবলৈ দিয়া হ’ব।"</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"আপোনাৰ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> পৰিচালনা কৰিবলৈ এপ্‌টোৰ আৱশ্যক। <xliff:g id="APP_NAME">%2$s</xliff:g>ক কল কৰোঁতাৰ নামৰ দৰে তথ্য ছিংক কৰিবলৈ আৰু এই অনুমতিসমূহ এক্সেছ কৰিবলৈ অনুমতি দিয়া হ’ব:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"চছ্‌মা"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> পৰিচালনা কৰিবলৈ এই এপ্‌টোৰ আৱশ্যক। <xliff:g id="APP_NAME">%2$s</xliff:g>ক এই অনুমতিসমূহৰ সৈতে ভাব-বিনিময় কৰিবলৈ আৰু আপোনাৰ ফ’ন, এছএমএছ, সম্পৰ্ক, মাইক্ৰ’ফ’ন আৰু নিকটৱৰ্তী ডিভাইচৰ অনুমতিসমূহ এক্সেছ কৰিবলৈ দিয়া হ’ব।"</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> পৰিচালনা কৰিবলৈ এপ্‌টোৰ আৱশ্যক। <xliff:g id="APP_NAME">%2$s</xliff:g>ক এই অনুমতিসমূহৰ সৈতে ভাব-বিনিময় কৰিবলৈ দিয়া হ’ব:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;ক আপোনাৰ ফ’নৰ পৰা এই তথ্যখিনি এক্সেছ কৰাৰ অনুমতি দিয়ক"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"ক্ৰছ-ডিভাইচ সেৱাসমূহ"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ আপোনাৰ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ৰ হৈ আপোনাৰ ডিভাইচসমূহৰ মাজত এপ্‌ ষ্ট্ৰীম কৰাৰ বাবে অনুৰোধ জনাইছে"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"ক্ৰছ-ডিভাইচ সেৱাসমূহ"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ আপোনাৰ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ৰ হৈ নিকটৱৰ্তী ডিভাইচত সমল ষ্ট্ৰীম কৰাৰ অনুমতি দিবলৈ অনুৰোধ জনাইছে"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ডিভাইচ"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"এই এপ্‌টোৱে আপোনাৰ ফ’ন আৰু <xliff:g id="DEVICE_NAME">%1$s</xliff:g>ৰ মাজত তথ্য ছিংক কৰিব পাৰিব, যেনে, কল কৰোঁতাৰ নাম।"</string>
+ <string name="summary_generic" msgid="4988130802522924650">"এই এপ্‌টোৱে আপোনাৰ ফ’ন আৰু বাছনি কৰা ডিভাইচটোৰ মাজত তথ্য ছিংক কৰিব পাৰিব, যেনে, কল কৰোঁতাৰ নাম।"</string>
<string name="consent_yes" msgid="8344487259618762872">"অনুমতি দিয়ক"</string>
<string name="consent_no" msgid="2640796915611404382">"অনুমতি নিদিব"</string>
<string name="consent_back" msgid="2560683030046918882">"উভতি যাওক"</string>
diff --git a/packages/CompanionDeviceManager/res/values-az/strings.xml b/packages/CompanionDeviceManager/res/values-az/strings.xml
index e333c511a322..b882203f6767 100644
--- a/packages/CompanionDeviceManager/res/values-az/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-az/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Kompanyon Cihaz Meneceri"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; tətbiqinə &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; cihazına daxil olmaq icazəsi verin"</string>
<string name="profile_name_watch" msgid="576290739483672360">"izləyin"</string>
<string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; tərəfindən idarə ediləcək <xliff:g id="PROFILE_NAME">%1$s</xliff:g> seçin"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"Tətbiq <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazını idarə etmək üçün lazımdır. <xliff:g id="APP_NAME">%2$s</xliff:g> tətbiqinə zəng edənin adı kimi məlumatları sinxronlaşdırmaq, bildirişlərlə qarşılıqlı əlaqəyə girmək, habelə Telefon, SMS, Kontaktlar, Təqvim, Zəng qeydləri və Yaxınlıqdakı cihazlar üzrə icazələrə daxil olmaq imkanı veriləcək."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"Tətbiq <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazını idarə etmək üçün lazımdır. <xliff:g id="APP_NAME">%2$s</xliff:g> tətbiqinə zəng edənin adı kimi məlumatları sinxronlaşdırmaq və bu icazələrə daxil olmaq imkanı veriləcək:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"eynək"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"Bu tətbiq <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazını idarə etmək üçün lazımdır. <xliff:g id="APP_NAME">%2$s</xliff:g> üçün bildirişlərlə qarşılıqlı əlaqə, Telefon, SMS, Kontaktlar, Mikrofon və Yaxınlıqdakı cihazlar üzrə icazələrə giriş imkanı veriləcək."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"Tətbiq <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazını idarə etmək üçün lazımdır. <xliff:g id="APP_NAME">%2$s</xliff:g> tətbiqinə bu icazələrlə qarşılıqlı əlaqə imkanı veriləcək:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; tətbiqinə telefonunuzdan bu məlumata giriş icazəsi verin"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Cihazlararası xidmətlər"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> tətbiqi <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> adından cihazlarınız arasında tətbiqləri yayımlamaq üçün icazə istəyir"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Cihazlararası xidmətlər"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> tətbiqi <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> adından yaxınlıqdakı cihazlarda yayımlamaq üçün icazə istəyir"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"cihaz"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"Bu tətbiq telefon və <xliff:g id="DEVICE_NAME">%1$s</xliff:g> arasında zəng edənin adı kimi məlumatları sinxronlaşdıra biləcək."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"Bu tətbiq telefon və seçilmiş cihaz arasında zəng edənin adı kimi məlumatları sinxronlaşdıra biləcək."</string>
<string name="consent_yes" msgid="8344487259618762872">"İcazə verin"</string>
<string name="consent_no" msgid="2640796915611404382">"İcazə verməyin"</string>
<string name="consent_back" msgid="2560683030046918882">"Geriyə"</string>
diff --git a/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml b/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
index 8564793796c0..2add9f7e6aa4 100644
--- a/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Menadžer pridruženog uređaja"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"Dozvolite da &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; pristupa uređaju &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
<string name="profile_name_watch" msgid="576290739483672360">"sat"</string>
<string name="chooser_title" msgid="2262294130493605839">"Odaberite <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kojim će upravljati aplikacija &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"Aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> će dobiti dozvolu za sinhronizovanje informacija, poput osobe koja upućuje poziv, za interakciju sa obaveštenjima i pristup dozvolama za telefon, SMS, kontakte, kalendar, evidencije poziva i uređaje u blizini."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"Aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> će dobiti dozvolu za sinhronizaciju informacija, poput osobe koja upućuje poziv, kao za pristup sledećim dozvolama:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"naočare"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"Ova aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> će dobiti dozvolu za interakciju sa obaveštenjima i pristup dozvolama za telefon, SMS, kontakte, mikrofon i uređaje u blizini."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"Aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> će dobiti dozvolu za interakciju sa ovim dozvolama:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Dozvolite da &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; pristupa ovim informacijama sa telefona"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Usluge na više uređaja"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> zahteva dozvolu u ime uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> za strimovanje aplikacija između uređaja"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Usluge na više uređaja"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> zahteva dozvolu u ime uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> da strimuje sadržaj na uređaje u blizini"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"uređaj"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"Ova aplikacija će moći da sinhronizuje podatke, poput imena osobe koja upućuje poziv, između telefona i uređaja <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"Ova aplikacija će moći da sinhronizuje podatke, poput imena osobe koja upućuje poziv, između telefona i odabranog uređaja."</string>
<string name="consent_yes" msgid="8344487259618762872">"Dozvoli"</string>
<string name="consent_no" msgid="2640796915611404382">"Ne dozvoli"</string>
<string name="consent_back" msgid="2560683030046918882">"Nazad"</string>
diff --git a/packages/CompanionDeviceManager/res/values-be/strings.xml b/packages/CompanionDeviceManager/res/values-be/strings.xml
index 071dd6f34b5b..605ce339ed4e 100644
--- a/packages/CompanionDeviceManager/res/values-be/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-be/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Менеджар спадарожнай прылады"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"Дазвольце праграме &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; доступ да прылады &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
<string name="profile_name_watch" msgid="576290739483672360">"гадзіннік"</string>
<string name="chooser_title" msgid="2262294130493605839">"Выберыце прыладу (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>), якой будзе кіраваць праграма &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"Гэта праграма неабходная для кіравання прыладай \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". <xliff:g id="APP_NAME">%2$s</xliff:g> зможа сінхранізаваць інфармацыю (напрыклад, імя таго, хто звоніць), узаемадзейнічаць з вашымі апавяшчэннямі, а таксама атрымае доступ да тэлефона, SMS, кантактаў, календара, журналаў выклікаў і прылад паблізу."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"Гэта праграма неабходная для кіравання прыладай \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". <xliff:g id="APP_NAME">%2$s</xliff:g> зможа сінхранізаваць інфармацыю (напрыклад, імя таго, хто звоніць) і атрымае наступныя дазволы:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"акуляры"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"Гэта праграма неабходная для кіравання прыладай \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". <xliff:g id="APP_NAME">%2$s</xliff:g> зможа ўзаемадзейнічаць з вашымі апавяшчэннямі і атрымае доступ да тэлефона, SMS, кантактаў, мікрафона і прылад паблізу."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"Гэта праграма неабходная для кіравання прыладай \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". <xliff:g id="APP_NAME">%2$s</xliff:g> зможа выкарыстоўваць наступныя дазволы:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Дазвольце праграме &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; мець доступ да гэтай інфармацыі з вашага тэлефона"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Сэрвісы для некалькіх прылад"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"Праграма \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" запытвае дазвол ад імя вашай прылады \"<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>\" на трансляцыю праграм паміж вашымі прыладамі"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Сэрвісы для некалькіх прылад"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"Праграма \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" запытвае дазвол ад імя вашай прылады \"<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>\" на перадачу змесціва плынню на прылады паблізу."</string>
<string name="profile_name_generic" msgid="6851028682723034988">"прылада"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"Гэта праграма зможа сінхранізаваць інфармацыю (напрыклад, імя таго, хто звоніць) паміж тэлефонам і прыладай \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\"."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"Гэта праграма зможа сінхранізаваць інфармацыю (напрыклад, імя таго, хто звоніць) паміж тэлефонам і выбранай прыладай."</string>
<string name="consent_yes" msgid="8344487259618762872">"Дазволіць"</string>
<string name="consent_no" msgid="2640796915611404382">"Не дазваляць"</string>
<string name="consent_back" msgid="2560683030046918882">"Назад"</string>
diff --git a/packages/CompanionDeviceManager/res/values-bg/strings.xml b/packages/CompanionDeviceManager/res/values-bg/strings.xml
index 780924a7432f..f1dd8c05d737 100644
--- a/packages/CompanionDeviceManager/res/values-bg/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bg/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Companion Device Manager"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"Разрешаване на &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; да осъществява достъп до устройството &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
<string name="profile_name_watch" msgid="576290739483672360">"часовник"</string>
<string name="chooser_title" msgid="2262294130493605839">"Изберете устройство (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>), което да се управлява от &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"Това приложение е необходимо за управление на <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ще получи право да синхронизира различна информация, като например името на обаждащия се, да взаимодейства с известията ви и достъп до разрешенията за телефона, SMS съобщенията, контактите, календара, списъците с обажданията и устройствата в близост."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"Това приложение е необходимо за управление на <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ще получи право да синхронизира различна информация, като например името на обаждащия се, и достъп до следните разрешения:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"очилата"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"Това приложение е необходимо за управление на <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ще получи право да взаимодейства с известията ви, както и достъп до разрешенията за телефона, SMS съобщенията, контактите, микрофона и устройствата в близост."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"Това приложение е необходимо за управление на <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ще получи разрешение да взаимодейства със следните разрешения:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Разрешете на &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; да осъществява достъп до тази информация от телефона ви"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Услуги за различни устройства"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ иска разрешение от името на <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> да предава поточно приложения между устройствата ви"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Услуги за различни устройства"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> иска разрешение от името на <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> да предава поточно съдържание към устройства в близост"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"устройство"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"Това приложение ще може да синхронизира различна информация, като например името на обаждащия се, между телефона ви и <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"Това приложение ще може да синхронизира различна информация, като например името на обаждащия се, между телефона ви и избраното устройство."</string>
<string name="consent_yes" msgid="8344487259618762872">"Разрешаване"</string>
<string name="consent_no" msgid="2640796915611404382">"Забраняване"</string>
<string name="consent_back" msgid="2560683030046918882">"Назад"</string>
diff --git a/packages/CompanionDeviceManager/res/values-bn/strings.xml b/packages/CompanionDeviceManager/res/values-bn/strings.xml
index 88e334e55484..95ec4a6e2b00 100644
--- a/packages/CompanionDeviceManager/res/values-bn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bn/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Companion Device Manager"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"আপনার &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; অ্যাক্সেস করার জন্য &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; অ্যাপকে অনুমতি দিন"</string>
<string name="profile_name_watch" msgid="576290739483672360">"ঘড়ি"</string>
<string name="chooser_title" msgid="2262294130493605839">"<xliff:g id="PROFILE_NAME">%1$s</xliff:g> বেছে নিন যেটি &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; ম্যানেজ করবে"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"আপনার <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ম্যানেজ করার জন্য অ্যাপটি প্রয়োজন। <xliff:g id="APP_NAME">%2$s</xliff:g>-কে কলারের নামের মতো তথ্য সিঙ্ক করার অনুমতি দেওয়া হবে, এছাড়াও আপনার বিজ্ঞপ্তির সাথে ইন্টার‌্যাক্ট করা এবং আপনার ফোন, এসএমএস, পরিচিতি তালিকা, ক্যালেন্ডার, কল লগ এবং আশেপাশের ডিভাইস ব্যবহার করার অনুমতি অ্যাক্সেস করতে দেওয়া হবে।"</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"আপনার <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ম্যানেজ করার জন্য অ্যাপটি প্রয়োজন। <xliff:g id="APP_NAME">%2$s</xliff:g>-কে কলারের নামের মতো তথ্য় সিঙ্ক করতে এবং এইসব অনুমতি অ্যাক্সেস করতে দেওয়া হবে:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"চশমা"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"আপনার <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ম্যানেজ করতে এই অ্যাপটি প্রয়োজন। <xliff:g id="APP_NAME">%2$s</xliff:g>-কে আপনার বিজ্ঞপ্তির সাথে ইন্টার‌্যাক্ট করার অনুমতি দেওয়া হবে। এছাড়াও আপনার ফোন, এসএমএস, পরিচিতি তালিকা, মাইক্রোফোন এবং আশেপাশের ডিভাইস ব্যবহার করার অনুমতি অ্যাক্সেস করতে দেওয়া হবে।"</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ম্যানেজ করার জন্য অ্যাপটি প্রয়োজন। <xliff:g id="APP_NAME">%2$s</xliff:g> অ্যাপকে এইসব অনুমতির সাথে ইন্টার‌্যাক্ট করার জন্য অনুমোদন দেওয়া হবে:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"আপনার ফোন থেকে &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; অ্যাপকে এই তথ্য অ্যাক্সেস করার অনুমতি দিন"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"ক্রস-ডিভাইস পরিষেবা"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"আপনার ডিভাইসগুলির মধ্যে অ্যাপ স্ট্রিম করার জন্য <xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-এর হয়ে অনুমতি চাইছে"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"ক্রস-ডিভাইস পরিষেবা"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"আশেপাশের ডিভাইসে কন্টেন্ট স্ট্রিম করার জন্য আপনার <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-এর হয়ে <xliff:g id="APP_NAME">%1$s</xliff:g> অনুমতি চাইছে"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ডিভাইস"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"এই অ্যাপ আপনার ফোন এবং <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ডিভাইসের মধ্যে তথ্য সিঙ্ক করতে পারবে, যেমন কলারের নাম।"</string>
+ <string name="summary_generic" msgid="4988130802522924650">"এই অ্যাপ আপনার ফোন এবং বেছে নেওয়া ডিভাইসের মধ্যে তথ্য সিঙ্ক করতে পারবে, যেমন কলারের নাম।"</string>
<string name="consent_yes" msgid="8344487259618762872">"অনুমতি দিন"</string>
<string name="consent_no" msgid="2640796915611404382">"অনুমতি দেবেন না"</string>
<string name="consent_back" msgid="2560683030046918882">"ফিরুন"</string>
diff --git a/packages/CompanionDeviceManager/res/values-bs/strings.xml b/packages/CompanionDeviceManager/res/values-bs/strings.xml
index 4f8d37af6823..a4a825c46578 100644
--- a/packages/CompanionDeviceManager/res/values-bs/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bs/strings.xml
@@ -17,14 +17,14 @@
<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="4470785958457506021">"Prateći upravitelj uređaja"</string>
- <string name="confirmation_title" msgid="8024993972587946678">"Dopustite aplikaciji &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; da pristupa uređaju &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
+ <string name="confirmation_title" msgid="8024993972587946678">"Dozvolite aplikaciji &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; da pristupa uređaju &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
<string name="profile_name_watch" msgid="576290739483672360">"sat"</string>
<string name="chooser_title" msgid="2262294130493605839">"Odaberite uređaj \"<xliff:g id="PROFILE_NAME">%1$s</xliff:g>\" kojim će upravljati aplikacija &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
- <string name="summary_watch" msgid="6566922405914995759">"Aplikacija je potrebna za upravljanje vašim uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacija <xliff:g id="APP_NAME">%2$s</xliff:g> moći će sinkronizirati podatke, primjerice ime pozivatelja, stupati u interakciju s vašim obavijestima i pristupati vašim dopuštenjima za telefon, SMS-ove, kontakte, kalendar, zapisnike poziva i uređaje u blizini."</string>
- <string name="summary_watch_single_device" msgid="7443464525873186735">"Aplikacija je potrebna za upravljanje vašim uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacija <xliff:g id="APP_NAME">%2$s</xliff:g> moći će sinkronizirati podatke, primjerice ime pozivatelja i pristupati sljedećim dopuštenjima:"</string>
+ <string name="summary_watch" msgid="6566922405914995759">"Aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikaciji <xliff:g id="APP_NAME">%2$s</xliff:g> će biti dozvoljeni sinhroniziranje informacija, kao što je ime osobe koja upućuje poziv, interakcija s obavještenjima i pristup odobrenjima za Telefon, SMS-ove, Kontakte, Kalendar, Zapisnike poziva i Uređaje u blizini."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"Aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikaciji <xliff:g id="APP_NAME">%2$s</xliff:g> će biti dozvoljeni sinhroniziranje informacija, kao što je ime osobe koja upućuje poziv, i pristup ovim odobrenjima:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"naočale"</string>
- <string name="summary_glasses" msgid="3808267780579061241">"Ta je aplikacija potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacija <xliff:g id="APP_NAME">%2$s</xliff:g> moći će stupati u interakciju s vašim obavijestima i pristupati vašim dopuštenjima za telefon, SMS-ove, kontakte, mikrofon i uređaje u blizini."</string>
- <string name="summary_glasses_single_device" msgid="7051392780285915640">"Aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacija <xliff:g id="APP_NAME">%2$s</xliff:g> moći će stupati u interakciju s ovim dopuštenjima:"</string>
+ <string name="summary_glasses" msgid="3808267780579061241">"Ova aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikaciji <xliff:g id="APP_NAME">%2$s</xliff:g> će biti dozvoljena interakcija s obavještenjima i pristup odobrenjima za Telefon, SMS-ove, Kontakte, Mikrofon i Uređaje u blizini."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"Aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikaciji <xliff:g id="APP_NAME">%2$s</xliff:g> će biti dozvoljena interakcija s ovim odobrenjima:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Dozvolite da aplikacija &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; pristupa ovim informacijama s telefona"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Usluga na više uređaja"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> u ime uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> zahtijeva odobrenje da prenosi aplikacije između vaših uređaja"</string>
@@ -38,8 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Usluga na više uređaja"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> zahtijeva odobrenje u ime uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> da prenosi sadržaj na uređajima u blizini"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"uređaj"</string>
- <string name="summary_generic_single_device" msgid="4735072202474939111">"Ta će aplikacija moći sinkronizirati podatke između vašeg telefona i uređaja <xliff:g id="DEVICE_NAME">%1$s</xliff:g>, primjerice ime pozivatelja."</string>
- <string name="summary_generic" msgid="4988130802522924650">"Ta će aplikacija moći sinkronizirati podatke između vašeg telefona i odabranog uređaja, primjerice ime pozivatelja."</string>
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"Ova aplikacija će moći sinhronizirati informacije, kao što je ime osobe koja upućuje poziv, između vašeg telefona i uređaja <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"Ova aplikacija će moći sinhronizirati informacije, kao što je ime osobe koja upućuje poziv, između vašeg telefona i odabranog uređaja."</string>
<string name="consent_yes" msgid="8344487259618762872">"Dozvoli"</string>
<string name="consent_no" msgid="2640796915611404382">"Nemoj dozvoliti"</string>
<string name="consent_back" msgid="2560683030046918882">"Nazad"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ca/strings.xml b/packages/CompanionDeviceManager/res/values-ca/strings.xml
index c407a1c903f1..9e5aef7ee2f0 100644
--- a/packages/CompanionDeviceManager/res/values-ca/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ca/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Gestor de dispositius complementaris"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"Permet que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; accedeixi a &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
<string name="profile_name_watch" msgid="576290739483672360">"rellotge"</string>
<string name="chooser_title" msgid="2262294130493605839">"Tria un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> perquè el gestioni &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"L\'aplicació és necessària per gestionar el dispositiu (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>). <xliff:g id="APP_NAME">%2$s</xliff:g> tindrà permís per sincronitzar informació, com ara el nom d\'algú que truca, per interaccionar amb les teves notificacions i accedir al telèfon, als SMS, als contactes, al calendari, als registres de trucades i als dispositius propers."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"L\'aplicació és necessària per gestionar el dispositiu (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>). <xliff:g id="APP_NAME">%2$s</xliff:g> tindrà permís per sincronitzar informació, com ara el nom d\'algú que truca, i accedir a aquests permisos:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"ulleres"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"Aquesta aplicació es necessita per gestionar el dispositiu (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>). <xliff:g id="APP_NAME">%2$s</xliff:g> tindrà permís per interaccionar amb les teves notificacions i accedir al telèfon, als SMS, als contactes, al micròfon i als dispositius propers."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"L\'aplicació és necessària per gestionar el dispositiu (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>). <xliff:g id="APP_NAME">%2$s</xliff:g> tindrà permís per interaccionar amb aquests permisos:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Permet que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; accedeixi a aquesta informació del telèfon"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Serveis multidispositiu"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> demana permís en nom del teu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> per reproduir en continu aplicacions entre els dispositius"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Serveis multidispositiu"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> demana permís en nom del teu dispositiu (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) per reproduir contingut en continu en dispositius propers"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"dispositiu"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"Aquesta aplicació podrà sincronitzar informació, com ara el nom d\'algú que truca, entre el teu telèfon i el teu dispositiu (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>)."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"Aquesta aplicació podrà sincronitzar informació, com ara el nom d\'algú que truca, entre el teu telèfon i el dispositiu triat."</string>
<string name="consent_yes" msgid="8344487259618762872">"Permet"</string>
<string name="consent_no" msgid="2640796915611404382">"No permetis"</string>
<string name="consent_back" msgid="2560683030046918882">"Enrere"</string>
diff --git a/packages/CompanionDeviceManager/res/values-da/strings.xml b/packages/CompanionDeviceManager/res/values-da/strings.xml
index f1bf63361d87..99913da45749 100644
--- a/packages/CompanionDeviceManager/res/values-da/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-da/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Medfølgende enhedsadministrator"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"Tillad, at &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; får adgang til &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
<string name="profile_name_watch" msgid="576290739483672360">"ur"</string>
<string name="chooser_title" msgid="2262294130493605839">"Vælg det <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, som skal administreres af &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"Du skal bruge denne app for at administrere <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tilladelse til at interagere med dine notifikationer og synkronisere oplysninger som f.eks. navnet på en person, der ringer, og appen får adgang til dine tilladelser for Opkald, Sms, Kalender, Opkaldshistorik og Enheder i nærheden."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"Du skal bruge denne app for at administrere <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tilladelse til at synkronisere oplysninger som f.eks. navnet på en person, der ringer, og appen får adgang til følgende tilladelser:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"briller"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"Du skal bruge denne app for at administrere <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tilladelse til at interagere med dine notifikationer og tilgå tilladelserne Telefon, Sms, Kontakter, Mikrofon og Enheder i nærheden."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"Du skal bruge denne app for at administrere <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får mulighed for at interagere med følgende tilladelser:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Giv &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; adgang til disse oplysninger fra din telefon"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Tjenester, som kan tilsluttes en anden enhed"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> anmoder om tilladelse på vegne af din <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> til at streame apps mellem dine enheder"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Tjenester til flere enheder"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> anmoder om tilladelse på vegne af din <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> til at streame indhold til enheder i nærheden"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"enhed"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"Denne app vil kunne synkronisere oplysninger som f.eks. navnet på en person, der ringer, mellem din telefon og <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"Denne app vil kunne synkronisere oplysninger som f.eks. navnet på en person, der ringer, mellem din telefon og den valgte enhed."</string>
<string name="consent_yes" msgid="8344487259618762872">"Tillad"</string>
<string name="consent_no" msgid="2640796915611404382">"Tillad ikke"</string>
<string name="consent_back" msgid="2560683030046918882">"Tilbage"</string>
diff --git a/packages/CompanionDeviceManager/res/values-de/strings.xml b/packages/CompanionDeviceManager/res/values-de/strings.xml
index b914f2f95c48..ce22c34772db 100644
--- a/packages/CompanionDeviceManager/res/values-de/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-de/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Begleitgerät-Manager"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; erlauben, auf dein Gerät (&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;) zuzugreifen"</string>
<string name="profile_name_watch" msgid="576290739483672360">"Smartwatch"</string>
<string name="chooser_title" msgid="2262294130493605839">"Gerät „<xliff:g id="PROFILE_NAME">%1$s</xliff:g>“ auswählen, das von &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; verwaltet werden soll"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"Die App wird zur Verwaltung deines Geräts (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) benötigt. <xliff:g id="APP_NAME">%2$s</xliff:g> darf dann Daten wie den Namen eines Anrufers synchronisieren, mit deinen Benachrichtigungen interagieren und auf die Berechtigungen „Telefon“, „SMS“, „Kontakte“, „Kalender“, „Anruflisten“ und „Geräte in der Nähe“ zugreifen."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"Die App wird zur Verwaltung deines Geräts (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) benötigt. <xliff:g id="APP_NAME">%2$s</xliff:g> darf dann Daten wie den Namen eines Anrufers synchronisieren und auf folgende Berechtigungen zugreifen:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"Glass-Geräte"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"Diese App wird zur Verwaltung deines Geräts (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) benötigt. <xliff:g id="APP_NAME">%2$s</xliff:g> darf dann mit deinen Benachrichtigungen interagieren und auf die Berechtigungen „Telefon“, „SMS“, „Kontakte“, „Mikrofon“ und „Geräte in der Nähe“ zugreifen."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"Die App wird zur Verwaltung deines Geräts (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) benötigt. <xliff:g id="APP_NAME">%2$s</xliff:g> darf dann mit diesen Berechtigungen interagieren:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; Zugriff auf diese Informationen von deinem Smartphone gewähren"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Geräteübergreifende Dienste"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> bittet für dein <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> um die Berechtigung zum Streamen von Apps zwischen deinen Geräten"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Geräteübergreifende Dienste"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> bittet für dein Gerät (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) um die Berechtigung zum Streamen von Inhalten auf Geräte in der Nähe"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"Gerät"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"Diese App kann dann Daten wie den Namen eines Anrufers zwischen deinem Smartphone und deinem Gerät (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) synchronisieren."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"Diese App kann dann Daten wie den Namen eines Anrufers zwischen deinem Smartphone und dem ausgewählten Gerät synchronisieren."</string>
<string name="consent_yes" msgid="8344487259618762872">"Zulassen"</string>
<string name="consent_no" msgid="2640796915611404382">"Nicht zulassen"</string>
<string name="consent_back" msgid="2560683030046918882">"Zurück"</string>
diff --git a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
index 85333a902c56..debfcd929015 100644
--- a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Administrador de dispositivo complementario"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"Permite que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acceda a &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
<string name="profile_name_watch" msgid="576290739483672360">"reloj"</string>
<string name="chooser_title" msgid="2262294130493605839">"Elige un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para que la app &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; lo administre"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"Esta app es necesaria para administrar tu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> podrá sincronizar información, como el nombre de la persona que llama, interactuar con tus notificaciones y acceder a los permisos de Teléfono, SMS, Contactos, Calendario, Llamadas y Dispositivos cercanos."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"Esta app es necesaria para administrar tu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> podrá sincronizar información, como el nombre de la persona que llama, y acceder a los siguientes permisos:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"Gafas"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"Esta app es necesaria para administrar <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> podrá interactuar con tus notificaciones y acceder a los permisos de Teléfono, SMS, Contactos, Micrófono y Dispositivos cercanos."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"Esta app es necesaria para administrar <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> podrá interactuar con estos permisos:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Permite que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acceda a esta información de tu teléfono"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Servicios multidispositivo"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicita tu permiso en nombre de <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para transmitir apps entre dispositivos"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Servicios multidispositivo"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicita tu permiso en nombre de <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para transmitir contenido a dispositivos cercanos"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"Esta app podrá sincronizar información, como el nombre de la persona que llama, entre el teléfono y <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"Esta app podrá sincronizar información, como el nombre de la persona que llama, entre el teléfono y el dispositivo elegido."</string>
<string name="consent_yes" msgid="8344487259618762872">"Permitir"</string>
<string name="consent_no" msgid="2640796915611404382">"No permitir"</string>
<string name="consent_back" msgid="2560683030046918882">"Atrás"</string>
diff --git a/packages/CompanionDeviceManager/res/values-es/strings.xml b/packages/CompanionDeviceManager/res/values-es/strings.xml
index c5127e88087a..acdb957237b4 100644
--- a/packages/CompanionDeviceManager/res/values-es/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-es/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Gestor de dispositivos complementario"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"Permitir que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acceda a &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
<string name="profile_name_watch" msgid="576290739483672360">"reloj"</string>
<string name="chooser_title" msgid="2262294130493605839">"Elige un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para gestionarlo con &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"Se necesita la aplicación para gestionar <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> podrá sincronizar información (por ejemplo, el nombre de la persona que te llama), interactuar con tus notificaciones y acceder a tus permisos de teléfono, SMS, contactos, calendario, registros de llamadas y dispositivos cercanos."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"Se necesita la aplicación para gestionar <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> podrá sincronizar información (por ejemplo, el nombre de la persona que te llama) y acceder a los permisos siguientes:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"gafas"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"Se necesita esta aplicación para gestionar <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> podrá interactuar con tus notificaciones y acceder a tus permisos de teléfono, SMS, contactos, micrófono y dispositivos cercanos."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"Se necesita la aplicación para gestionar <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Se permitirá que <xliff:g id="APP_NAME">%2$s</xliff:g> interaccione con los siguientes permisos:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Permitir que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acceda a esta información de tu teléfono"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Servicios multidispositivo"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> está pidiendo permiso en nombre de tu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para emitir aplicaciones en otros dispositivos tuyos"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Servicios multidispositivo"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> está pidiendo permiso en nombre de tu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para reproducir contenido en dispositivos cercanos"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"Esta aplicación podrá sincronizar información (por ejemplo, el nombre de la persona que te llama) entre tu teléfono y <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"Esta aplicación podrá sincronizar información (por ejemplo, el nombre de la persona que te llama) entre tu teléfono y el dispositivo que elijas."</string>
<string name="consent_yes" msgid="8344487259618762872">"Permitir"</string>
<string name="consent_no" msgid="2640796915611404382">"No permitir"</string>
<string name="consent_back" msgid="2560683030046918882">"Atrás"</string>
diff --git a/packages/CompanionDeviceManager/res/values-et/strings.xml b/packages/CompanionDeviceManager/res/values-et/strings.xml
index cd362de77126..0e029bdf5233 100644
--- a/packages/CompanionDeviceManager/res/values-et/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-et/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Kaasseadme haldur"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"Andke rakendusele &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; juurdepääs seadmele &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
<string name="profile_name_watch" msgid="576290739483672360">"käekell"</string>
<string name="chooser_title" msgid="2262294130493605839">"Valige <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, mida haldab rakendus &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"Seda rakendust on vaja teie seadme <xliff:g id="DEVICE_NAME">%1$s</xliff:g> haldamiseks. Rakendusel <xliff:g id="APP_NAME">%2$s</xliff:g> lubatakse sünkroonida teavet, näiteks helistaja nime, kasutada teie märguandeid ning pääseda juurde teie telefoni, SMS-ide, kontaktide, kalendri, kõnelogide ja läheduses olevate seadmete lubadele."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"Seda rakendust on vaja teie seadme <xliff:g id="DEVICE_NAME">%1$s</xliff:g> haldamiseks. <xliff:g id="APP_NAME">%2$s</xliff:g> lubatakse sünkroonida teavet, näiteks helistaja nime, ja pääseda juurde järgmistele lubadele."</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"prillid"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"Seda rakendust on vaja seadme <xliff:g id="DEVICE_NAME">%1$s</xliff:g> haldamiseks. Rakendusel <xliff:g id="APP_NAME">%2$s</xliff:g> lubatakse kasutada teie märguandeid ning pääseda juurde teie telefoni, SMS-ide, kontaktide, mikrofoni ja läheduses olevate seadmete lubadele."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"Seda rakendust on vaja seadme <xliff:g id="DEVICE_NAME">%1$s</xliff:g> haldamiseks. Rakendusel <xliff:g id="APP_NAME">%2$s</xliff:g> lubatakse kasutada järgmisi lube."</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Lubage rakendusel &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; pääseda teie telefonis juurde sellele teabele"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Seadmeülesed teenused"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> taotleb teie seadme <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> nimel luba teie seadmete vahel rakendusi voogesitada"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Seadmeülesed teenused"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> taotleb teie seadme <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> nimel luba voogesitada sisu läheduses olevates seadmetes"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"seade"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"See rakendus saab sünkroonida teavet, näiteks helistaja nime, teie telefoni ja seadme <xliff:g id="DEVICE_NAME">%1$s</xliff:g> vahel."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"See rakendus saab sünkroonida teavet, näiteks helistaja nime, teie telefoni ja valitud seadme vahel."</string>
<string name="consent_yes" msgid="8344487259618762872">"Luba"</string>
<string name="consent_no" msgid="2640796915611404382">"Ära luba"</string>
<string name="consent_back" msgid="2560683030046918882">"Tagasi"</string>
diff --git a/packages/CompanionDeviceManager/res/values-eu/strings.xml b/packages/CompanionDeviceManager/res/values-eu/strings.xml
index d2a7d988244f..8d58f88256cb 100644
--- a/packages/CompanionDeviceManager/res/values-eu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-eu/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Gailu osagarriaren kudeatzailea"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"Eman &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; erabiltzeko baimena &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; aplikazioari"</string>
<string name="profile_name_watch" msgid="576290739483672360">"erlojua"</string>
<string name="chooser_title" msgid="2262294130493605839">"Aukeratu &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; aplikazioak kudeatu beharreko <xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> kudeatzeko behar da aplikazioa. Informazioa sinkronizatzeko (esate baterako, deitzaileen izenak), jakinarazpenekin interakzioan aritzeko, eta telefonoa, SMSak, kontaktuak, egutegia, deien erregistroa eta inguruko gailuak erabiltzeko baimena izango du <xliff:g id="APP_NAME">%2$s</xliff:g> aplikazioak."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> kudeatzeko behar da aplikazioa. Informazioa sinkronizatzeko (esate baterako, deitzaileen izenak) eta ekintza hauek gauzatzeko baimena izango du <xliff:g id="APP_NAME">%2$s</xliff:g> aplikazioak:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"betaurrekoak"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> kudeatzeko behar da aplikazioa. Jakinarazpenekin interakzioan aritzeko, eta telefonoa, SMSak, kontaktuak, mikrofonoa eta inguruko gailuak erabiltzeko baimena izango du <xliff:g id="APP_NAME">%2$s</xliff:g> aplikazioak."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> kudeatzeko behar da aplikazioa. Baimen hauek izango ditu <xliff:g id="APP_NAME">%2$s</xliff:g> aplikazioak:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Eman informazioa telefonotik hartzeko baimena &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; aplikazioari"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Gailu baterako baino gehiagotarako zerbitzuak"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"Gailu batetik bestera aplikazioak igortzeko baimena eskatzen ari da <xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> gailuaren izenean"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Gailu baterako baino gehiagotarako zerbitzuak"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"Inguruko gailuetara edukia igortzeko baimena eskatzen ari da <xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> gailuaren izenean"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"gailua"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"Telefonoaren eta <xliff:g id="DEVICE_NAME">%1$s</xliff:g> gailuaren artean informazioa sinkronizatzeko gai izango da aplikazioa (esate baterako, deitzaileen izenak)."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"Telefonoaren eta hautatutako gailuaren artean informazioa sinkronizatzeko gai izango da aplikazioa (esate baterako, deitzaileen izenak)."</string>
<string name="consent_yes" msgid="8344487259618762872">"Eman baimena"</string>
<string name="consent_no" msgid="2640796915611404382">"Ez eman baimenik"</string>
<string name="consent_back" msgid="2560683030046918882">"Atzera"</string>
diff --git a/packages/CompanionDeviceManager/res/values-fa/strings.xml b/packages/CompanionDeviceManager/res/values-fa/strings.xml
index 1d283f0a424b..701cdb3ebee0 100644
--- a/packages/CompanionDeviceManager/res/values-fa/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fa/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"مدیر دستگاه مرتبط"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"‏اجازه دادن به &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; برای دسترسی به &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
<string name="profile_name_watch" msgid="576290739483672360">"ساعت"</string>
<string name="chooser_title" msgid="2262294130493605839">"‏انتخاب <xliff:g id="PROFILE_NAME">%1$s</xliff:g> برای مدیریت کردن با &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>‏&lt;/strong&gt;"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"این برنامه برای مدیریت <xliff:g id="DEVICE_NAME">%1$s</xliff:g> شما لازم است. به <xliff:g id="APP_NAME">%2$s</xliff:g> اجازه داده می‌شود اطلاعاتی مثل نام شخصی که تماس می‌گیرد را همگام‌سازی کند، با اعلان‌های شما تعامل داشته باشد، و به اجازه‌های «تلفن»، «پیامک»، «مخاطبین»، «تقویم»، «گزارش‌های تماس»، و «دستگاه‌های اطراف» دسترسی داشته باشد."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"این برنامه برای مدیریت <xliff:g id="DEVICE_NAME">%1$s</xliff:g> شما لازم است. به <xliff:g id="APP_NAME">%2$s</xliff:g> اجازه داده می‌شود اطلاعاتی مثل نام شخصی که تماس می‌گیرد را همگام‌سازی کند و به این اجازه‌ها دسترسی داشته باشد:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"عینک"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"این برنامه برای مدیریت <xliff:g id="DEVICE_NAME">%1$s</xliff:g> لازم است. به <xliff:g id="APP_NAME">%2$s</xliff:g> اجازه داده می‌شود با اعلان‌های شما تعامل داشته باشد و به اجازه‌های «تلفن»، «پیامک»، «مخاطبین»، «میکروفون»، و «دستگاه‌های اطراف» دسترسی داشته باشد."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"این برنامه برای مدیریت <xliff:g id="DEVICE_NAME">%1$s</xliff:g> لازم است. <xliff:g id="APP_NAME">%2$s</xliff:g> مجاز می‌شود با این اجازه‌ها تعامل داشته باشد:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"‏اجازه دادن به &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; برای دسترسی به اطلاعات تلفن"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"سرویس‌های بین‌دستگاهی"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> اجازه می‌خواهد ازطرف <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> برنامه‌ها را بین دستگاه‌های شما جاری‌سازی کند"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"سرویس‌های بین‌دستگاهی"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> ازطرف <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> اجازه می‌خواهد تا در دستگاه‌های اطراف محتوا جاری‌سازی کند."</string>
<string name="profile_name_generic" msgid="6851028682723034988">"دستگاه"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"این برنامه مجاز می‌شود اطلاعتی مثل نام شخصی که تماس می‌گیرد را بین تلفن شما و <xliff:g id="DEVICE_NAME">%1$s</xliff:g> همگام‌سازی کند."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"این برنامه مجاز می‌شود اطلاعتی مثل نام شخصی که تماس می‌گیرد را بین تلفن شما و دستگاه انتخاب‌شده همگام‌سازی کند."</string>
<string name="consent_yes" msgid="8344487259618762872">"اجازه دادن"</string>
<string name="consent_no" msgid="2640796915611404382">"اجازه ندادن"</string>
<string name="consent_back" msgid="2560683030046918882">"برگشتن"</string>
diff --git a/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
index 3f9ec0b1d46b..1c6daef91d00 100644
--- a/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Gestionnaire d\'appareil compagnon"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"Autoriser &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; à accéder à &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
<string name="profile_name_watch" msgid="576290739483672360">"montre"</string>
<string name="chooser_title" msgid="2262294130493605839">"Choisissez un(e) <xliff:g id="PROFILE_NAME">%1$s</xliff:g> qui sera géré(e) par &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"L\'application est nécessaire pour gérer votre <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> aura l\'autorisation de synchroniser des informations, comme le nom de l\'appelant, d\'interagir avec vos notifications et d\'accéder à vos autorisations pour le téléphone, les messages texte, les contacts, l\'agenda, les journaux d\'appels et les appareils à proximité."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"L\'application est nécessaire pour gérer votre <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> aura l\'autorisation de synchroniser des informations, comme le nom de l\'appelant, et d\'accéder à ces autorisations :"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"lunettes"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"Cette application est nécessaire pour gérer <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> sera autorisée à interagir avec vos notifications et à accéder à vos autorisations pour le téléphone, les messages texte, les contacts, le microphone et les appareils à proximité."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"L\'application est nécessaire pour gérer <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> aura l\'autorisation d\'interagir avec ces autorisations :"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Autorisez &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; à accéder à ces informations à partir de votre téléphone"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Services multiappareils"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation au nom de votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> pour diffuser des applications entre vos appareils"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Services multiappareils"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation au nom de votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> de diffuser du contenu aux appareils à proximité"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"appareil"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"Cette application pourra synchroniser des informations, comme le nom de l\'appelant, entre votre téléphone et <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"Cette application pourra synchroniser des informations, comme le nom de l\'appelant, entre votre téléphone et l\'appareil sélectionné."</string>
<string name="consent_yes" msgid="8344487259618762872">"Autoriser"</string>
<string name="consent_no" msgid="2640796915611404382">"Ne pas autoriser"</string>
<string name="consent_back" msgid="2560683030046918882">"Retour"</string>
diff --git a/packages/CompanionDeviceManager/res/values-fr/strings.xml b/packages/CompanionDeviceManager/res/values-fr/strings.xml
index d05087d48af1..bbdb5ce65db1 100644
--- a/packages/CompanionDeviceManager/res/values-fr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fr/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Gestionnaire d\'appareils associés"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"Autoriser &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; à accéder à &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
<string name="profile_name_watch" msgid="576290739483672360">"montre"</string>
<string name="chooser_title" msgid="2262294130493605839">"Sélectionnez le/la <xliff:g id="PROFILE_NAME">%1$s</xliff:g> qui sera géré(e) par &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"Cette appli est nécessaire pour gérer votre <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> aura l\'autorisation de synchroniser des informations (comme le nom de la personne à l\'origine d\'un appel entrant), d\'interagir avec vos notifications et d\'accéder aux autorisations du téléphone, des SMS, des contacts, de l\'agenda, des journaux d\'appels et des appareils à proximité."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"Cette appli est nécessaire pour gérer votre <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> aura l\'autorisation de synchroniser vos informations, comme le nom de la personne à l\'origine d\'un appel entrant, et d\'accéder à ces autorisations :"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"lunettes"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"Cette appli est nécessaire pour gérer <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> aura l\'autorisation d\'interagir avec vos notifications et d\'accéder aux autorisations du téléphone, des SMS, des contacts, du micro et des appareils à proximité."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"Cette appli est nécessaire pour gérer <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> pourra interagir avec ces autorisations :"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Autoriser &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; à accéder à ces informations depuis votre téléphone"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Services inter-appareils"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation au nom de votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> pour caster des applis d\'un appareil à l\'autre"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Services inter-appareils"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation au nom de votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> de diffuser du contenu en streaming sur les appareils à proximité"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"appareil"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"Cette appli pourra synchroniser des informations entre votre téléphone et <xliff:g id="DEVICE_NAME">%1$s</xliff:g>, comme le nom de la personne à l\'origine d\'un appel entrant."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"Cette appli pourra synchroniser des informations entre votre téléphone et l\'appareil choisi, comme le nom de la personne à l\'origine d\'un appel entrant."</string>
<string name="consent_yes" msgid="8344487259618762872">"Autoriser"</string>
<string name="consent_no" msgid="2640796915611404382">"Ne pas autoriser"</string>
<string name="consent_back" msgid="2560683030046918882">"Retour"</string>
diff --git a/packages/CompanionDeviceManager/res/values-gl/strings.xml b/packages/CompanionDeviceManager/res/values-gl/strings.xml
index f3e2d4313413..0a6db74883fd 100644
--- a/packages/CompanionDeviceManager/res/values-gl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-gl/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Xestor de dispositivos complementarios"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"Permitir que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acceda ao dispositivo (&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;)"</string>
<string name="profile_name_watch" msgid="576290739483672360">"reloxo"</string>
<string name="chooser_title" msgid="2262294130493605839">"Escolle un dispositivo (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>) para que o xestione a aplicación &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"A aplicación é necesaria para xestionar o teu dispositivo (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>). <xliff:g id="APP_NAME">%2$s</xliff:g> poderá sincronizar información (por exemplo, o nome de quen chama), interactuar coas túas notificacións e acceder aos permisos do teu teléfono, das SMS, dos contactos, do calendario, dos rexistros de chamadas e dos dispositivos próximos."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"A aplicación é necesaria para xestionar o teu dispositivo (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>). <xliff:g id="APP_NAME">%2$s</xliff:g> poderá sincronizar información (por exemplo, o nome de quen chama) e acceder a estes permisos:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"lentes"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"Esta aplicación é necesaria para xestionar o dispositivo (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>). <xliff:g id="APP_NAME">%2$s</xliff:g> poderá interactuar coas túas notificacións e acceder aos permisos do teu teléfono, das SMS, dos contactos, do micrófono e dos dispositivos próximos."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"A aplicación é necesaria para xestionar o dispositivo (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>). <xliff:g id="APP_NAME">%2$s</xliff:g> poderá interactuar con estes permisos:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Permitir que a aplicación &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; acceda a esta información desde o teu teléfono"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Servizos multidispositivo"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> está solicitando permiso en nome do teu dispositivo (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) para emitir contido de aplicacións entre os teus aparellos"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Servizos multidispositivo"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> está solicitando permiso en nome do teu dispositivo (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) para emitir contido aos dispositivos próximos"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"Esta aplicación poderá sincronizar información (por exemplo, o nome de quen chama) entre o teléfono e o dispositivo (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>)."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"Esta aplicación poderá sincronizar información (por exemplo, o nome de quen chama) entre o teléfono e o dispositivo escollido."</string>
<string name="consent_yes" msgid="8344487259618762872">"Permitir"</string>
<string name="consent_no" msgid="2640796915611404382">"Non permitir"</string>
<string name="consent_back" msgid="2560683030046918882">"Atrás"</string>
diff --git a/packages/CompanionDeviceManager/res/values-gu/strings.xml b/packages/CompanionDeviceManager/res/values-gu/strings.xml
index 5e21ccbb8dc5..1a6107e07162 100644
--- a/packages/CompanionDeviceManager/res/values-gu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-gu/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"કમ્પેનિયન ડિવાઇસ મેનેજર"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;ને &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; ઍક્સેસ કરવાની મંજૂરી આપો"</string>
<string name="profile_name_watch" msgid="576290739483672360">"સ્માર્ટવૉચ"</string>
<string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; દ્વારા મેનેજ કરવા માટે કોઈ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> પસંદ કરો"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"તમારા <xliff:g id="DEVICE_NAME">%1$s</xliff:g>ને મેનેજ કરવા માટે ઍપ જરૂરી છે. <xliff:g id="APP_NAME">%2$s</xliff:g>ને કૉલ કરનાર વ્યક્તિનું નામ જેવી માહિતી સિંક કરવાની, તમારા નોટિફિકેશન સાથે ક્રિયાપ્રતિક્રિયા કરવાની અને તમારો ફોન, SMS, સંપર્કો, Calendar, કૉલ લૉગ તથા નજીકના ડિવાઇસની પરવાનગીઓ ઍક્સેસ કરવાની મંજૂરી આપવામાં આવશે."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"તમારા <xliff:g id="DEVICE_NAME">%1$s</xliff:g>ને મેનેજ કરવા માટે ઍપ જરૂરી છે. <xliff:g id="APP_NAME">%2$s</xliff:g>ને કૉલ કરનાર વ્યક્તિનું નામ જેવી માહિતી સિંક કરવાની અને આ પરવાનગીઓ ઍક્સેસ કરવાની મંજૂરી આપવામાં આવશે:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"ચશ્માં"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>ને મેનેજ કરવા માટે આ ઍપ જરૂરી છે. <xliff:g id="APP_NAME">%2$s</xliff:g>ને તમારા નોટિફિકેશન સાથે ક્રિયાપ્રતિક્રિયા કરવાની અને તમારો ફોન, SMS, સંપર્કો, માઇક્રોફોન તથા નજીકના ડિવાઇસની પરવાનગીઓ ઍક્સેસ કરવાની મંજૂરી આપવામાં આવશે."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>ને મેનેજ કરવા માટે ઍપ જરૂરી છે. <xliff:g id="APP_NAME">%2$s</xliff:g>ને આ પરવાનગીઓ સાથે ક્રિયાપ્રતિક્રિયા કરવાની મંજૂરી આપવામાં આવશે:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"તમારા ફોનમાંથી આ માહિતી ઍક્સેસ કરવા માટે, &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;ને મંજૂરી આપો"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"ક્રોસ-ડિવાઇસ સેવાઓ"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> તમારા <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> વતી તમારા ડિવાઇસ વચ્ચે ઍપ સ્ટ્રીમ કરવાની પરવાનગીની વિનંતી કરી રહી છે"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"ક્રૉસ-ડિવાઇસ સેવાઓ"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> નજીકના ડિવાઇસ પર કન્ટેન્ટ સ્ટ્રીમ કરવા માટે તમારા <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> વતી પરવાનગીની વિનંતી કરી રહી છે"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ડિવાઇસ"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"આ ઍપ તમારા ફોન અને <xliff:g id="DEVICE_NAME">%1$s</xliff:g> વચ્ચે, કૉલ કરનાર કોઈ વ્યક્તિનું નામ જેવી માહિતી સિંક કરી શકશે."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"આ ઍપ તમારા ફોન અને પસંદ કરેલા ડિવાઇસ વચ્ચે, કૉલ કરનાર કોઈ વ્યક્તિનું નામ જેવી માહિતી સિંક કરી શકશે."</string>
<string name="consent_yes" msgid="8344487259618762872">"મંજૂરી આપો"</string>
<string name="consent_no" msgid="2640796915611404382">"મંજૂરી આપશો નહીં"</string>
<string name="consent_back" msgid="2560683030046918882">"પાછળ"</string>
diff --git a/packages/CompanionDeviceManager/res/values-hi/strings.xml b/packages/CompanionDeviceManager/res/values-hi/strings.xml
index 4c52ad7debf6..4ceb30ca6fe9 100644
--- a/packages/CompanionDeviceManager/res/values-hi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hi/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"सहयोगी डिवाइस मैनेजर"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; को &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; की जानकारी ऐक्सेस करने की अनुमति दें"</string>
<string name="profile_name_watch" msgid="576290739483672360">"स्मार्टवॉच"</string>
<string name="chooser_title" msgid="2262294130493605839">"कोई <xliff:g id="PROFILE_NAME">%1$s</xliff:g> चुनें, ताकि उसे &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; की मदद से मैनेज किया जा सके"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"यह ऐप्लिकेशन, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> को मैनेज करने के लिए ज़रूरी है. <xliff:g id="APP_NAME">%2$s</xliff:g> को डिवाइस की जानकारी सिंक करने की अनुमति होगी. जैसे, कॉल करने वाले व्यक्ति का नाम. इसे आपकी सूचनाओं पर कार्रवाई करने के साथ-साथ आपके फ़ोन, एसएमएस, संपर्कों, कैलेंडर, कॉल लॉग, और आस-पास मौजूद डिवाइसों को ऐक्सेस करने की अनुमति भी होगी."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"यह ऐप्लिकेशन, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> को मैनेज करने के लिए ज़रूरी है. <xliff:g id="APP_NAME">%2$s</xliff:g> को डिवाइस की जानकारी सिंक करने की अनुमति होगी. जैसे, कॉल करने वाले व्यक्ति का नाम. ऐप्लिकेशन इन अनुमतियों का भी इस्तेमाल कर पाएगा:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"चश्मा"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"यह ऐप्लिकेशन, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> को मैनेज करने के लिए ज़रूरी है. <xliff:g id="APP_NAME">%2$s</xliff:g> को डिवाइस की सूचनाओं पर कार्रवाई करने की अनुमति होगी. इसे आपके फ़ोन, मैसेज, संपर्कों, माइक्रोफ़ोन, और आस-पास मौजूद डिवाइसों को ऐक्सेस करने की अनुमति भी होगी."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"यह ऐप्लिकेशन, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> को मैनेज करने के लिए ज़रूरी है. <xliff:g id="APP_NAME">%2$s</xliff:g>, इन अनुमतियों का इस्तेमाल कर पाएगा:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; को अपने फ़ोन से यह जानकारी ऐक्सेस करने की अनुमति दें"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"क्रॉस-डिवाइस से जुड़ी सेवाएं"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> आपके <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> की ओर से, आपके डिवाइसों के बीच ऐप्लिकेशन को स्ट्रीम करने की अनुमति मांग रहा है"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"क्रॉस-डिवाइस से जुड़ी सेवाएं"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> आपके <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> की ओर से, कॉन्टेंट को आस-पास मौजूद डिवाइसों पर स्ट्रीम करने की अनुमति मांग रहा है"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"डिवाइस"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"यह ऐप्लिकेशन, आपके फ़ोन और <xliff:g id="DEVICE_NAME">%1$s</xliff:g> के बीच जानकारी सिंक कर सकता है. जैसे, कॉल करने वाले व्यक्ति का नाम."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"यह ऐप्लिकेशन, आपके फ़ोन और चुने हुए डिवाइस के बीच जानकारी सिंक कर सकता है. जैसे, कॉल करने वाले व्यक्ति का नाम."</string>
<string name="consent_yes" msgid="8344487259618762872">"अनुमति दें"</string>
<string name="consent_no" msgid="2640796915611404382">"अनुमति न दें"</string>
<string name="consent_back" msgid="2560683030046918882">"वापस जाएं"</string>
diff --git a/packages/CompanionDeviceManager/res/values-hu/strings.xml b/packages/CompanionDeviceManager/res/values-hu/strings.xml
index cfd6ad413f22..8151038e8e71 100644
--- a/packages/CompanionDeviceManager/res/values-hu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hu/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Társeszközök kezelője"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"A(z) &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; hozzáférésének engedélyezése a(z) &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; eszközhöz"</string>
<string name="profile_name_watch" msgid="576290739483672360">"óra"</string>
<string name="chooser_title" msgid="2262294130493605839">"A(z) &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; alkalmazással kezelni kívánt <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kiválasztása"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"Az alkalmazásra szükség van a következő eszköz kezeléséhez: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. A(z) <xliff:g id="APP_NAME">%2$s</xliff:g> képes lesz szinkronizálni információkat (például a hívó fél nevét), műveleteket végezhet majd az értesítésekkel, és hozzáférhet majd a Telefon, az SMS, a Névjegyek, a Naptár, a Hívásnaplók és a Közeli eszközök engedélyekhez."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"Az alkalmazásra szükség van a következő eszköz kezeléséhez: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. A(z) <xliff:g id="APP_NAME">%2$s</xliff:g> képes lesz szinkronizálni információkat (például a hívó fél nevét), és hozzáférhet majd ezekhez az engedélyekhez:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"szemüveg"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"Erre az alkalmazásra szükség van a következő eszköz kezeléséhez: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. A(z) <xliff:g id="APP_NAME">%2$s</xliff:g> műveleteket végezhet majd az értesítésekkel, és hozzáférhet majd a Telefon, az SMS, a Névjegyek, a Mikrofon és a Közeli eszközök engedélyekhez."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"Az alkalmazásra szükség van a következő eszköz kezeléséhez: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. A(z) <xliff:g id="APP_NAME">%2$s</xliff:g> műveleteket végezhet majd ezekkel az engedélyekkel:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Engedélyezi a(z) „<xliff:g id="APP_NAME">%1$s</xliff:g>” alkalmazás számára az információhoz való hozzáférést a telefonról"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Többeszközös szolgáltatások"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> engedélyt kér a(z) <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> nevében az alkalmazások eszközök közötti streameléséhez"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Többeszközös szolgáltatások"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> engedélyt kér a(z) <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> nevében a közeli eszközökre való streameléséhez."</string>
<string name="profile_name_generic" msgid="6851028682723034988">"eszköz"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"Ez az alkalmazás képes lesz szinkronizálni az olyan információkat a telefon és a(z) <xliff:g id="DEVICE_NAME">%1$s</xliff:g> eszköz között, mint például a hívó fél neve."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"Ez az alkalmazás képes lesz szinkronizálni az olyan információkat a telefon és a kiválasztott eszköz között, mint például a hívó fél neve."</string>
<string name="consent_yes" msgid="8344487259618762872">"Engedélyezés"</string>
<string name="consent_no" msgid="2640796915611404382">"Tiltás"</string>
<string name="consent_back" msgid="2560683030046918882">"Vissza"</string>
diff --git a/packages/CompanionDeviceManager/res/values-in/strings.xml b/packages/CompanionDeviceManager/res/values-in/strings.xml
index 5394808cec78..598a0bee14d0 100644
--- a/packages/CompanionDeviceManager/res/values-in/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-in/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Pengelola Perangkat Pendamping"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"Izinkan &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; mengakses &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
<string name="profile_name_watch" msgid="576290739483672360">"smartwatch"</string>
<string name="chooser_title" msgid="2262294130493605839">"Pilih <xliff:g id="PROFILE_NAME">%1$s</xliff:g> untuk dikelola oleh &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"Aplikasi diperlukan untuk mengelola <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> akan diizinkan menyinkronkan informasi, seperti nama pemanggil, berinteraksi dengan notifikasi, dan mengakses izin Telepon, SMS, Kontak, Kalender, Log panggilan, dan Perangkat di sekitar."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"Aplikasi diperlukan untuk mengelola <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> akan diizinkan menyinkronkan informasi, seperti nama pemanggil, dan mengakses izin berikut:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"glasses"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"Aplikasi ini diperlukan untuk mengelola <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> akan diizinkan berinteraksi dengan notifikasi dan mengakses izin Telepon, SMS, Kontak, Mikrofon, dan Perangkat di sekitar."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"Aplikasi diperlukan untuk mengelola <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> akan diizinkan berinteraksi dengan izin ini:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Izinkan &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; untuk mengakses informasi ini dari ponsel Anda"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Layanan lintas perangkat"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> meminta izin atas nama <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> untuk menstreaming aplikasi di antara perangkat Anda"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Layanan lintas perangkat"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> meminta izin atas nama <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> untuk menstreaming konten ke perangkat di sekitar"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"perangkat"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"Aplikasi ini akan dapat menyinkronkan info, seperti nama penelepon, antara ponsel dan <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"Aplikasi ini akan dapat menyinkronkan info, seperti nama penelepon, antara ponsel dan perangkat yang dipilih."</string>
<string name="consent_yes" msgid="8344487259618762872">"Izinkan"</string>
<string name="consent_no" msgid="2640796915611404382">"Jangan izinkan"</string>
<string name="consent_back" msgid="2560683030046918882">"Kembali"</string>
diff --git a/packages/CompanionDeviceManager/res/values-is/strings.xml b/packages/CompanionDeviceManager/res/values-is/strings.xml
index 81c7864dfa86..6f0b0c31ff2c 100644
--- a/packages/CompanionDeviceManager/res/values-is/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-is/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Stjórnun fylgdartækja"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"Veita &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; aðgang að &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
<string name="profile_name_watch" msgid="576290739483672360">"úr"</string>
<string name="chooser_title" msgid="2262294130493605839">"Velja <xliff:g id="PROFILE_NAME">%1$s</xliff:g> sem &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; á að stjórna"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"Forritið er nauðsynlegt til að stjórna <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> fær heimild til að samstilla upplýsingar, t.d. nafn þess sem hringir, og bregðast við tilkynningum og fær aðgang að heimildum fyrir síma, SMS, tengiliði, dagatal, símtalaskrár og nálæg tæki."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"Forritið er nauðsynlegt til að stjórna <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> fær heimild til að samstilla upplýsingar, t.d. nafn þess sem hringir, og fær aðgang að eftirfarandi heimildum:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"gleraugu"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"Þetta forrit er nauðsynlegt til að hafa umsjón með <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> fær heimild til að bregðast við tilkynningum og fær aðgang að heimildum fyrir síma, SMS, tengiliði, hljóðnema og nálæg tæki."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"Forritið er nauðsynlegt til að stjórna <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> fær aðgang að eftirfarandi heimildum:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Veita &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; aðgang að þessum upplýsingum úr símanum þínum"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Þjónustur á milli tækja"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> sendir beiðni um heimild til straumspilunar forrita á milli tækjanna þinna fyrir hönd <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Þjónustur á milli tækja"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> biður um heimild fyrir <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> til að streyma efni í nálægum tækjum"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"tæki"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"Þetta forrit mun geta samstillt upplýsingar, t.d. nafn þess sem hringir, á milli símans og <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"Þetta forrit mun geta samstillt upplýsingar, t.d. nafn þess sem hringir, á milli símans og valins tækis."</string>
<string name="consent_yes" msgid="8344487259618762872">"Leyfa"</string>
<string name="consent_no" msgid="2640796915611404382">"Ekki leyfa"</string>
<string name="consent_back" msgid="2560683030046918882">"Til baka"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ja/strings.xml b/packages/CompanionDeviceManager/res/values-ja/strings.xml
index 6eda60b42a6f..606712b219a4 100644
--- a/packages/CompanionDeviceManager/res/values-ja/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ja/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"コンパニオン デバイス マネージャー"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; に &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; へのアクセスを許可する"</string>
<string name="profile_name_watch" msgid="576290739483672360">"ウォッチ"</string>
<string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; の管理対象となる<xliff:g id="PROFILE_NAME">%1$s</xliff:g>の選択"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"このアプリは <xliff:g id="DEVICE_NAME">%1$s</xliff:g> の管理に必要です。<xliff:g id="APP_NAME">%2$s</xliff:g> は通話相手の名前などの情報を同期したり、デバイスの通知を使用したり、電話、SMS、連絡先、カレンダー、通話履歴、付近のデバイスの権限にアクセスしたりできるようになります。"</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"このアプリは <xliff:g id="DEVICE_NAME">%1$s</xliff:g> の管理に必要です。<xliff:g id="APP_NAME">%2$s</xliff:g> は通話相手の名前などの情報を同期したり、次の権限にアクセスしたりできるようになります。"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"眼鏡"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"このアプリは <xliff:g id="DEVICE_NAME">%1$s</xliff:g> の管理に必要です。<xliff:g id="APP_NAME">%2$s</xliff:g> はデバイスの通知を使用したり、電話、SMS、連絡先、マイク、付近のデバイスの権限にアクセスしたりできるようになります。"</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"このアプリは <xliff:g id="DEVICE_NAME">%1$s</xliff:g> の管理に必要です。<xliff:g id="APP_NAME">%2$s</xliff:g> は次の権限を使用できるようになります。"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"スマートフォンのこの情報へのアクセスを &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; に許可"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"クロスデバイス サービス"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> が <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> に代わってデバイス間でアプリをストリーミングする権限をリクエストしています"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"クロスデバイス サービス"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> が <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> に代わって付近のデバイスにコンテンツをストリーミングする権限をリクエストしています"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"デバイス"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"このアプリは、あなたのスマートフォンと <xliff:g id="DEVICE_NAME">%1$s</xliff:g> との間で、通話相手の名前などの情報を同期できるようになります。"</string>
+ <string name="summary_generic" msgid="4988130802522924650">"このアプリは、あなたのスマートフォンと選択したデバイスとの間で、通話相手の名前などの情報を同期できるようになります。"</string>
<string name="consent_yes" msgid="8344487259618762872">"許可"</string>
<string name="consent_no" msgid="2640796915611404382">"許可しない"</string>
<string name="consent_back" msgid="2560683030046918882">"戻る"</string>
diff --git a/packages/CompanionDeviceManager/res/values-kk/strings.xml b/packages/CompanionDeviceManager/res/values-kk/strings.xml
index 622834b90095..c6016cbd93a6 100644
--- a/packages/CompanionDeviceManager/res/values-kk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-kk/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Companion Device Manager"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; қолданбасына &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; құрылғысын пайдалануға рұқсат беру"</string>
<string name="profile_name_watch" msgid="576290739483672360">"сағат"</string>
<string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; арқылы басқарылатын <xliff:g id="PROFILE_NAME">%1$s</xliff:g> құрылғысын таңдаңыз"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"Қолданба <xliff:g id="DEVICE_NAME">%1$s</xliff:g> құрылғысын басқару үшін қажет. <xliff:g id="APP_NAME">%2$s</xliff:g> қолданбасына қоңырау шалушының аты сияқты деректі синхрондау, хабарландыруларды оқу, телефон, SMS, контактілер, күнтізбе, қоңырау журналдары қолданбаларын және маңайдағы құрылғыларды пайдалану рұқсаттары беріледі."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"Қолданба <xliff:g id="DEVICE_NAME">%1$s</xliff:g> құрылғысын басқару үшін қажет. <xliff:g id="APP_NAME">%2$s</xliff:g> қолданбасына деректі (мысалы, қоңырау шалушының аты) синхрондауға және мына рұқсаттарды пайдалануға рұқсат беріледі:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"көзілдірік"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"Бұл қолданба <xliff:g id="DEVICE_NAME">%1$s</xliff:g> құрылғысын басқару үшін қажет. <xliff:g id="APP_NAME">%2$s</xliff:g> қолданбасына хабарландыруларды оқуға, телефонды, хабарларды, контактілерді, микрофон мен маңайдағы құрылғыларды пайдалануға рұқсат беріледі."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"Қолданба <xliff:g id="DEVICE_NAME">%1$s</xliff:g> құрылғысын басқару үшін қажет. <xliff:g id="APP_NAME">%2$s</xliff:g> қолданбасына осы рұқсаттар беріледі:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; қолданбасына телефоныңыздағы осы ақпаратты пайдалануға рұқсат беріңіз."</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Аралық құрылғы қызметтері"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасы <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> атынан құрылғылар арасында қолданбалар трансляциялау үшін рұқсат сұрайды."</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Аралық құрылғы қызметтері"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасы маңайдағы құрылғыларға <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> атынан контент трансляциялау үшін рұқсат сұрайды."</string>
<string name="profile_name_generic" msgid="6851028682723034988">"құрылғы"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"Бұл қолданба телефон мен <xliff:g id="DEVICE_NAME">%1$s</xliff:g> құрылғысы арасында деректі (мысалы, қоңырау шалушының атын) синхрондайды."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"Бұл қолданба телефон мен таңдалған құрылғы арасында деректі (мысалы, қоңырау шалушының атын) синхрондайды."</string>
<string name="consent_yes" msgid="8344487259618762872">"Рұқсат беру"</string>
<string name="consent_no" msgid="2640796915611404382">"Рұқсат бермеу"</string>
<string name="consent_back" msgid="2560683030046918882">"Артқа"</string>
diff --git a/packages/CompanionDeviceManager/res/values-km/strings.xml b/packages/CompanionDeviceManager/res/values-km/strings.xml
index 455f88236ada..9619d703e068 100644
--- a/packages/CompanionDeviceManager/res/values-km/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-km/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"កម្មវិធី​គ្រប់​គ្រង​ឧបករណ៍ដៃគូ"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"អនុញ្ញាតឱ្យ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ចូលប្រើ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
<string name="profile_name_watch" msgid="576290739483672360">"នាឡិកា"</string>
<string name="chooser_title" msgid="2262294130493605839">"ជ្រើសរើស <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ដើម្បីឱ្យស្ថិតក្រោម​ការគ្រប់គ្រងរបស់ &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"ត្រូវការកម្មវិធីនេះ ដើម្បីគ្រប់គ្រង <xliff:g id="DEVICE_NAME">%1$s</xliff:g> របស់អ្នក។ <xliff:g id="APP_NAME">%2$s</xliff:g> នឹងត្រូវបានអនុញ្ញាតឱ្យ​ធ្វើសមកាលកម្មព័ត៌មានដូចជា ឈ្មោះមនុស្សដែលហៅទូរសព្ទ ធ្វើអន្តរកម្មជាមួយ​ការជូនដំណឹងរបស់អ្នក និងចូលប្រើការអនុញ្ញាតទូរសព្ទ, SMS, ទំនាក់ទំនង, ប្រតិទិន, កំណត់ហេតុហៅទូរសព្ទ និងឧបករណ៍នៅជិតរបស់អ្នក។"</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"ត្រូវការកម្មវិធីនេះ ដើម្បីគ្រប់គ្រង <xliff:g id="DEVICE_NAME">%1$s</xliff:g> របស់អ្នក។ <xliff:g id="APP_NAME">%2$s</xliff:g> នឹងត្រូវបានអនុញ្ញាតឱ្យ​ធ្វើសមកាលកម្មព័ត៌មានដូចជា ឈ្មោះមនុស្សដែលហៅទូរសព្ទ និងចូលប្រើការអនុញ្ញាតទាំងនេះ៖"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"វ៉ែនតា"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"ត្រូវការកម្មវិធីនេះ ដើម្បីគ្រប់គ្រង <xliff:g id="DEVICE_NAME">%1$s</xliff:g>។ <xliff:g id="APP_NAME">%2$s</xliff:g> នឹងត្រូវបានអនុញ្ញាតឱ្យ​ធ្វើអន្តរកម្មជាមួយ​ការជូនដំណឹងរបស់អ្នក និងចូលប្រើការអនុញ្ញាត​របស់ទូរសព្ទ, SMS, ទំនាក់ទំនង, មីក្រូហ្វូន និងឧបករណ៍នៅជិត​របស់អ្នក។"</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"ត្រូវការកម្មវិធីនេះ ដើម្បីគ្រប់គ្រង <xliff:g id="DEVICE_NAME">%1$s</xliff:g>។ <xliff:g id="APP_NAME">%2$s</xliff:g> នឹងត្រូវបានអនុញ្ញាតឱ្យធ្វើអន្តរកម្មជាមួយការអនុញ្ញាតទាំងនេះ៖"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"អនុញ្ញាតឱ្យ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ចូលប្រើព័ត៌មាននេះពីទូរសព្ទរបស់អ្នក"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"សេវាកម្មឆ្លងកាត់ឧបករណ៍"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> កំពុងស្នើសុំការអនុញ្ញាតជំនួសឱ្យ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> របស់អ្នក ដើម្បីបញ្ចាំងកម្មវិធីរវាងឧបករណ៍របស់អ្នក"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"សេវាកម្មឆ្លងកាត់ឧបករណ៍"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> កំពុងស្នើសុំការអនុញ្ញាតជំនួសឱ្យ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> របស់អ្នក ដើម្បីផ្សាយខ្លឹមសារទៅឧបករណ៍នៅជិត"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ឧបករណ៍"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"កម្មវិធីនឹងអាច​ធ្វើសមកាលកម្មព័ត៌មាន​ដូចជា ឈ្មោះមនុស្សដែលហៅទូរសព្ទ​រវាងទូរសព្ទ និង <xliff:g id="DEVICE_NAME">%1$s</xliff:g> របស់អ្នក។"</string>
+ <string name="summary_generic" msgid="4988130802522924650">"កម្មវិធីនេះនឹងអាច​ធ្វើសមកាលកម្មព័ត៌មាន​ដូចជា ឈ្មោះមនុស្សដែលហៅទូរសព្ទ​រវាងឧបករណ៍ដែលបានជ្រើសរើស និងទូរសព្ទរបស់អ្នក។"</string>
<string name="consent_yes" msgid="8344487259618762872">"អនុញ្ញាត"</string>
<string name="consent_no" msgid="2640796915611404382">"មិនអនុញ្ញាត"</string>
<string name="consent_back" msgid="2560683030046918882">"ថយក្រោយ"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ko/strings.xml b/packages/CompanionDeviceManager/res/values-ko/strings.xml
index 38740f558ba5..91e96374848d 100644
--- a/packages/CompanionDeviceManager/res/values-ko/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ko/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"부속 기기 관리자"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;에서 &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; 기기에 액세스하도록 허용"</string>
<string name="profile_name_watch" msgid="576290739483672360">"시계"</string>
<string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;에서 관리할 <xliff:g id="PROFILE_NAME">%1$s</xliff:g>을(를) 선택"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"이 앱은 <xliff:g id="DEVICE_NAME">%1$s</xliff:g> 기기를 관리하는 데 필요합니다. <xliff:g id="APP_NAME">%2$s</xliff:g>에서 전화를 건 사람 이름과 같은 정보를 동기화하며 알림과 상호작용하고 내 전화, SMS, 연락처, Calendar, 통화 기록, 근처 기기에 액세스할 수 있게 됩니다."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"이 앱은 <xliff:g id="DEVICE_NAME">%1$s</xliff:g> 기기를 관리하는 데 필요합니다. <xliff:g id="APP_NAME">%2$s</xliff:g>에서 전화를 건 사람 이름과 같은 정보를 동기화하며 이러한 권한에 액세스할 수 있게 됩니다."</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"안경"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"이 앱은 <xliff:g id="DEVICE_NAME">%1$s</xliff:g> 기기를 관리하는 데 필요합니다. <xliff:g id="APP_NAME">%2$s</xliff:g>에서 알림과 상호작용하고 내 전화, SMS, 연락처, 마이크, 근처 기기에 대한 권한을 갖게 됩니다."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"이 앱은 <xliff:g id="DEVICE_NAME">%1$s</xliff:g> 기기를 관리하는 데 필요합니다. <xliff:g id="APP_NAME">%2$s</xliff:g>에서 다음 권한과 상호작용할 수 있습니다."</string>
<string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;이 휴대전화의 이 정보에 액세스하도록 허용합니다."</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"교차 기기 서비스"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> 대신 기기 간에 앱을 스트리밍할 수 있는 권한을 요청하고 있습니다."</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"교차 기기 서비스"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> 대신 근처 기기로 콘텐츠를 스트리밍할 수 있는 권한을 요청하고 있습니다."</string>
<string name="profile_name_generic" msgid="6851028682723034988">"기기"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"이 앱이 전화를 건 사람 이름과 같은 정보를 휴대전화와 <xliff:g id="DEVICE_NAME">%1$s</xliff:g> 간에 동기화할 수 있습니다."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"이 앱이 전화를 건 사람 이름과 같은 정보를 휴대전화와 선택한 기기 간에 동기화할 수 있습니다."</string>
<string name="consent_yes" msgid="8344487259618762872">"허용"</string>
<string name="consent_no" msgid="2640796915611404382">"허용 안함"</string>
<string name="consent_back" msgid="2560683030046918882">"뒤로"</string>
diff --git a/packages/CompanionDeviceManager/res/values-lv/strings.xml b/packages/CompanionDeviceManager/res/values-lv/strings.xml
index 581c84ac7d85..7441c0dd6a51 100644
--- a/packages/CompanionDeviceManager/res/values-lv/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-lv/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Palīgierīču pārzinis"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"Atļauja lietotnei &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; piekļūt ierīcei &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
<string name="profile_name_watch" msgid="576290739483672360">"pulkstenis"</string>
<string name="chooser_title" msgid="2262294130493605839">"Profila (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>) izvēle, ko pārvaldīt lietotnē &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"Šī lietotne ir nepieciešama jūsu ierīces (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) pārvaldībai. <xliff:g id="APP_NAME">%2$s</xliff:g> drīkstēs sinhronizēt informāciju, piemēram, zvanītāja vārdu, mijiedarboties ar jūsu paziņojumiem un piekļūt atļaujām Tālrunis, Īsziņas, Kontaktpersonas, Kalendārs, Zvanu žurnāli un Tuvumā esošas ierīces."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"Šī lietotne ir nepieciešama jūsu ierīces (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) pārvaldībai. <xliff:g id="APP_NAME">%2$s</xliff:g> drīkstēs sinhronizēt informāciju, piemēram, zvanītāja vārdu, un piekļūt šīm atļaujām:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"brilles"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"Šī lietotne ir nepieciešama šādas ierīces pārvaldībai: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> drīkstēs mijiedarboties ar jūsu paziņojumiem un piekļūt atļaujām Tālrunis, Īsziņas, Kontaktpersonas, Mikrofons un Tuvumā esošas ierīces."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"Lietotne ir nepieciešama šādas ierīces pārvaldībai: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Lietotnei <xliff:g id="APP_NAME">%2$s</xliff:g> tiks atļauts mijiedarboties ar šīm atļaujām:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Atļaut lietotnei &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; piekļūt šai informācijai no jūsu tālruņa"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Vairāku ierīču pakalpojumi"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> pieprasa atļauju straumēt lietotnes starp jūsu ierīcēm šīs ierīces vārdā: <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Vairāku ierīču pakalpojumi"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> pieprasa atļauju straumēt saturu tuvumā esošās ierīcēs šīs ierīces vārdā: <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ierīce"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"Šī lietotne varēs sinhronizēt informāciju, piemēram, zvanītāja vārdu, starp jūsu tālruni un šo ierīci: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"Šī lietotne varēs sinhronizēt informāciju, piemēram, zvanītāja vārdu, starp jūsu tālruni un izvēlēto ierīci."</string>
<string name="consent_yes" msgid="8344487259618762872">"Atļaut"</string>
<string name="consent_no" msgid="2640796915611404382">"Neatļaut"</string>
<string name="consent_back" msgid="2560683030046918882">"Atpakaļ"</string>
diff --git a/packages/CompanionDeviceManager/res/values-mk/strings.xml b/packages/CompanionDeviceManager/res/values-mk/strings.xml
index 2768d56aac9f..455b559eeae8 100644
--- a/packages/CompanionDeviceManager/res/values-mk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mk/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Companion Device Manager"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"Дозволете &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; да пристапува до &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
<string name="profile_name_watch" msgid="576290739483672360">"часовник"</string>
<string name="chooser_title" msgid="2262294130493605839">"Изберете <xliff:g id="PROFILE_NAME">%1$s</xliff:g> со којшто ќе управува &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"Апликацијата е потребна за управување со вашиот <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ќе може да ги синхронизира податоците како што се имињата на јавувачите, да остварува интеракција со известувањата и да пристапува до дозволите за „Телефон“, SMS, „Контакти“, „Календар“, „Евиденција на повици“ и „Уреди во близина“."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"Апликацијата е потребна за управување со вашиот <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ќе има дозвола да ги синхронизира податоците како што се имињата на јавувачите и да пристапува до следниве дозволи:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"очила"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"Апликацијава е потребна за управување со <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ќе може да остварува интеракција со известувањата и да пристапува до дозволите за „Телефон“, SMS, „Контакти“, „Микрофон“ и „Уреди во близина“."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"Апликацијата е потребна за управување со <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ќе може да остварува интеракција со следниве дозволи:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Овозможете &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; да пристапува до овие податоци на телефонот"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Повеќенаменски услуги"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> бара дозвола во име на вашиот <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> за да стримува апликации помеѓу вашите уреди"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Услуги на повеќе уреди"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> бара дозвола во име на вашиот <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> за да стримува содржини на уредите во близина"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"уред"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"Оваа апликација ќе може да ги синхронизира податоците како што се имињата на јавувачите помеѓу вашиот телефон и <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"Оваа апликација ќе може да ги синхронизира податоците како што се имињата на јавувачите помеѓу вашиот телефон и избраниот уред."</string>
<string name="consent_yes" msgid="8344487259618762872">"Дозволи"</string>
<string name="consent_no" msgid="2640796915611404382">"Не дозволувај"</string>
<string name="consent_back" msgid="2560683030046918882">"Назад"</string>
diff --git a/packages/CompanionDeviceManager/res/values-mn/strings.xml b/packages/CompanionDeviceManager/res/values-mn/strings.xml
index 9ce4124c36db..02266f22a71d 100644
--- a/packages/CompanionDeviceManager/res/values-mn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mn/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Companion Device Manager"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;-д &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;-д хандахыг зөвшөөрнө үү"</string>
<string name="profile_name_watch" msgid="576290739483672360">"цаг"</string>
<string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;-н удирдах<xliff:g id="PROFILE_NAME">%1$s</xliff:g>-г сонгоно уу"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"Энэ апп таны <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-г удирдахад шаардлагатай. <xliff:g id="APP_NAME">%2$s</xliff:g>-д залгаж буй хүний нэр зэрэг мэдээллийг синк хийх, таны мэдэгдэлтэй харилцан үйлдэл хийх, Утас, SMS, Харилцагчид, Календарь, Дуудлагын жагсаалт болон Ойролцоох төхөөрөмжүүдийн зөвшөөрөлд хандахыг зөвшөөрнө."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"Энэ апп таны <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-г удирдахад шаардлагатай. <xliff:g id="APP_NAME">%2$s</xliff:g>-д залгаж буй хүний нэр зэрэг мэдээллийг синк хийх болон эдгээр зөвшөөрөлд хандахыг зөвшөөрнө:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"нүдний шил"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"Энэ апп <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-г удирдахад шаардлагатай. <xliff:g id="APP_NAME">%2$s</xliff:g>-д таны мэдэгдэлтэй харилцан үйлдэл хийх, Утас, SMS, Харилцагчид, Микрофон болон Ойролцоох төхөөрөмжүүдийн зөвшөөрөлд хандахыг зөвшөөрнө."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"Энэ апп <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-г удирдахад шаардлагатай. <xliff:g id="APP_NAME">%2$s</xliff:g>-д эдгээр зөвшөөрөлтэй харилцан үйлдэл хийхийг зөвшөөрнө:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;-д таны утаснаас энэ мэдээлэлд хандахыг зөвшөөрнө үү"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Төхөөрөмж хоорондын үйлчилгээ"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"Таны төхөөрөмжүүд хооронд апп дамжуулахын тулд <xliff:g id="APP_NAME">%1$s</xliff:g> таны <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-н өмнөөс зөвшөөрөл хүсэж байна"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Төхөөрөмж хоорондын үйлчилгээ"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> таны <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-н өмнөөс ойролцоох төхөөрөмжүүд рүү контент дамжуулах зөвшөөрөл хүсэж байна"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"төхөөрөмж"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"Энэ апп залгаж буй хүний нэр зэрэг мэдээллийг таны утас болон <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-н хооронд синк хийх боломжтой болно."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"Энэ апп залгаж буй хүний нэр зэрэг мэдээллийг таны утас болон сонгосон төхөөрөмжийн хооронд синк хийх боломжтой болно."</string>
<string name="consent_yes" msgid="8344487259618762872">"Зөвшөөрөх"</string>
<string name="consent_no" msgid="2640796915611404382">"Бүү зөвшөөр"</string>
<string name="consent_back" msgid="2560683030046918882">"Буцах"</string>
diff --git a/packages/CompanionDeviceManager/res/values-mr/strings.xml b/packages/CompanionDeviceManager/res/values-mr/strings.xml
index 2c4d6f3a05d4..8a22595d65e0 100644
--- a/packages/CompanionDeviceManager/res/values-mr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mr/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"सहयोगी डिव्हाइस व्यवस्थापक"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ला &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; अ‍ॅक्सेस करण्याची अनुमती द्या"</string>
<string name="profile_name_watch" msgid="576290739483672360">"वॉच"</string>
<string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; द्वारे व्यवस्थापित करण्यासाठी <xliff:g id="PROFILE_NAME">%1$s</xliff:g> निवडा"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"तुमचे <xliff:g id="DEVICE_NAME">%1$s</xliff:g> व्यवस्थापित करण्यासाठी हे ॲप आवश्यक आहे. <xliff:g id="APP_NAME">%2$s</xliff:g> ला कॉल करत असलेल्या एखाद्या व्यक्तीचे नाव यासारखी माहिती सिंक करण्याची, तुमच्या सूचनांसोबत संवाद साधण्याची आणि तुमचा फोन, एसएमएस, संपर्क, कॅलेंडर, कॉल लॉग व जवळपासच्या डिव्हाइसच्या परवानग्या अ‍ॅक्सेस करण्याची अनुमती मिळेल."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"तुमचे <xliff:g id="DEVICE_NAME">%1$s</xliff:g> व्यवस्थापित करण्यासाठी हे ॲप आवश्यक आहे. <xliff:g id="APP_NAME">%2$s</xliff:g> ला कॉल करत असलेल्या एखाद्या व्यक्तीचे नाव यासारखी माहिती सिंक करण्याची आणि पुढील परवानग्या अ‍ॅक्सेस करण्याची अनुमती मिळेल:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"Glasses"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> व्यवस्थापित करण्यासाठी हे ॲप आवश्यक आहे. <xliff:g id="APP_NAME">%2$s</xliff:g> ला तुमच्या सूचनांसोबत संवाद साधण्याची आणि तुमचा फोन, एसएमएस, संपर्क, मायक्रोफोन व जवळपासच्या डिव्हाइसच्या परवानग्या अ‍ॅक्सेस करण्याची अनुमती मिळेल."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> व्यवस्थापित करण्यासाठी ॲप आवश्यक आहे. <xliff:g id="APP_NAME">%2$s</xliff:g> ला पुढील परवानग्यांशी संवाद साधण्याची अनुमती मिळेल:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ला ही माहिती तुमच्या फोनवरून अ‍ॅक्सेस करण्यासाठी अनुमती द्या"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"क्रॉस-डिव्हाइस सेवा"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"तुमच्या डिव्हाइसदरम्यान ॲप्स स्ट्रीम करण्यासाठी <xliff:g id="APP_NAME">%1$s</xliff:g> हे तुमच्या <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> च्या वतीने परवानगीची विनंती करत आहे"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"क्रॉस-डिव्हाइस सेवा"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> हे जवळपासच्या डिव्हाइसवर आशय स्ट्रीम करण्यासाठी तुमच्या <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> च्या वतीने परवानगीची विनंती करत आहे"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"डिव्हाइस"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"हे ॲप तुमचा फोन आणि <xliff:g id="DEVICE_NAME">%1$s</xliff:g> दरम्यान कॉल करत असलेल्‍या एखाद्या व्यक्तीचे नाव यासारखी माहिती सिंक करू शकेल."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"हे ॲप तुमचा फोन आणि निवडलेल्या डिव्‍हाइसदरम्यान कॉल करत असलेल्‍या एखाद्या व्यक्तीचे नाव यासारखी माहिती सिंक करू शकेल."</string>
<string name="consent_yes" msgid="8344487259618762872">"अनुमती द्या"</string>
<string name="consent_no" msgid="2640796915611404382">"अनुमती देऊ नका"</string>
<string name="consent_back" msgid="2560683030046918882">"मागे जा"</string>
diff --git a/packages/CompanionDeviceManager/res/values-nb/strings.xml b/packages/CompanionDeviceManager/res/values-nb/strings.xml
index 883359169fe6..ee7091f4fea0 100644
--- a/packages/CompanionDeviceManager/res/values-nb/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-nb/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Companion Device Manager"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"Tillat at &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; bruker &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
<string name="profile_name_watch" msgid="576290739483672360">"klokke"</string>
<string name="chooser_title" msgid="2262294130493605839">"Velg <xliff:g id="PROFILE_NAME">%1$s</xliff:g> som skal administreres av &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"Appen kreves for å administrere <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tillatelse til å synkronisere informasjon som navnet til noen som ringer, og samhandle med varslene dine, og får tilgang til tillatelsene for telefon, SMS, kontakter, kalender, samtalelogger og enheter i nærheten."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"Appen kreves for å administrere <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tillatelse til å synkronisere informasjon som navnet til noen som ringer, og kan bruke disse tillatelsene:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"briller"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"Denne appen kreves for å administrere <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tillatelse til å samhandle med varslene dine og har tilgang til tillatelsene for telefon, SMS, kontakter, mikrofon og enheter i nærheten."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"Appen kreves for å administrere <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tillatelse til å samhandle med disse tillatelsene:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Gi &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; tilgang til denne informasjonen fra telefonen din"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Tjenester på flere enheter"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> ber om tillatelse til å strømme apper mellom enhetene dine, på vegne av <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Tjenester på flere enheter"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> ber om tillatelse på vegne av <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> til å strømme innhold til enheter i nærheten"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"enhet"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"Denne appen kan synkronisere informasjon som navnet til noen som ringer, mellom telefonen og <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"Denne appen kan synkronisere informasjon som navnet til noen som ringer, mellom telefonen og den valgte enheten."</string>
<string name="consent_yes" msgid="8344487259618762872">"Tillat"</string>
<string name="consent_no" msgid="2640796915611404382">"Ikke tillat"</string>
<string name="consent_back" msgid="2560683030046918882">"Tilbake"</string>
diff --git a/packages/CompanionDeviceManager/res/values-or/strings.xml b/packages/CompanionDeviceManager/res/values-or/strings.xml
index b9794c47ac4a..cd742f1edba1 100644
--- a/packages/CompanionDeviceManager/res/values-or/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-or/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"ସହଯୋଗୀ ଡିଭାଇସ୍ ପରିଚାଳକ"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;କୁ ଆକ୍ସେସ କରିବା ପାଇଁ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;କୁ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
<string name="profile_name_watch" msgid="576290739483672360">"ୱାଚ୍"</string>
<string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; ଦ୍ୱାରା ପରିଚାଳିତ ହେବା ପାଇଁ ଏକ <xliff:g id="PROFILE_NAME">%1$s</xliff:g>କୁ ବାଛନ୍ତୁ"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"ଆପଣଙ୍କ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>କୁ ପରିଚାଳନା କରିବା ପାଇଁ ଆପ ଆବଶ୍ୟକ। କଲ କରୁଥିବା ଯେ କୌଣସି ବ୍ୟକ୍ତିଙ୍କ ନାମ ପରି ସୂଚନା ସିଙ୍କ କରିବା, ଆପଣଙ୍କ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ସହ ଇଣ୍ଟରାକ୍ଟ କରିବା ଏବଂ ଆପଣଙ୍କର ଫୋନ, SMS, କଣ୍ଟାକ୍ଟ, କେଲେଣ୍ଡର, କଲ ଲଗ ଓ ଆଖପାଖର ଡିଭାଇସ ଅନୁମତିଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%2$s</xliff:g>କୁ ଅନୁମତି ଦିଆଯିବ।"</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"ଆପଣଙ୍କ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>କୁ ପରିଚାଳନା କରିବା ପାଇଁ ଆପ ଆବଶ୍ୟକ। କଲ କରୁଥିବା ଯେ କୌଣସି ବ୍ୟକ୍ତିଙ୍କ ନାମ ପରି ସୂଚନା ସିଙ୍କ କରିବା ଏବଂ ଏହି ଅନୁମତିଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%2$s</xliff:g>କୁ ଅନୁମତି ଦିଆଯିବ:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"ଚଷମା"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>କୁ ପରିଚାଳନା କରିବା ପାଇଁ ଏହି ଆପ ଆବଶ୍ୟକ। ଆପଣଙ୍କ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ସହ ଇଣ୍ଟରାକ୍ଟ କରିବା ଏବଂ ଆପଣଙ୍କର ଫୋନ, SMS, କଣ୍ଟାକ୍ଟ, ମାଇକ୍ରୋଫୋନ ଓ ଆଖପାଖର ଡିଭାଇସ ଅନୁମତିଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%2$s</xliff:g>କୁ ଅନୁମତି ଦିଆଯିବ।"</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>କୁ ପରିଚାଳନା କରିବା ପାଇଁ ଆପ ଆବଶ୍ୟକ। ଏହି ଅନୁମତିଗୁଡ଼ିକ ସହ ଇଣ୍ଟରାକ୍ଟ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%2$s</xliff:g>କୁ ଅନୁମତି ଦିଆଯିବ:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"ଆପଣଙ୍କ ଫୋନରୁ ଏହି ସୂଚନାକୁ ଆକ୍ସେସ କରିବା ପାଇଁ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;କୁ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"କ୍ରସ-ଡିଭାଇସ ସେବାଗୁଡ଼ିକ"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"ଆପଣଙ୍କ ଡିଭାଇସଗୁଡ଼ିକ ମଧ୍ୟରେ ଆପ୍ସକୁ ଷ୍ଟ୍ରିମ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%1$s</xliff:g> ଆପଣଙ୍କର <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ତରଫରୁ ଅନୁମତି ପାଇଁ ଅନୁରୋଧ କରୁଛି"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"କ୍ରସ-ଡିଭାଇସ ସେବାଗୁଡ଼ିକ"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"ଆଖପାଖର ଡିଭାଇସଗୁଡ଼ିକରେ ବିଷୟବସ୍ତୁକୁ ଷ୍ଟ୍ରିମ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%1$s</xliff:g> ଆପଣଙ୍କର <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ତରଫରୁ ଅନୁମତି ପାଇଁ ଅନୁରୋଧ କରୁଛି"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ଡିଭାଇସ୍"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"ଆପଣଙ୍କ ଫୋନ ଏବଂ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ମଧ୍ୟରେ, କଲ କରୁଥିବା ଯେ କୌଣସି ବ୍ୟକ୍ତିଙ୍କ ନାମ ପରି ସୂଚନା ସିଙ୍କ କରିବାକୁ ଏହି ଆପ ସକ୍ଷମ ହେବ।"</string>
+ <string name="summary_generic" msgid="4988130802522924650">"ଆପଣଙ୍କ ଫୋନ ଏବଂ ବଛାଯାଇଥିବା ଡିଭାଇସ ମଧ୍ୟରେ, କଲ କରୁଥିବା ଯେ କୌଣସି ବ୍ୟକ୍ତିଙ୍କ ନାମ ପରି ସୂଚନା ସିଙ୍କ କରିବାକୁ ଏହି ଆପ ସକ୍ଷମ ହେବ।"</string>
<string name="consent_yes" msgid="8344487259618762872">"ଅନୁମତି ଦିଅନ୍ତୁ"</string>
<string name="consent_no" msgid="2640796915611404382">"ଅନୁମତି ଦିଅନ୍ତୁ ନାହିଁ"</string>
<string name="consent_back" msgid="2560683030046918882">"ପଛକୁ ଫେରନ୍ତୁ"</string>
diff --git a/packages/CompanionDeviceManager/res/values-pa/strings.xml b/packages/CompanionDeviceManager/res/values-pa/strings.xml
index f933c9a2dc80..1e03ee0e6be5 100644
--- a/packages/CompanionDeviceManager/res/values-pa/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pa/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"ਸੰਬੰਧੀ ਡੀਵਾਈਸ ਪ੍ਰਬੰਧਕ"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ਨੂੰ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿਓ"</string>
<string name="profile_name_watch" msgid="576290739483672360">"ਸਮਾਰਟ-ਵਾਚ"</string>
<string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; ਵੱਲੋਂ ਪ੍ਰਬੰਧਿਤ ਕੀਤੇ ਜਾਣ ਲਈ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ਚੁਣੋ"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"ਇਹ ਐਪ ਤੁਹਾਡੇ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਨ ਲਈ ਲੋੜੀਂਦੀ ਹੈ। <xliff:g id="APP_NAME">%2$s</xliff:g> ਨੂੰ ਕਾਲਰ ਦੇ ਨਾਮ ਵਰਗੀ ਜਾਣਕਾਰੀ ਨੂੰ ਸਿੰਕ ਕਰਨ, ਤੁਹਾਡੀਆਂ ਸੂਚਨਾਵਾਂ ਨਾਲ ਅੰਤਰਕਿਰਿਆ ਕਰਨ ਅਤੇ ਤੁਹਾਡੇ ਫ਼ੋਨ, SMS, ਸੰਪਰਕਾਂ, ਕੈਲੰਡਰ, ਕਾਲ ਲੌਗਾਂ ਅਤੇ ਨਜ਼ਦੀਕੀ ਡੀਵਾਈਸਾਂ ਸੰਬੰਧੀ ਇਜਾਜ਼ਤਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਹੋਵੇਗੀ।"</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"ਇਹ ਐਪ ਤੁਹਾਡੇ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਨ ਲਈ ਲੋੜੀਂਦੀ ਹੈ। <xliff:g id="APP_NAME">%2$s</xliff:g> ਨੂੰ ਕਾਲਰ ਦੇ ਨਾਮ ਵਰਗੀ ਜਾਣਕਾਰੀ ਨੂੰ ਸਿੰਕ ਕਰਨ ਅਤੇ ਇਨ੍ਹਾਂ ਇਜਾਜ਼ਤਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਹੋਵੇਗੀ:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"ਐਨਕਾਂ"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"ਇਹ ਐਪ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਨ ਲਈ ਲੋੜੀਂਦੀ ਹੈ। <xliff:g id="APP_NAME">%2$s</xliff:g> ਨੂੰ ਤੁਹਾਡੀਆਂ ਸੂਚਨਾਵਾਂ ਨਾਲ ਅੰਤਰਕਿਰਿਆ ਕਰਨ ਅਤੇ ਤੁਹਾਡੇ ਫ਼ੋਨ, SMS, ਸੰਪਰਕਾਂ, ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਅਤੇ ਨਜ਼ਦੀਕੀ ਡੀਵਾਈਸਾਂ ਸੰਬੰਧੀ ਇਜਾਜ਼ਤਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਹੋਵੇਗੀ।"</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"ਇਹ ਐਪ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਨ ਲਈ ਲੋੜੀਂਦੀ ਹੈ। <xliff:g id="APP_NAME">%2$s</xliff:g> ਨੂੰ ਇਨ੍ਹਾਂ ਇਜਾਜ਼ਤਾਂ ਨਾਲ ਅੰਤਰਕਿਰਿਆ ਕਰਨ ਦੀ ਆਗਿਆ ਹੋਵੇਗੀ:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਨ ਤੋਂ ਇਸ ਜਾਣਕਾਰੀ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿਓ"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"ਕ੍ਰਾਸ-ਡੀਵਾਈਸ ਸੇਵਾਵਾਂ"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਤੁਹਾਡੇ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ਦੀ ਤਰਫ਼ੋਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸਾਂ ਵਿਚਕਾਰ ਐਪਾਂ ਨੂੰ ਸਟ੍ਰੀਮ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਮੰਗ ਰਹੀ ਹੈ"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"ਕ੍ਰਾਸ-ਡੀਵਾਈਸ ਸੇਵਾਵਾਂ"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਤੁਹਾਡੇ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ਦੀ ਤਰਫ਼ੋਂ ਨਜ਼ਦੀਕੀ ਡੀਵਾਈਸਾਂ ਲਈ ਸਮੱਗਰੀ ਨੂੰ ਸਟ੍ਰੀਮ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਮੰਗ ਰਹੀ ਹੈ"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ਡੀਵਾਈਸ"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"ਇਹ ਐਪ ਤੁਹਾਡੇ ਫ਼ੋਨ ਅਤੇ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਵਿਚਕਾਰ ਕਾਲਰ ਦੇ ਨਾਮ ਵਰਗੀ ਜਾਣਕਾਰੀ ਨੂੰ ਸਿੰਕ ਕਰ ਸਕੇਗੀ।"</string>
+ <string name="summary_generic" msgid="4988130802522924650">"ਇਹ ਐਪ ਤੁਹਾਡੇ ਫ਼ੋਨ ਅਤੇ ਚੁਣੇ ਗਏ ਡੀਵਾਈਸ ਵਿਚਕਾਰ ਕਾਲਰ ਦੇ ਨਾਮ ਵਰਗੀ ਜਾਣਕਾਰੀ ਨੂੰ ਸਿੰਕ ਕਰ ਸਕੇਗੀ।"</string>
<string name="consent_yes" msgid="8344487259618762872">"ਆਗਿਆ ਦਿਓ"</string>
<string name="consent_no" msgid="2640796915611404382">"ਆਗਿਆ ਨਾ ਦਿਓ"</string>
<string name="consent_back" msgid="2560683030046918882">"ਪਿੱਛੇ"</string>
diff --git a/packages/CompanionDeviceManager/res/values-pl/strings.xml b/packages/CompanionDeviceManager/res/values-pl/strings.xml
index 6b7159219ff1..c5915944ce1a 100644
--- a/packages/CompanionDeviceManager/res/values-pl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pl/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Menedżer urządzeń towarzyszących"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"Zezwól na dostęp aplikacji &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; do urządzenia &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
<string name="profile_name_watch" msgid="576290739483672360">"zegarek"</string>
<string name="chooser_title" msgid="2262294130493605839">"Wybierz profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, którym ma zarządzać aplikacja &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"Ta aplikacja jest niezbędna do zarządzania urządzeniem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacja <xliff:g id="APP_NAME">%2$s</xliff:g> będzie mogła synchronizować informacje takie jak nazwa osoby dzwoniącej, korzystać z powiadomień oraz uprawnień dotyczących Telefonu, SMS-ów, Kontaktów, Kalendarza, rejestrów połączeń i Urządzeń w pobliżu."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"Ta aplikacja jest niezbędna do zarządzania urządzeniem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacja <xliff:g id="APP_NAME">%2$s</xliff:g> będzie mogła synchronizować informacje takie jak nazwa osoby dzwoniącej i korzystać z tych uprawnień:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"Okulary"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"Ta aplikacja jest niezbędna do zarządzania urządzeniem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacja <xliff:g id="APP_NAME">%2$s</xliff:g> będzie mogła wchodzić w interakcję z powiadomieniami i korzystać z uprawnień dotyczących telefonu, SMS-ów, kontaktów, mikrofonu oraz urządzeń w pobliżu."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"Ta aplikacja jest niezbędna do zarządzania urządzeniem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacja <xliff:g id="APP_NAME">%2$s</xliff:g> będzie mogła korzystać z tych uprawnień:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Zezwól urządzeniu &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; na dostęp do tych informacji na Twoim telefonie"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Usługi na innym urządzeniu"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> prosi w imieniu urządzenia <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> o uprawnienia dotyczące strumieniowego odtwarzania treści z aplikacji na innym urządzeniu"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Usługi na innym urządzeniu"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> prosi w imieniu urządzenia <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> o uprawnienia dotyczące strumieniowego odtwarzania treści na urządzeniach w pobliżu"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"urządzenie"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"Ta aplikacja może synchronizować informacje takie jak nazwa osoby dzwoniącej między Twoim telefonem i urządzeniem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"Ta aplikacja może synchronizować informacje takie jak nazwa osoby dzwoniącej między Twoim telefonem i wybranym urządzeniem."</string>
<string name="consent_yes" msgid="8344487259618762872">"Zezwól"</string>
<string name="consent_no" msgid="2640796915611404382">"Nie zezwalaj"</string>
<string name="consent_back" msgid="2560683030046918882">"Wstecz"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ro/strings.xml b/packages/CompanionDeviceManager/res/values-ro/strings.xml
index e3a86c1ec579..072a13155cc5 100644
--- a/packages/CompanionDeviceManager/res/values-ro/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ro/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Manager de dispozitiv Companion"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"Permite ca &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; să acceseze dispozitivul &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
<string name="profile_name_watch" msgid="576290739483672360">"ceas"</string>
<string name="chooser_title" msgid="2262294130493605839">"Alege un profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g> pe care să îl gestioneze &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"Aplicația este necesară pentru a gestiona <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> va putea să sincronizeze informații, cum ar fi numele unui apelant, să interacționeze cu notificările tale și să îți acceseze permisiunile pentru Telefon, SMS, Agendă, Calendar, Jurnale de apeluri și Dispozitive din apropiere."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"Aplicația este necesară pentru a gestiona <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> va putea să sincronizeze informații, cum ar fi numele unui apelant, și să acceseze următoarele permisiuni:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"ochelari"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"Această aplicație este necesară pentru a gestiona <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> va putea să interacționeze cu notificările tale și să-ți acceseze permisiunile pentru Telefon, SMS, Agendă, Microfon și Dispozitive din apropiere."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"Aplicația este necesară pentru a gestiona <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> va putea să interacționeze cu următoarele permisiuni:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Permite ca &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; să acceseze aceste informații de pe telefon"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Servicii pe mai multe dispozitive"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicită permisiunea pentru <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> de a reda în stream aplicații între dispozitivele tale"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Servicii pe mai multe dispozitive"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicită permisiunea pentru <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> de a reda în stream conținut pe dispozitivele din apropiere"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"dispozitiv"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"Aplicația va putea să sincronizeze informații, cum ar fi numele unui apelant, între telefonul tău și <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"Aplicația va putea să sincronizeze informații, cum ar fi numele unui apelant, între telefonul tău și dispozitivul ales."</string>
<string name="consent_yes" msgid="8344487259618762872">"Permite"</string>
<string name="consent_no" msgid="2640796915611404382">"Nu permite"</string>
<string name="consent_back" msgid="2560683030046918882">"Înapoi"</string>
diff --git a/packages/CompanionDeviceManager/res/values-si/strings.xml b/packages/CompanionDeviceManager/res/values-si/strings.xml
index fbe482308515..21ed787954cc 100644
--- a/packages/CompanionDeviceManager/res/values-si/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-si/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"සහායක උපාංග කළමනාකරු"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; හට &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; වෙත ප්‍රවේශ වීමට ඉඩ දෙන්න"</string>
<string name="profile_name_watch" msgid="576290739483672360">"ඔරලෝසුව"</string>
<string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; මගින් කළමනාකරණය කරනු ලැබීමට <xliff:g id="PROFILE_NAME">%1$s</xliff:g>ක් තෝරන්න"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"ඔබේ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> කළමනාකරණය කිරීමට මෙම යෙදුම අවශ්‍යයි. <xliff:g id="APP_NAME">%2$s</xliff:g> හට අමතන කෙනෙකුගේ නම වැනි, තතු සමමුහුර්ත කිරීමට, ඔබේ දැනුම්දීම් සමග අන්තර්ක්‍රියා කිරීමට සහ ඔබේ දුරකථනය, SMS, සම්බන්ධතා, දින දර්ශනය, ඇමතුම් ලොග සහ අවට උපාංග අවසර වෙත ප්‍රවේශ වීමට ඉඩ දෙනු ඇත."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"ඔබේ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> කළමනාකරණය කිරීමට මෙම යෙදුම අවශ්‍යයි. <xliff:g id="APP_NAME">%2$s</xliff:g> හට අමතන කෙනෙකුගේ නම වැනි, තතු සමමුහුර්ත කිරීමට සහ මෙම අවසරවලට ප්‍රවේශ වීමට ඉඩ දෙනු ඇත:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"කණ්ණාඩි"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> කළමනාකරණය කිරීමට මෙම යෙදුම අවශ්‍යයි. <xliff:g id="APP_NAME">%2$s</xliff:g> හට ඔබේ දැනුම්දීම් සමග අන්තර් ක්‍රියා කිරීමට සහ ඔබේ දුරකථනය, SMS, සම්බන්ධතා, මයික්‍රෆෝනය සහ අවට උපාංග අවසර වෙත ප්‍රවේශ වීමට ඉඩ දෙනු ඇත."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> කළමනාකරණය කිරීමට මෙම යෙදුම අවශ්‍යයි. <xliff:g id="APP_NAME">%2$s</xliff:g> හට මෙම අවසර සමග අන්තර්ක්‍රියා කිරීමට අවසර දෙනු ලැබේ:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; හට ඔබගේ දුරකථනයෙන් මෙම තොරතුරුවලට ප්‍රවේශ වීමට ඉඩ දෙන්න"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"හරස්-උපාංග සේවා"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> ඔබගේ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> වෙනුවෙන් ඔබගේ උපාංග අතර යෙදුම් ප්‍රවාහ කිරීමට අවසරය ඉල්ලමින් සිටියි"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"හරස්-උපාංග සේවා"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> අවට උපාංග වෙත අන්තර්ගතය ප්‍රවාහ කිරීමට ඔබේ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> වෙනුවෙන් අවසර ඉල්ලයි"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"උපාංගය"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"මෙම යෙදුමට ඔබේ දුරකථනය සහ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> අතර, අමතන කෙනෙකුගේ නම වැනි, තතු සමමුහුර්ත කිරීමට හැකි වනු ඇත."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"මෙම යෙදුමට ඔබේ දුරකථනය සහ තෝරා ගත් උපාංගය අතර, අමතන කෙනෙකුගේ නම වැනි, තතු සමමුහුර්ත කිරීමට හැකි වනු ඇත."</string>
<string name="consent_yes" msgid="8344487259618762872">"ඉඩ දෙන්න"</string>
<string name="consent_no" msgid="2640796915611404382">"ඉඩ නොදෙන්න"</string>
<string name="consent_back" msgid="2560683030046918882">"ආපසු"</string>
diff --git a/packages/CompanionDeviceManager/res/values-sl/strings.xml b/packages/CompanionDeviceManager/res/values-sl/strings.xml
index 62342861edc2..f804e694f398 100644
--- a/packages/CompanionDeviceManager/res/values-sl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sl/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Upravitelj spremljevalnih naprav"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"Aplikaciji &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; dovolite dostop do naprave &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
<string name="profile_name_watch" msgid="576290739483672360">"ura"</string>
<string name="chooser_title" msgid="2262294130493605839">"Izbira naprave »<xliff:g id="PROFILE_NAME">%1$s</xliff:g>«, ki jo bo upravljala aplikacija &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"Ta aplikacija je potrebna za upravljanje naprave »<xliff:g id="DEVICE_NAME">%1$s</xliff:g>«. Aplikaciji <xliff:g id="APP_NAME">%2$s</xliff:g> bodo omogočene sinhronizacija podatkov, na primer imena klicatelja, interakcija z obvestili in uporaba dovoljenj Telefon, SMS, Stiki, Koledar, Dnevniki klicev in Naprave v bližini."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"Ta aplikacija je potrebna za upravljanje naprave »<xliff:g id="DEVICE_NAME">%1$s</xliff:g>«. Aplikaciji <xliff:g id="APP_NAME">%2$s</xliff:g> bosta omogočena sinhronizacija podatkov, na primer imena klicatelja, in dostop do teh dovoljenj:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"očala"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"Ta aplikacija je potrebna za upravljanje naprave »<xliff:g id="DEVICE_NAME">%1$s</xliff:g>«. Aplikaciji <xliff:g id="APP_NAME">%2$s</xliff:g> bosta omogočeni interakcija z obvestili in uporaba dovoljenj Telefon, SMS, Stiki, Mikrofon in Naprave v bližini."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"Ta aplikacija je potrebna za upravljanje naprave »<xliff:g id="DEVICE_NAME">%1$s</xliff:g>«. Aplikaciji <xliff:g id="APP_NAME">%2$s</xliff:g> bo omogočena interakcija s temi dovoljenji:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Dovolite, da &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; dostopa do teh podatkov v vašem telefonu"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Storitve za zunanje naprave"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> v imenu naprave »<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>« zahteva dovoljenje za pretočno predvajanje aplikacij v vaših napravah."</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Storitve za zunanje naprave"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> v imenu naprave »<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>« zahteva dovoljenje za pretočno predvajanje vsebine v napravah v bližini."</string>
<string name="profile_name_generic" msgid="6851028682723034988">"naprava"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"Ta aplikacija bo lahko sinhronizirala podatke, na primer ime klicatelja, v telefonu in napravi »<xliff:g id="DEVICE_NAME">%1$s</xliff:g>«."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"Ta aplikacija bo lahko sinhronizirala podatke, na primer ime klicatelja, v telefonu in izbrani napravi."</string>
<string name="consent_yes" msgid="8344487259618762872">"Dovoli"</string>
<string name="consent_no" msgid="2640796915611404382">"Ne dovoli"</string>
<string name="consent_back" msgid="2560683030046918882">"Nazaj"</string>
diff --git a/packages/CompanionDeviceManager/res/values-sr/strings.xml b/packages/CompanionDeviceManager/res/values-sr/strings.xml
index 30f83e9fa9d0..8d13c895f209 100644
--- a/packages/CompanionDeviceManager/res/values-sr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sr/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Менаџер придруженог уређаја"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"Дозволите да &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; приступа уређају &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
<string name="profile_name_watch" msgid="576290739483672360">"сат"</string>
<string name="chooser_title" msgid="2262294130493605839">"Одаберите <xliff:g id="PROFILE_NAME">%1$s</xliff:g> којим ће управљати апликација &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"Апликација је потребна за управљање уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ће добити дозволу за синхронизовање информација, попут особе која упућује позив, за интеракцију са обавештењима и приступ дозволама за телефон, SMS, контакте, календар, евиденције позива и уређаје у близини."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"Апликација је потребна за управљање уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ће добити дозволу за синхронизацију информација, попут особе која упућује позив, као за приступ следећим дозволама:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"наочаре"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"Ова апликација је потребна за управљање уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ће добити дозволу за интеракцију са обавештењима и приступ дозволама за телефон, SMS, контакте, микрофон и уређаје у близини."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"Апликација је потребна за управљање уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ће добити дозволу за интеракцију са овим дозволама:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Дозволите да &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; приступа овим информацијама са телефона"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Услуге на више уређаја"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> захтева дозволу у име уређаја <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> за стримовање апликација између уређаја"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Услуге на више уређаја"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"Апликација <xliff:g id="APP_NAME">%1$s</xliff:g> захтева дозволу у име уређаја <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> да стримује садржај на уређаје у близини"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"уређај"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"Ова апликација ће моћи да синхронизује податке, попут имена особе која упућује позив, између телефона и уређаја <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"Ова апликација ће моћи да синхронизује податке, попут имена особе која упућује позив, између телефона и одабраног уређаја."</string>
<string name="consent_yes" msgid="8344487259618762872">"Дозволи"</string>
<string name="consent_no" msgid="2640796915611404382">"Не дозволи"</string>
<string name="consent_back" msgid="2560683030046918882">"Назад"</string>
diff --git a/packages/CompanionDeviceManager/res/values-sv/strings.xml b/packages/CompanionDeviceManager/res/values-sv/strings.xml
index c3c97213283f..82c7e414aa1a 100644
--- a/packages/CompanionDeviceManager/res/values-sv/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sv/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Companion Device Manager"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"Tillåt att &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; får åtkomst till &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
<string name="profile_name_watch" msgid="576290739483672360">"klocka"</string>
<string name="chooser_title" msgid="2262294130493605839">"Välj en <xliff:g id="PROFILE_NAME">%1$s</xliff:g> för hantering av &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"Appen behövs för att hantera <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tillåtelse att synkronisera information, till exempel namnet på någon som ringer, interagera med dina aviseringar och får åtkomst till behörigheterna Telefon, Sms, Kontakter, Kalender, Samtalsloggar och Enheter i närheten."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"Appen behövs för att hantera <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tillåtelse att synkronisera information, till exempel namnet på någon som ringer, och får åtkomst till följande behörigheter:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"glasögon"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"Appen behövs för att hantera <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tillåtelse att interagera med dina aviseringar och får åtkomst till behörigheterna Telefon, Sms, Kontakter, Mikrofon och Enheter i närheten."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"Appen behövs för att hantera <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tillåtelse att interagera med följande behörigheter:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Ge &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; åtkomstbehörighet till denna information på telefonen"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Tjänster för flera enheter"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> begär behörighet att låta <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> streama appar mellan enheter"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Tjänster för flera enheter"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> begär behörighet för att streama innehåll till enheter i närheten för din <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"enhet"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"Den här appen kommer att kunna synkronisera information mellan telefonen och <xliff:g id="DEVICE_NAME">%1$s</xliff:g>, till exempel namnet på någon som ringer."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"Den här appen kommer att kunna synkronisera information mellan telefonen och den valda enheten, till exempel namnet på någon som ringer."</string>
<string name="consent_yes" msgid="8344487259618762872">"Tillåt"</string>
<string name="consent_no" msgid="2640796915611404382">"Tillåt inte"</string>
<string name="consent_back" msgid="2560683030046918882">"Tillbaka"</string>
diff --git a/packages/CompanionDeviceManager/res/values-sw/strings.xml b/packages/CompanionDeviceManager/res/values-sw/strings.xml
index 873c857096b1..37354bbe5639 100644
--- a/packages/CompanionDeviceManager/res/values-sw/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sw/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Kidhibiti cha Vifaa Visaidizi"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"Ruhusu &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ifikie &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
<string name="profile_name_watch" msgid="576290739483672360">"saa"</string>
<string name="chooser_title" msgid="2262294130493605839">"Chagua <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ili idhibitiwe na &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"Programu hii inahitajika ili udhibiti <xliff:g id="DEVICE_NAME">%1$s</xliff:g> yako. <xliff:g id="APP_NAME">%2$s</xliff:g> itaruhusiwa kusawazisha maelezo, kama vile jina la mtu anayepiga simu, kutumia arifa zako na ruhusa zako za Simu, SMS, Anwani, Maikrofoni na vifaa vilivyo Karibu."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"Programu hii inahitajika ili udhibiti <xliff:g id="DEVICE_NAME">%1$s</xliff:g> yako. <xliff:g id="APP_NAME">%2$s</xliff:g> itaruhusiwa kusawazisha maelezo, kama vile jina la mtu anayepiga simu na kufikia ruhusa hizi:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"miwani"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"Programu hii inahitajika ili udhibiti <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> itaruhusiwa kutumia arifa zako na kufikia ruhusa zako za Simu, SMS, Anwani, Maikrofoni na Vifaa vilivyo Karibu."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"Programu inahitajika ili udhibiti <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> itaruhusiwa kufikia ruhusa hizi:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Ruhusu &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ifikie maelezo haya kutoka kwenye simu yako"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Huduma za kifaa kilichounganishwa kwingine"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"Programu ya <xliff:g id="APP_NAME">%1$s</xliff:g> inaomba ruhusa kwa niaba ya <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> yako ili itiririshe programu kati ya vifaa vyako"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Huduma za kifaa kilichounganishwa kwingine"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> inaomba ruhusa kwa niaba ya <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ili itiririshe maudhui kwenye vifaa vilivyo karibu"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"kifaa"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"Programu hii itaweza kusawazisha maelezo, kama vile jina la mtu anayepiga simu, kati ya simu na <xliff:g id="DEVICE_NAME">%1$s</xliff:g> yako."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"Programu hii itaweza kusawazisha maelezo, kama vile jina la mtu anayepiga simu, kati ya simu yako na kifaa ulichochagua."</string>
<string name="consent_yes" msgid="8344487259618762872">"Ruhusu"</string>
<string name="consent_no" msgid="2640796915611404382">"Usiruhusu"</string>
<string name="consent_back" msgid="2560683030046918882">"Nyuma"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ta/strings.xml b/packages/CompanionDeviceManager/res/values-ta/strings.xml
index fbfbc40b2e52..2e1c8725bbf2 100644
--- a/packages/CompanionDeviceManager/res/values-ta/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ta/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"கம்பேனியன் சாதன நிர்வாகி"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; சாதனத்தை &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ஆப்ஸ் அணுக அனுமதியுங்கள்"</string>
<string name="profile_name_watch" msgid="576290739483672360">"வாட்ச்"</string>
<string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; ஆப்ஸ் நிர்வகிக்கக்கூடிய <xliff:g id="PROFILE_NAME">%1$s</xliff:g> தேர்ந்தெடுக்கப்பட வேண்டும்"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"உங்கள் <xliff:g id="DEVICE_NAME">%1$s</xliff:g> சாதனத்தை நிர்வகிக்க இந்த ஆப்ஸ் தேவை. தகவலை (அழைப்பவரின் பெயர் போன்றவை) ஒத்திசைத்தல், உங்கள் அறிவிப்புகளைப் பார்த்தல் போன்றவற்றுக்கான அனுமதியையும் உங்கள் மொபைல், மெசேஜ், தொடர்புகள், கேலெண்டர், அழைப்புப் பதிவுகள், அருகிலுள்ள சாதனங்கள் ஆகியவற்றுக்கான அணுகலையும் <xliff:g id="APP_NAME">%2$s</xliff:g> ஆப்ஸ் பெறும்."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"உங்கள் <xliff:g id="DEVICE_NAME">%1$s</xliff:g> சாதனத்தை நிர்வகிக்க இந்த ஆப்ஸ் தேவை. தகவலை (அழைப்பவரின் பெயர் போன்றவை) ஒத்திசைப்பதற்கும் இந்த அனுமதிகளைப் பயன்படுத்துவதற்கும் <xliff:g id="APP_NAME">%2$s</xliff:g> ஆப்ஸுக்கு அனுமதி வழங்கப்படும்:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"கிளாஸஸ்"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> சாதனத்தை நிர்வகிக்க இந்த ஆப்ஸ் தேவை. உங்கள் மொபைல், மெசேஜ், தொடர்புகள், மைக்ரோஃபோன், அருகிலுள்ள சாதனங்கள் ஆகியவற்றுக்கான அணுகலையும் உங்கள் அறிவிப்புகளைப் பார்ப்பதற்கான அனுமதியையும் <xliff:g id="APP_NAME">%2$s</xliff:g> பெறும்."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> சாதனத்தை நிர்வகிக்க இந்த ஆப்ஸ் தேவை. இந்த அனுமதிகளைப் பயன்படுத்த <xliff:g id="APP_NAME">%2$s</xliff:g> ஆப்ஸ் அனுமதிக்கப்படும்:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"மொபைலில் உள்ள இந்தத் தகவல்களை அணுக, &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ஆப்ஸை அனுமதிக்கவும்"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"பன்முக சாதன சேவைகள்"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"உங்கள் சாதனங்களுக்கு இடையே ஆப்ஸை ஸ்ட்ரீம் செய்ய உங்கள் <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> சார்பாக <xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸ் அனுமதியைக் கோருகிறது"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"பன்முக சாதன சேவைகள்"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"அருகிலுள்ள சாதனங்களுடன் உள்ளடக்கத்தை ஸ்ட்ரீம் செய்ய உங்கள் <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> சார்பாக <xliff:g id="APP_NAME">%1$s</xliff:g> அனுமதி கோருகிறது"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"சாதனம்"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"இந்த ஆப்ஸால் தகவலை (அழைப்பவரின் பெயர் போன்றவை) உங்கள் மொபைலிலும் <xliff:g id="DEVICE_NAME">%1$s</xliff:g> சாதனத்திலும் ஒத்திசைக்க முடியும்."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"இந்த ஆப்ஸால் தகவலை (அழைப்பவரின் பெயர் போன்றவை) உங்கள் மொபைலிலும் தேர்ந்தெடுக்கப்பட்ட சாதனத்திலும் ஒத்திசைக்க முடியும்."</string>
<string name="consent_yes" msgid="8344487259618762872">"அனுமதி"</string>
<string name="consent_no" msgid="2640796915611404382">"அனுமதிக்க வேண்டாம்"</string>
<string name="consent_back" msgid="2560683030046918882">"பின்செல்"</string>
diff --git a/packages/CompanionDeviceManager/res/values-te/strings.xml b/packages/CompanionDeviceManager/res/values-te/strings.xml
index 7c077ce7d15f..4c193c59fb6b 100644
--- a/packages/CompanionDeviceManager/res/values-te/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-te/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"సహచర పరికర మేనేజర్"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;‌ను యాక్సెస్ చేయడానికి &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;‌ను అనుమతించండి"</string>
<string name="profile_name_watch" msgid="576290739483672360">"వాచ్"</string>
<string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; ద్వారా మేనేజ్ చేయబడటానికి ఒక <xliff:g id="PROFILE_NAME">%1$s</xliff:g>ను ఎంచుకోండి"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"మీ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>‌ను మేనేజ్ చేయడానికి ఈ యాప్ అవసరం. కాల్ చేస్తున్న వారి పేరు వంటి సమాచారాన్ని సింక్ చేయడానికి, మీ నోటిఫికేషన్‌లతో ఇంటరాక్ట్ అవ్వడానికి, అలాగే మీ ఫోన్, SMS, కాంటాక్ట్‌లు, క్యాలెండర్, కాల్ లాగ్‌లు, సమీపంలోని పరికరాల అనుమతులను యాక్సెస్ చేయడానికి <xliff:g id="APP_NAME">%2$s</xliff:g> అనుమతించబడుతుంది."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"మీ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>‌ను మేనేజ్ చేయడానికి ఈ యాప్ అవసరం. కాల్ చేస్తున్న వారి పేరు వంటి సమాచారాన్ని సింక్ చేయడానికి, ఈ అనుమతులను యాక్సెస్ చేయడానికి <xliff:g id="APP_NAME">%2$s</xliff:g> అనుమతించబడుతుంది:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"గ్లాసెస్"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>‌ను మేనేజ్ చేయడానికి ఈ యాప్ అవసరం. మీ నోటిఫికేషన్‌లతో ఇంటరాక్ట్ అవ్వడానికి, అలాగే మీ ఫోన్, SMS, కాంటాక్ట్‌లు, మైక్రోఫోన్, సమీపంలోని పరికరాల అనుమతులను యాక్సెస్ చేయడానికి <xliff:g id="APP_NAME">%2$s</xliff:g> అనుమతించబడుతుంది."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>‌ను మేనేజ్ చేయడానికి ఈ యాప్ అవసరం. ఈ అనుమతులతో ఇంటరాక్ట్ అవ్వడానికి <xliff:g id="APP_NAME">%2$s</xliff:g> అనుమతించబడుతుంది:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"మీ ఫోన్ నుండి ఈ సమాచారాన్ని యాక్సెస్ చేయడానికి &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; యాప్‌ను అనుమతించండి"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"మీ పరికరాల మధ్య యాప్‌లను స్ట్రీమ్ చేయడానికి <xliff:g id="APP_NAME">%1$s</xliff:g> మీ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> తరఫున అనుమతిని రిక్వెస్ట్ చేస్తోంది"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"క్రాస్-డివైజ్ సర్వీస్‌లు"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"సమీపంలోని పరికరాలకు కంటెంట్‌ను స్ట్రీమ్ చేయడానికి <xliff:g id="APP_NAME">%1$s</xliff:g> మీ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> తరఫున అనుమతిని రిక్వెస్ట్ చేస్తోంది"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"పరికరం"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"కాల్ చేస్తున్న వారి పేరు వంటి సమాచారాన్ని ఈ యాప్ మీ ఫోన్, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> మధ్య సింక్ చేయగలుగుతుంది."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"కాల్ చేస్తున్న వారి పేరు వంటి సమాచారాన్ని ఈ యాప్ మీ ఫోన్, ఎంచుకున్న పరికరం మధ్య సింక్ చేయగలుగుతుంది."</string>
<string name="consent_yes" msgid="8344487259618762872">"అనుమతించండి"</string>
<string name="consent_no" msgid="2640796915611404382">"అనుమతించవద్దు"</string>
<string name="consent_back" msgid="2560683030046918882">"వెనుకకు"</string>
diff --git a/packages/CompanionDeviceManager/res/values-tl/strings.xml b/packages/CompanionDeviceManager/res/values-tl/strings.xml
index 2fd2edaa91e5..dd9a0f6edb57 100644
--- a/packages/CompanionDeviceManager/res/values-tl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-tl/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Kasamang Device Manager"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"Payagan ang &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; na i-access ang &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
<string name="profile_name_watch" msgid="576290739483672360">"relo"</string>
<string name="chooser_title" msgid="2262294130493605839">"Pumili ng <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para pamahalaan ng &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"Kailangan ang app para mapamahalaan ang iyong <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Papayagan ang <xliff:g id="APP_NAME">%2$s</xliff:g> na mag-sync ng impormasyon, tulad ng pangalan ng isang taong tumatawag, makipag-ugnayan sa mga notification mo, at ma-access ang iyong mga pahintulot sa Telepono, SMS, Mga Contact, Kalendaryo, Mga log ng tawag, at Mga kalapit na device."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"Kailangan ang app para mapamahalaan ang iyong <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Papayagan ang <xliff:g id="APP_NAME">%2$s</xliff:g> na mag-sync ng impormasyon, tulad ng pangalan ng isang taong tumatawag, at na ma-access ang mga pahintulot na ito:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"salamin"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"Kailangan ang app na ito para mapamahalaan ang <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Papayagan ang <xliff:g id="APP_NAME">%2$s</xliff:g> na makipag-ugnayan sa mga notification mo at i-access ang iyong mga pahintulot sa Telepono, SMS, Mga Contact, Mikropono, at Mga kalapit na device."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"Kailangan ang app para mapamahalaan ang <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Papayagan ang <xliff:g id="APP_NAME">%2$s</xliff:g> na makipag-ugnayan sa mga pahintulot na ito:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Payagan ang &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; na i-access ang impormasyong ito sa iyong telepono"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Mga cross-device na serbisyo"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"Ang <xliff:g id="APP_NAME">%1$s</xliff:g> ay humihiling ng pahintulot sa ngalan ng iyong <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para mag-stream ng mga app sa pagitan ng mga device mo"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Mga cross-device na serbisyo"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"Humihiling ng pahintulot ang <xliff:g id="APP_NAME">%1$s</xliff:g> sa ngalan ng iyong <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para mag-stream ng content sa mga kalapit na device"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"Magagawa ng app na ito na mag-sync ng impormasyon, tulad ng pangalan ng isang taong tumatawag, sa pagitan ng iyong telepono at ng <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"Magagawa ng app na ito na mag-sync ng impormasyon, tulad ng pangalan ng isang taong tumatawag, sa pagitan ng iyong telepono at ng napiling device."</string>
<string name="consent_yes" msgid="8344487259618762872">"Payagan"</string>
<string name="consent_no" msgid="2640796915611404382">"Huwag payagan"</string>
<string name="consent_back" msgid="2560683030046918882">"Bumalik"</string>
diff --git a/packages/CompanionDeviceManager/res/values-tr/strings.xml b/packages/CompanionDeviceManager/res/values-tr/strings.xml
index 8a73c654f6a3..0bf5c1f4a59d 100644
--- a/packages/CompanionDeviceManager/res/values-tr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-tr/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Companion Device Manager"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"&lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; cihazına erişmesi için &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; uygulamasına izin verin"</string>
<string name="profile_name_watch" msgid="576290739483672360">"saat"</string>
<string name="chooser_title" msgid="2262294130493605839">"&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; tarafından yönetilecek bir <xliff:g id="PROFILE_NAME">%1$s</xliff:g> seçin"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"Bu uygulama, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazınızın yönetilmesi için gereklidir. <xliff:g id="APP_NAME">%2$s</xliff:g> adlı uygulamanın arayan kişinin adı gibi bilgileri senkronize etmesine, bildirimlerinizle etkileşimde bulunup Telefon, SMS, Kişiler, Takvim, Arama kayıtları ve Yakındaki cihazlar izinlerine erişmesine izin verilir."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"Bu uygulama, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazınızın yönetilmesi için gereklidir. <xliff:g id="APP_NAME">%2$s</xliff:g> adlı uygulamanın arayan kişinin adı gibi bilgileri senkronize etmesine ve aşağıdaki izinlere erişmesine izin verilir:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"glasses"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"Bu uygulama, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazının yönetilmesi için gereklidir. <xliff:g id="APP_NAME">%2$s</xliff:g> adlı uygulamanın bildirimlerinizle etkileşimde bulunup Telefon, SMS, Kişiler, Mikrofon ve Yakındaki cihazlar izinlerine erişmesine izin verilir."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"Uygulama, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazının yönetilmesi için gereklidir. <xliff:g id="APP_NAME">%2$s</xliff:g> uygulamasının şu izinlerle etkileşime girmesine izin verilir:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; uygulamasının, telefonunuzdaki bu bilgilere erişmesine izin verin"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Cihazlar arası hizmetler"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g>, cihazlarınız arasında uygulama akışı gerçekleştirmek için <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> cihazınız adına izin istiyor"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Cihazlar arası hizmetler"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g>, yakındaki cihazlarda içerikleri canlı oynatmak için <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> cihazınız adına izin istiyor"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"cihaz"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"Bu uygulama, arayan kişinin adı gibi bilgileri telefonunuz ve <xliff:g id="DEVICE_NAME">%1$s</xliff:g> adlı cihaz arasında senkronize edebilir."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"Bu uygulama, arayan kişinin adı gibi bilgileri telefonunuz ve seçili cihaz arasında senkronize edebilir."</string>
<string name="consent_yes" msgid="8344487259618762872">"İzin ver"</string>
<string name="consent_no" msgid="2640796915611404382">"İzin verme"</string>
<string name="consent_back" msgid="2560683030046918882">"Geri"</string>
diff --git a/packages/CompanionDeviceManager/res/values-uk/strings.xml b/packages/CompanionDeviceManager/res/values-uk/strings.xml
index 1ba997e0d1d6..29a55da07fe5 100644
--- a/packages/CompanionDeviceManager/res/values-uk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-uk/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Диспетчер супутніх пристроїв"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"Надати додатку &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; доступ до пристрою &lt;strong&gt;\"<xliff:g id="DEVICE_NAME">%2$s</xliff:g>\"&lt;/strong&gt;"</string>
<string name="profile_name_watch" msgid="576290739483672360">"годинник"</string>
<string name="chooser_title" msgid="2262294130493605839">"Виберіть <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, яким керуватиме додаток &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"Цей додаток потрібен, щоб керувати пристроєм \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". Додаток <xliff:g id="APP_NAME">%2$s</xliff:g> зможе синхронізувати інформацію (наприклад, ім’я абонента, який викликає), взаємодіяти з вашими сповіщеннями й отримає дозволи \"Телефон\", \"SMS\", \"Контакти\", \"Календар\", \"Журнали викликів\" і \"Пристрої поблизу\"."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"Цей додаток потрібен, щоб керувати пристроєм \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". Додаток <xliff:g id="APP_NAME">%2$s</xliff:g> зможе синхронізувати інформацію (наприклад, ім’я абонента, який викликає) і отримає такі дозволи:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"окуляри"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"Цей додаток потрібен, щоб керувати пристроєм \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". Додаток <xliff:g id="APP_NAME">%2$s</xliff:g> зможе взаємодіяти з вашими сповіщеннями й отримає дозволи \"Телефон\", \"SMS\", \"Контакти\", \"Мікрофон\" і \"Пристрої поблизу\"."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"Цей додаток потрібен, щоб керувати пристроєм \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". Додаток <xliff:g id="APP_NAME">%2$s</xliff:g> зможе взаємодіяти з такими дозволами:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Надайте додатку &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; доступ до цієї інформації з телефона"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Сервіси для кількох пристроїв"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> від імені вашого пристрою <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> запитує дозвіл на трансляцію додатків між вашими пристроями"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Сервіси для кількох пристроїв"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> від імені вашого пристрою (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) запитує дозвіл на трансляцію контенту на пристрої поблизу"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"пристрій"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"Цей додаток зможе синхронізувати інформацію (наприклад, ім’я абонента, який викликає) між телефоном і пристроєм \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\"."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"Цей додаток зможе синхронізувати інформацію (наприклад, ім’я абонента, який викликає) між телефоном і вибраним пристроєм."</string>
<string name="consent_yes" msgid="8344487259618762872">"Дозволити"</string>
<string name="consent_no" msgid="2640796915611404382">"Не дозволяти"</string>
<string name="consent_back" msgid="2560683030046918882">"Назад"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ur/strings.xml b/packages/CompanionDeviceManager/res/values-ur/strings.xml
index f83e216db71d..c38217a57da9 100644
--- a/packages/CompanionDeviceManager/res/values-ur/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ur/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"ساتھی آلہ مینیجر"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"‏&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; کو &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt; تک رسائی کی اجازت دیں"</string>
<string name="profile_name_watch" msgid="576290739483672360">"دیکھیں"</string>
<string name="chooser_title" msgid="2262294130493605839">"‏&lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; کے ذریعے نظم کئے جانے کیلئے <xliff:g id="PROFILE_NAME">%1$s</xliff:g> کو منتخب کریں"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"‏آپ کے <xliff:g id="DEVICE_NAME">%1$s</xliff:g> کا نظم کرنے کے لیے، ایپ کی ضرورت ہے۔ <xliff:g id="APP_NAME">%2$s</xliff:g> کو کسی کے کال کرنے والے کے نام، آپ کی اطلاعات کے ساتھ تعامل، آپ کے فون، SMS، رابطے، کیلنڈر، کال لاگز اور قریبی آلات کی اجازتوں جیسی معلومات کی مطابقت پذیری کی اجازت ہوگی۔"</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"آپ کے <xliff:g id="DEVICE_NAME">%1$s</xliff:g> کا نظم کرنے کے لیے، ایپ کی ضرورت ہے۔ <xliff:g id="APP_NAME">%2$s</xliff:g> کو کسی کال کرنے والے کے نام اور ان اجازتوں تک رسائی جیسی معلومات کی مطابقت پذیری کی اجازت ہوگی:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"گلاسز"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"‏<xliff:g id="DEVICE_NAME">%1$s</xliff:g> کا نظم کرنے کے لیے، اس ایپ کی ضرورت ہے۔ <xliff:g id="APP_NAME">%2$s</xliff:g> کو آپ کی اطلاعات کے ساتھ تعامل کرنے اور آپ کے فون، SMS، رابطوں، مائیکروفون اور قریبی آلات کی اجازتوں تک رسائی کی اجازت ہوگی۔"</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> کا نظم کرنے کے لیے، ایپ کی ضرورت ہے۔ <xliff:g id="APP_NAME">%2$s</xliff:g> کو ان اجازتوں کے ساتھ تعامل کرنے کی اجازت ہوگی:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"‏اپنے فون سے ان معلومات تک رسائی حاصل کرنے کی &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; کو اجازت دیں"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"کراس ڈیوائس سروسز"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> ایپ آپ کے <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> کی جانب سے آپ کے آلات کے درمیان ایپس کی سلسلہ بندی کرنے کی اجازت کی درخواست کر رہی ہے"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"کراس آلے کی سروسز"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> ایپ آپ کے <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> کی جانب سے مواد کے قریبی آلات کی سلسلہ بندی کرنے کی اجازت کی درخواست کر رہی ہے"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"آلہ"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"یہ ایپ آپ کے فون اور <xliff:g id="DEVICE_NAME">%1$s</xliff:g> کے درمیان معلومات، جیسے کسی کال کرنے والے کے نام، کی مطابقت پذیری کر سکے گی۔"</string>
+ <string name="summary_generic" msgid="4988130802522924650">"یہ ایپ آپ کے فون اور منتخب کردہ آلے کے درمیان معلومات، جیسے کسی کال کرنے والے کے نام، کی مطابقت پذیری کر سکے گی۔"</string>
<string name="consent_yes" msgid="8344487259618762872">"اجازت دیں"</string>
<string name="consent_no" msgid="2640796915611404382">"اجازت نہ دیں"</string>
<string name="consent_back" msgid="2560683030046918882">"پیچھے"</string>
diff --git a/packages/CompanionDeviceManager/res/values-vi/strings.xml b/packages/CompanionDeviceManager/res/values-vi/strings.xml
index e5f50af8529b..a71d6473a712 100644
--- a/packages/CompanionDeviceManager/res/values-vi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-vi/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"Companion Device Manager"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"Cho phép &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; truy cập &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
<string name="profile_name_watch" msgid="576290739483672360">"đồng hồ"</string>
<string name="chooser_title" msgid="2262294130493605839">"Chọn một <xliff:g id="PROFILE_NAME">%1$s</xliff:g> sẽ do &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; quản lý"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"Cần có ứng dụng này để quản lý <xliff:g id="DEVICE_NAME">%1$s</xliff:g> của bạn. <xliff:g id="APP_NAME">%2$s</xliff:g> sẽ được phép đồng bộ hoá thông tin (ví dụ: tên người gọi), tương tác với thông báo của bạn cũng như truy cập vào dữ liệu Điện thoại, SMS, Danh bạ, Lịch, Nhật ký cuộc gọi và Thiết bị ở gần."</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"Cần có ứng dụng này để quản lý <xliff:g id="DEVICE_NAME">%1$s</xliff:g> của bạn. <xliff:g id="APP_NAME">%2$s</xliff:g> sẽ được phép đồng bộ hoá thông tin (ví dụ: tên người gọi) và có các quyền sau:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"kính"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"Bạn cần có ứng dụng này để quản lý <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> sẽ được phép tương tác với thông báo của bạn cũng như truy cập vào dữ liệu Điện thoại, SMS, Danh bạ, Micrô và Thiết bị ở gần."</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"Bạn cần có ứng dụng này để quản lý <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> sẽ được phép tương tác bằng những quyền sau:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Cho phép &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; truy cập vào thông tin này trên điện thoại của bạn"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Dịch vụ trên nhiều thiết bị"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> đang yêu cầu quyền thay cho <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> để truyền trực tuyến ứng dụng giữa các thiết bị của bạn"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"Dịch vụ trên nhiều thiết bị"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"<xliff:g id="APP_NAME">%1$s</xliff:g> đang thay mặt <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> yêu cầu quyền để truyền nội dung đến các thiết bị ở gần"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"thiết bị"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"Ứng dụng này sẽ đồng bộ hoá được thông tin (ví dụ: tên người gọi) giữa điện thoại của bạn và <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="summary_generic" msgid="4988130802522924650">"Ứng dụng này sẽ đồng bộ hoá được thông tin (ví dụ: tên người gọi) giữa điện thoại của bạn và thiết bị bạn chọn."</string>
<string name="consent_yes" msgid="8344487259618762872">"Cho phép"</string>
<string name="consent_no" msgid="2640796915611404382">"Không cho phép"</string>
<string name="consent_back" msgid="2560683030046918882">"Quay lại"</string>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
index 7620ce487c89..b582d94fec9c 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"隨附裝置管理工具"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"允許 &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; 存取 &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
<string name="profile_name_watch" msgid="576290739483672360">"手錶"</string>
<string name="chooser_title" msgid="2262294130493605839">"選擇由 &lt;strong&gt;<xliff:g id="APP_NAME">%2$s</xliff:g>&lt;/strong&gt; 管理的<xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"必須使用此應用程式,才能管理「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」。「<xliff:g id="APP_NAME">%2$s</xliff:g>」將可同步資訊 (例如來電者的名稱)、透過通知與您互動,並存取電話、短訊、通訊錄、日曆、通話記錄和附近的裝置權限。"</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"必須使用此應用程式,才能管理「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」。「<xliff:g id="APP_NAME">%2$s</xliff:g>」將可同步資訊 (例如來電者的名稱),並存取以下權限:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"眼鏡"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"必須使用此應用程式,才能管理「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」。「<xliff:g id="APP_NAME">%2$s</xliff:g>」將可透過通知與您互動,並存取電話、短訊、通訊錄、麥克風和附近的裝置權限。"</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"必須使用此應用程式,才能管理「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」。「<xliff:g id="APP_NAME">%2$s</xliff:g>」將可存取以下權限:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;strong&gt;&lt;/strong&gt;存取您手機中的這項資料"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"跨裝置服務"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在為 <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> 要求權限,以在裝置之間串流應用程式內容"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"跨裝置服務"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在代表「<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>」將內容串流至附近的裝置"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"裝置"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"此應用程式將可同步手機和「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」的資訊,例如來電者的名稱。"</string>
+ <string name="summary_generic" msgid="4988130802522924650">"此應用程式將可同步手機和所選裝置的資訊,例如來電者的名稱。"</string>
<string name="consent_yes" msgid="8344487259618762872">"允許"</string>
<string name="consent_no" msgid="2640796915611404382">"不允許"</string>
<string name="consent_back" msgid="2560683030046918882">"返回"</string>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
index a82996134a7f..401368db4cca 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
@@ -17,19 +17,14 @@
<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="4470785958457506021">"隨附裝置管理工具"</string>
- <!-- no translation found for confirmation_title (8024993972587946678) -->
- <skip />
+ <string name="confirmation_title" msgid="8024993972587946678">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;strong&gt;&lt;/strong&gt;存取「<xliff:g id="DEVICE_NAME">%2$s</xliff:g>」&lt;strong&gt;&lt;/strong&gt;"</string>
<string name="profile_name_watch" msgid="576290739483672360">"手錶"</string>
<string name="chooser_title" msgid="2262294130493605839">"選擇要讓「<xliff:g id="APP_NAME">%2$s</xliff:g>」&lt;strong&gt;&lt;/strong&gt;管理的<xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for summary_watch (6566922405914995759) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (7443464525873186735) -->
- <skip />
+ <string name="summary_watch" msgid="6566922405914995759">"你必須使用這個應用程式,才能管理「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」。「<xliff:g id="APP_NAME">%2$s</xliff:g>」將可同步資訊 (例如來電者名稱)、存取通知及在通知上執行操作,並取得電話、簡訊、聯絡人、日曆、通話記錄、麥克風和鄰近裝置權限。"</string>
+ <string name="summary_watch_single_device" msgid="7443464525873186735">"你必須使用這個應用程式,才能管理「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」。「<xliff:g id="APP_NAME">%2$s</xliff:g>」將可同步資訊 (例如來電者名稱),並取得以下權限:"</string>
<string name="profile_name_glasses" msgid="8488394059007275998">"眼鏡"</string>
- <!-- no translation found for summary_glasses (3808267780579061241) -->
- <skip />
- <!-- no translation found for summary_glasses_single_device (7051392780285915640) -->
- <skip />
+ <string name="summary_glasses" msgid="3808267780579061241">"你必須使用這個應用程式,才能管理「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」。「<xliff:g id="APP_NAME">%2$s</xliff:g>」將可存取通知及在通知上執行操作,並取得電話、簡訊、聯絡人、麥克風和鄰近裝置權限。"</string>
+ <string name="summary_glasses_single_device" msgid="7051392780285915640">"你必須使用這個應用程式,才能管理「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」。「<xliff:g id="APP_NAME">%2$s</xliff:g>」將取得以下權限:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;strong&gt;&lt;/strong&gt;存取手機中的這項資訊"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"跨裝置服務"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在代表你的「<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>」要求必要權限,以便在裝置之間串流傳輸應用程式內容"</string>
@@ -43,10 +38,8 @@
<string name="helper_title_nearby_device_streaming" msgid="6124438217620593669">"跨裝置服務"</string>
<string name="helper_summary_nearby_device_streaming" msgid="5538329403511524333">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在代表你的「<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>」將內容串流傳輸到鄰近裝置"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"裝置"</string>
- <!-- no translation found for summary_generic_single_device (4735072202474939111) -->
- <skip />
- <!-- no translation found for summary_generic (4988130802522924650) -->
- <skip />
+ <string name="summary_generic_single_device" msgid="4735072202474939111">"這個應用程式將可在手機和「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」之間同步資訊,例如來電者名稱。"</string>
+ <string name="summary_generic" msgid="4988130802522924650">"這個應用程式將可在手機和指定裝置之間同步資訊,例如來電者名稱。"</string>
<string name="consent_yes" msgid="8344487259618762872">"允許"</string>
<string name="consent_no" msgid="2640796915611404382">"不允許"</string>
<string name="consent_back" msgid="2560683030046918882">"返回"</string>
diff --git a/packages/CredentialManager/Android.bp b/packages/CredentialManager/Android.bp
index 00d42bd836b1..28b9bc04a249 100644
--- a/packages/CredentialManager/Android.bp
+++ b/packages/CredentialManager/Android.bp
@@ -20,6 +20,7 @@ android_app {
},
static_libs: [
+ "PlatformComposeCore",
"androidx.activity_activity-compose",
"androidx.appcompat_appcompat",
"androidx.compose.animation_animation-core",
diff --git a/packages/CredentialManager/AndroidManifest.xml b/packages/CredentialManager/AndroidManifest.xml
index b36cb5c9709f..dfc8aa06c404 100644
--- a/packages/CredentialManager/AndroidManifest.xml
+++ b/packages/CredentialManager/AndroidManifest.xml
@@ -41,6 +41,15 @@
android:excludeFromRecents="true"
android:theme="@style/Theme.CredentialSelector">
</activity>
+
+ <receiver
+ android:name=".CredentialProviderReceiver"
+ android:exported="true"
+ android:permission="android.permission.LAUNCH_CREDENTIAL_SELECTOR">
+ <intent-filter>
+ <action android:name="android.credentials.ui.action.CREDMAN_ENABLED_PROVIDERS_UPDATED"/>
+ </intent-filter>
+ </receiver>
</application>
</manifest>
diff --git a/packages/CredentialManager/res/drawable/ic_other_devices.xml b/packages/CredentialManager/res/drawable/ic_other_devices.xml
deleted file mode 100644
index 754648cbca1d..000000000000
--- a/packages/CredentialManager/res/drawable/ic_other_devices.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<vector
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- tools:ignore="VectorPath"
- android:name="vector"
- android:width="20dp"
- android:height="20dp"
- android:viewportWidth="20"
- android:viewportHeight="20">
- <path
- android:name="path"
- android:pathData="M 7.6 4.72 L 7.6 7.6 L 4.72 7.6 L 4.72 4.72 L 7.6 4.72 Z M 9.04 3.28 L 3.28 3.28 L 3.28 9.04 L 9.04 9.04 L 9.04 3.28 Z M 7.6 12.4 L 7.6 15.28 L 4.72 15.28 L 4.72 12.4 L 7.6 12.4 Z M 9.04 10.96 L 3.28 10.96 L 3.28 16.72 L 9.04 16.72 L 9.04 10.96 Z M 15.28 4.72 L 15.28 7.6 L 12.4 7.6 L 12.4 4.72 L 15.28 4.72 Z M 16.72 3.28 L 10.96 3.28 L 10.96 9.04 L 16.72 9.04 L 16.72 3.28 Z M 10.96 10.96 L 12.4 10.96 L 12.4 12.4 L 10.96 12.4 L 10.96 10.96 Z M 12.4 12.4 L 13.84 12.4 L 13.84 13.84 L 12.4 13.84 L 12.4 12.4 Z M 13.84 10.96 L 15.28 10.96 L 15.28 12.4 L 13.84 12.4 L 13.84 10.96 Z M 10.96 13.84 L 12.4 13.84 L 12.4 15.28 L 10.96 15.28 L 10.96 13.84 Z M 12.4 15.28 L 13.84 15.28 L 13.84 16.72 L 12.4 16.72 L 12.4 15.28 Z M 13.84 13.84 L 15.28 13.84 L 15.28 15.28 L 13.84 15.28 L 13.84 13.84 Z M 15.28 12.4 L 16.72 12.4 L 16.72 13.84 L 15.28 13.84 L 15.28 12.4 Z M 15.28 15.28 L 16.72 15.28 L 16.72 16.72 L 15.28 16.72 L 15.28 15.28 Z M 19.6 5.2 L 17.68 5.2 L 17.68 2.32 L 14.8 2.32 L 14.8 0.4 L 19.6 0.4 L 19.6 5.2 Z M 19.6 19.6 L 19.6 14.8 L 17.68 14.8 L 17.68 17.68 L 14.8 17.68 L 14.8 19.6 L 19.6 19.6 Z M 0.4 19.6 L 5.2 19.6 L 5.2 17.68 L 2.32 17.68 L 2.32 14.8 L 0.4 14.8 L 0.4 19.6 Z M 0.4 0.4 L 0.4 5.2 L 2.32 5.2 L 2.32 2.32 L 5.2 2.32 L 5.2 0.4 L 0.4 0.4 Z"
- android:fillColor="#000000"
- android:strokeWidth="1"/>
-</vector> \ No newline at end of file
diff --git a/packages/CredentialManager/res/drawable/ic_other_sign_in.xml b/packages/CredentialManager/res/drawable/ic_other_sign_in.xml
deleted file mode 100644
index 81501972d3ba..000000000000
--- a/packages/CredentialManager/res/drawable/ic_other_sign_in.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<!--
- ~ Copyright (C) 2022 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<vector
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- tools:ignore="VectorPath"
- android:name="vector"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <path
- android:name="path"
- android:pathData="M 20 19 L 12 19 L 12 21 L 20 21 C 21.1 21 22 20.1 22 19 L 22 5 C 22 3.9 21.1 3 20 3 L 12 3 L 12 5 L 20 5 L 20 19 Z"
- android:fillColor="#000"
- android:strokeWidth="1"/>
- <path
- android:name="path_1"
- android:pathData="M 12 7 L 10.6 8.4 L 13.2 11 L 8.85 11 C 8.42 9.55 7.09 8.5 5.5 8.5 C 3.57 8.5 2 10.07 2 12 C 2 13.93 3.57 15.5 5.5 15.5 C 7.09 15.5 8.42 14.45 8.85 13 L 13.2 13 L 10.6 15.6 L 12 17 L 17 12 L 12 7 Z M 5.5 13.5 C 4.67 13.5 4 12.83 4 12 C 4 11.17 4.67 10.5 5.5 10.5 C 6.33 10.5 7 11.17 7 12 C 7 12.83 6.33 13.5 5.5 13.5 Z"
- android:fillColor="#000"
- android:strokeWidth="1"/>
-</vector> \ No newline at end of file
diff --git a/packages/CredentialManager/res/drawable/ic_other_sign_in_24.xml b/packages/CredentialManager/res/drawable/ic_other_sign_in_24.xml
new file mode 100644
index 000000000000..ce2aeb213cf2
--- /dev/null
+++ b/packages/CredentialManager/res/drawable/ic_other_sign_in_24.xml
@@ -0,0 +1,30 @@
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<vector
+ android:alpha="0.8"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+>
+<group>
+ <clip-path android:pathData="M0,0h24v24h-24z"/>
+ <path android:fillColor="#444746" android:pathData="M20,19H12V21H20C21.1,21 22,20.1 22,19V5C22,3.9 21.1,3 20,3H12V5H20V19Z"/>
+ <path android:fillColor="#444746" android:pathData="M12,7L10.6,8.4L13.2,11H8.85C8.42,9.55 7.09,8.5 5.5,8.5C3.57,8.5 2,10.07 2,12C2,13.93 3.57,15.5 5.5,15.5C7.09,15.5 8.42,14.45 8.85,13H13.2L10.6,15.6L12,17L17,12L12,7ZM5.5,13.5C4.67,13.5 4,12.83 4,12C4,11.17 4.67,10.5 5.5,10.5C6.33,10.5 7,11.17 7,12C7,12.83 6.33,13.5 5.5,13.5Z"/>
+</group>
+</vector> \ No newline at end of file
diff --git a/packages/CredentialManager/res/drawable/ic_passkey.xml b/packages/CredentialManager/res/drawable/ic_passkey.xml
deleted file mode 100644
index 041a32164073..000000000000
--- a/packages/CredentialManager/res/drawable/ic_passkey.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="28dp"
- android:height="24dp"
- android:viewportWidth="28"
- android:viewportHeight="24">
- <path
- android:pathData="M27.453,13.253C27.453,14.952 26.424,16.411 24.955,17.041L26.21,18.295L24.839,19.666L26.21,21.037L23.305,23.942L22.012,22.65L22.012,17.156C20.385,16.605 19.213,15.066 19.213,13.253C19.213,10.977 21.058,9.133 23.333,9.133C25.609,9.133 27.453,10.977 27.453,13.253ZM25.47,13.254C25.47,14.434 24.514,15.39 23.334,15.39C22.154,15.39 21.197,14.434 21.197,13.254C21.197,12.074 22.154,11.118 23.334,11.118C24.514,11.118 25.47,12.074 25.47,13.254Z"
- android:fillColor="#00639B"
- android:fillType="evenOdd"/>
- <path
- android:pathData="M17.85,5.768C17.85,8.953 15.268,11.536 12.083,11.536C8.897,11.536 6.315,8.953 6.315,5.768C6.315,2.582 8.897,0 12.083,0C15.268,0 17.85,2.582 17.85,5.768Z"
- android:fillColor="#00639B"/>
- <path
- android:pathData="M0.547,20.15C0.547,16.32 8.23,14.382 12.083,14.382C13.59,14.382 15.684,14.679 17.674,15.269C18.116,16.454 18.952,17.447 20.022,18.089V23.071H0.547V20.15Z"
- android:fillColor="#00639B"/>
-</vector>
diff --git a/packages/CredentialManager/res/drawable/ic_passkey_24.xml b/packages/CredentialManager/res/drawable/ic_passkey_24.xml
new file mode 100644
index 000000000000..a2c4f374caf1
--- /dev/null
+++ b/packages/CredentialManager/res/drawable/ic_passkey_24.xml
@@ -0,0 +1,28 @@
+<!--
+ ~ Copyright (C) 2023 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:alpha="0.8"
+ android:height="24dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools">
+ <path android:fillColor="#4C463C" android:fillType="evenOdd" android:pathData="M22.18,14.09C22.18,15.364 21.408,16.459 20.306,16.931L21.247,17.872L20.219,18.9L21.247,19.928L19.068,22.107L18.099,21.138L18.099,17.017C16.878,16.604 16,15.45 16,14.09C16,12.383 17.383,11 19.09,11C20.796,11 22.18,12.383 22.18,14.09ZM20.692,14.091C20.692,14.976 19.975,15.693 19.09,15.693C18.205,15.693 17.488,14.976 17.488,14.091C17.488,13.206 18.205,12.488 19.09,12.488C19.975,12.488 20.692,13.206 20.692,14.091Z"/>
+ <path android:fillColor="#4C463C" android:pathData="M14.978,8.476C14.978,10.865 13.041,12.802 10.652,12.802C8.263,12.802 6.326,10.865 6.326,8.476C6.326,6.087 8.263,4.15 10.652,4.15C13.041,4.15 14.978,6.087 14.978,8.476Z"/>
+ <path android:fillColor="#4C463C" android:pathData="M2,19.263C2,16.39 7.762,14.937 10.652,14.937C11.782,14.937 13.353,15.16 14.845,15.602C15.177,16.491 15.804,17.236 16.607,17.717V21.454H2V19.263Z"/>
+</vector>
diff --git a/packages/CredentialManager/res/drawable/ic_password.xml b/packages/CredentialManager/res/drawable/ic_password.xml
deleted file mode 100644
index bf3056a115c1..000000000000
--- a/packages/CredentialManager/res/drawable/ic_password.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<!--
- ~ Copyright (C) 2022 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<vector
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- tools:ignore="VectorPath"
- android:name="vector"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <path
- android:name="path"
- android:pathData="M 8.71 10.29 C 8.52 10.1 8.28 10 8 10 L 7.75 10 L 7.75 8.75 C 7.75 7.98 7.48 7.33 6.95 6.8 C 6.42 6.27 5.77 6 5 6 C 4.23 6 3.58 6.27 3.05 6.8 C 2.52 7.33 2.25 7.98 2.25 8.75 L 2.25 10 L 2 10 C 1.72 10 1.48 10.1 1.29 10.29 C 1.1 10.48 1 10.72 1 11 L 1 16 C 1 16.28 1.1 16.52 1.29 16.71 C 1.48 16.9 1.72 17 2 17 L 8 17 C 8.28 17 8.52 16.9 8.71 16.71 C 8.9 16.52 9 16.28 9 16 L 9 11 C 9 10.72 8.9 10.48 8.71 10.29 Z M 6.25 10 L 3.75 10 L 3.75 8.75 C 3.75 8.4 3.87 8.1 4.11 7.86 C 4.35 7.62 4.65 7.5 5 7.5 C 5.35 7.5 5.65 7.62 5.89 7.86 C 6.13 8.1 6.25 8.4 6.25 8.75 L 6.25 10 Z M 10 14 L 23 14 L 23 16 L 10 16 Z M 21.5 9 C 21.102 9 20.721 9.158 20.439 9.439 C 20.158 9.721 20 10.102 20 10.5 C 20 10.898 20.158 11.279 20.439 11.561 C 20.721 11.842 21.102 12 21.5 12 C 21.898 12 22.279 11.842 22.561 11.561 C 22.842 11.279 23 10.898 23 10.5 C 23 10.102 22.842 9.721 22.561 9.439 C 22.279 9.158 21.898 9 21.5 9 Z M 16.5 9 C 16.102 9 15.721 9.158 15.439 9.439 C 15.158 9.721 15 10.102 15 10.5 C 15 10.898 15.158 11.279 15.439 11.561 C 15.721 11.842 16.102 12 16.5 12 C 16.898 12 17.279 11.842 17.561 11.561 C 17.842 11.279 18 10.898 18 10.5 C 18 10.102 17.842 9.721 17.561 9.439 C 17.279 9.158 16.898 9 16.5 9 Z M 11.5 9 C 11.102 9 10.721 9.158 10.439 9.439 C 10.158 9.721 10 10.102 10 10.5 C 10 10.898 10.158 11.279 10.439 11.561 C 10.721 11.842 11.102 12 11.5 12 C 11.898 12 12.279 11.842 12.561 11.561 C 12.842 11.279 13 10.898 13 10.5 C 13 10.102 12.842 9.721 12.561 9.439 C 12.279 9.158 11.898 9 11.5 9 Z"
- android:fillColor="#000"
- android:strokeWidth="1"/>
-</vector> \ No newline at end of file
diff --git a/packages/CredentialManager/res/drawable/ic_password_24.xml b/packages/CredentialManager/res/drawable/ic_password_24.xml
new file mode 100644
index 000000000000..8b24e882faf4
--- /dev/null
+++ b/packages/CredentialManager/res/drawable/ic_password_24.xml
@@ -0,0 +1,34 @@
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<vector
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ tools:ignore="VectorPath"
+ android:name="vector"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <group>
+ <clip-path android:pathData="M0,0h24v24h-24z"/>
+ <path android:fillColor="#4C463C" android:pathData="M8.46,10.29C8.27,10.1 8.03,10 7.75,10H7.5V8.75C7.5,7.98 7.23,7.33 6.7,6.8C6.17,6.27 5.52,6 4.75,6C3.98,6 3.33,6.27 2.8,6.8C2.27,7.33 2,7.98 2,8.75V10H1.75C1.47,10 1.23,10.1 1.04,10.29C0.85,10.48 0.75,10.72 0.75,11V16C0.75,16.28 0.85,16.52 1.04,16.71C1.23,16.9 1.47,17 1.75,17H7.75C8.03,17 8.27,16.9 8.46,16.71C8.65,16.52 8.75,16.28 8.75,16V11C8.75,10.72 8.65,10.48 8.46,10.29ZM6,10H3.5V8.75C3.5,8.4 3.62,8.1 3.86,7.86C4.1,7.62 4.4,7.5 4.75,7.5C5.1,7.5 5.4,7.62 5.64,7.86C5.88,8.1 6,8.4 6,8.75V10Z"/>
+ <path android:fillColor="#4C463C" android:pathData="M23.5,14H10.5V16H23.5V14Z"/>
+ <path android:fillColor="#4C463C" android:pathData="M22,12C22.828,12 23.5,11.328 23.5,10.5C23.5,9.672 22.828,9 22,9C21.172,9 20.5,9.672 20.5,10.5C20.5,11.328 21.172,12 22,12Z"/>
+ <path android:fillColor="#4C463C" android:pathData="M17,12C17.828,12 18.5,11.328 18.5,10.5C18.5,9.672 17.828,9 17,9C16.172,9 15.5,9.672 15.5,10.5C15.5,11.328 16.172,12 17,12Z"/>
+ <path android:fillColor="#4C463C" android:pathData="M12,12C12.828,12 13.5,11.328 13.5,10.5C13.5,9.672 12.828,9 12,9C11.172,9 10.5,9.672 10.5,10.5C10.5,11.328 11.172,12 12,12Z"/>
+ </group>
+</vector> \ No newline at end of file
diff --git a/packages/CredentialManager/res/values-af/strings.xml b/packages/CredentialManager/res/values-af/strings.xml
index 2aded3b1ba61..f0f040f4a866 100644
--- a/packages/CredentialManager/res/values-af/strings.xml
+++ b/packages/CredentialManager/res/values-af/strings.xml
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Ander wagwoordbestuurders"</string>
<string name="close_sheet" msgid="1393792015338908262">"Maak sigblad toe"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Gaan terug na die vorige bladsy"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Maak die Eiebewysbestuurder se handelingvoorstel toe wat onderaan die skerm verskyn"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Maak toe"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Gebruik jou gestoorde wagwoordsleutel vir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Gebruik jou gestoorde aanmelding vir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Kies ’n gestoorde aanmelding vir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Aanmeldopsies"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Vir <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Geslote wagwoordbestuurders"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Tik om te ontsluit"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Geen aanmeldinligting nie"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Geen aanmeldinligting in <xliff:g id="SOURCE">%1$s</xliff:g> nie"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Bestuur aanmeldings"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Van ’n ander toestel af"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Gebruik ’n ander toestel"</string>
diff --git a/packages/CredentialManager/res/values-am/strings.xml b/packages/CredentialManager/res/values-am/strings.xml
index 91a26c032360..730b0b020eeb 100644
--- a/packages/CredentialManager/res/values-am/strings.xml
+++ b/packages/CredentialManager/res/values-am/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"ቀጥል"</string>
<string name="string_more_options" msgid="7990658711962795124">"ተጨማሪ አማራጮች"</string>
<string name="string_learn_more" msgid="4541600451688392447">"የበለጠ ለመረዳት"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"የይለፍ ቃል አሳይ"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"የይለፍ ቃል ደብቅ"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"በይለፍ ቃል ይበልጥ ደህንነቱ የተጠበቀ"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"በይለፍ ቁልፎች ውስብስብ የይለፍ ቁልፎችን መፍጠር ወይም ማስታወስ አያስፈልግዎትም"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"የይለፍ ቁልፎች የእርስዎን የጣት አሻራ፣ መልክ ወይም የማያ ገጽ መቆለፊያ በመጠቀም የሚፈጥሯቸው የተመሰጠሩ ዲጂታል ቆልፎች ናቸው"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"ሌሎች የይለፍ ቃል አስተዳዳሪዎች"</string>
<string name="close_sheet" msgid="1393792015338908262">"ሉህን ዝጋ"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"ወደ ቀዳሚው ገፅ ይመለሱ"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"በማያ ገጹ ግርጌ ላይ የሚታየውን የመግቢያ ማስረጃ አስተዳዳሪ የእርምጃ ጥቆማን ዝጋ"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"ዝጋ"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"የተቀመጠ የይለፍ ቁልፍዎን ለ<xliff:g id="APP_NAME">%1$s</xliff:g> ይጠቀሙ?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"የተቀመጠ መግቢያዎን ለ<xliff:g id="APP_NAME">%1$s</xliff:g> ይጠቀሙ?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"ለ<xliff:g id="APP_NAME">%1$s</xliff:g> የተቀመጠ መግቢያ ይጠቀሙ"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"የመግቢያ አማራጮች"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"ለ<xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"የተቆለፉ የሚስጥር ቁልፍ አስተዳዳሪዎች"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"ለመክፈት መታ ያድርጉ"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"ምንም የመግቢያ ማስረጃ የለም"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> ውስጥ ምንም የመግቢያ መረጃ የለም"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"መግቢያዎችን ያስተዳድሩ"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"ከሌላ መሣሪያ"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"የተለየ መሣሪያ ይጠቀሙ"</string>
diff --git a/packages/CredentialManager/res/values-ar/strings.xml b/packages/CredentialManager/res/values-ar/strings.xml
index 8a88f3b4f99f..666f903514c6 100644
--- a/packages/CredentialManager/res/values-ar/strings.xml
+++ b/packages/CredentialManager/res/values-ar/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"متابعة"</string>
<string name="string_more_options" msgid="7990658711962795124">"خيارات إضافية"</string>
<string name="string_learn_more" msgid="4541600451688392447">"مزيد من المعلومات"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"عرض كلمة المرور"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"إخفاء كلمة المرور"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"توفير المزيد من الأمان باستخدام مفاتيح المرور"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"باستخدام مفاتيح المرور، لا حاجة لإنشاء كلمات مرور معقدة أو تذكّرها."</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"مفاتيح المرور هي مفاتيح رقمية مشفّرة يمكنك إنشاؤها باستخدام بصمة الإصبع أو التعرّف على الوجه أو قفل الشاشة."</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"خدمات مدراء كلمات المرور الأخرى"</string>
<string name="close_sheet" msgid="1393792015338908262">"إغلاق ورقة البيانات"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"العودة إلى الصفحة السابقة"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"إغلاق اقتراح إجراء \"مدير بيانات الاعتماد\" الذي يظهر في أسفل الشاشة"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"إغلاق"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"هل تريد استخدام مفتاح المرور المحفوظ لتطبيق \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"؟"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"هل تريد استخدام بيانات اعتماد تسجيل الدخول المحفوظة لتطبيق \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"؟"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"اختيار بيانات اعتماد تسجيل دخول محفوظة لـ \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"خيارات تسجيل الدخول"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"معلومات تسجيل دخول \"<xliff:g id="USERNAME">%1$s</xliff:g>\""</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"خدمات إدارة كلمات المرور المقفولة"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"انقر لفتح القفل."</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"ما مِن معلومات تسجيل دخول."</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"ليس هناك معلومات تسجيل دخول في <xliff:g id="SOURCE">%1$s</xliff:g>."</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"إداراة عمليات تسجيل الدخول"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"من جهاز آخر"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"استخدام جهاز مختلف"</string>
diff --git a/packages/CredentialManager/res/values-as/strings.xml b/packages/CredentialManager/res/values-as/strings.xml
index 8040c7aee2dd..6202de5dec45 100644
--- a/packages/CredentialManager/res/values-as/strings.xml
+++ b/packages/CredentialManager/res/values-as/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"অব্যাহত ৰাখক"</string>
<string name="string_more_options" msgid="7990658711962795124">"অধিক বিকল্প"</string>
<string name="string_learn_more" msgid="4541600451688392447">"অধিক জানক"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"পাছৱৰ্ড দেখুৱাওক"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"পাছৱৰ্ড লুকুৱাওক"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"পাছকীৰ জৰিয়তে অধিক সুৰক্ষিত"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"পাছকী ব্যৱহাৰ কৰিলে আপুনি জটিল পাছৱৰ্ড সৃষ্টি কৰিব অথবা মনত ৰাখিব নালাগে"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"পাছকীসমূহ হৈছে আপুনি আপোনাৰ ফিংগাৰপ্ৰিণ্ট, মুখাৱয়ব অথবা স্ক্ৰীন লক ব্যৱহাৰ কৰি সৃষ্টি কৰা এনক্ৰিপ্ট কৰা ডিজিটেল চাবি"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"অন্য পাছৱৰ্ড পৰিচালক"</string>
<string name="close_sheet" msgid="1393792015338908262">"শ্বীট বন্ধ কৰক"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"পূৰ্বৱৰ্তী পৃষ্ঠালৈ ঘূৰি যাওক"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"স্ক্ৰীনখনৰ একেবাৰে তলত প্ৰদৰ্শিত ক্ৰিডেনশ্বিয়েল পৰিচালকৰ কাৰ্য সম্পৰ্কীয় পৰামৰ্শ বন্ধ কৰক"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"বন্ধ কৰক"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাবে আপোনাৰ ছেভ হৈ থকা পাছকী ব্যৱহাৰ কৰিবনে?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাবে আপোনাৰ ছেভ হৈ থকা ছাইন ইন তথ্য ব্যৱহাৰ কৰিবনে?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাবে ছেভ হৈ থকা এটা ছাইন ইন বাছনি কৰক"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"ছাইন ইনৰ বিকল্প"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g>ৰ বাবে"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"লক হৈ থকা পাছৱৰ্ড পৰিচালক"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"আনলক কৰিবলৈ টিপক"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"ছাইন ইনৰ তথ্য নাই"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g>ত কোনো ছাইন ইনৰ তথ্য নাই"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"ছাইন ইন পৰিচালনা কৰক"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"অন্য এটা ডিভাইচৰ পৰা"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"অন্য এটা ডিভাইচ ব্যৱহাৰ কৰক"</string>
diff --git a/packages/CredentialManager/res/values-az/strings.xml b/packages/CredentialManager/res/values-az/strings.xml
index dd1db6f8fc3b..2481a5cf8d80 100644
--- a/packages/CredentialManager/res/values-az/strings.xml
+++ b/packages/CredentialManager/res/values-az/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Davam edin"</string>
<string name="string_more_options" msgid="7990658711962795124">"Digər seçimlər"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Ətraflı məlumat"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"Parolu göstərin"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Parolu gizlədin"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Giriş açarları ilə daha təhlükəsiz"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Giriş açarları ilə mürəkkəb parollar yaratmağa və ya yadda saxlamağa ehtiyac yoxdur"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Giriş açarları barmaq izi, üz və ya ekran kilidindən istifadə edərək yaratdığınız şifrələnmiş rəqəmsal açarlardır"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Digər parol menecerləri"</string>
<string name="close_sheet" msgid="1393792015338908262">"Səhifəni bağlayın"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Əvvəlki səhifəyə qayıdın"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Ekranın aşağı hissəsində görünən Giriş Məlumatları Meneceri əməliyyat təklifini bağlayın"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Bağlayın"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün yadda saxlanmış giriş açarı istifadə edilsin?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün yadda saxlanmış girişdən istifadə edilsin?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün yadda saxlanmış girişi seçin"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Giriş seçimləri"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g> üçün"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Kilidli parol menecerləri"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Kiliddən çıxarmaq üçün toxunun"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Giriş məlumatı yoxdur"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> giriş məlumatı mövcud deyil"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Girişləri idarə edin"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Başqa cihazdan"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Başqa cihaz istifadə edin"</string>
diff --git a/packages/CredentialManager/res/values-b+sr+Latn/strings.xml b/packages/CredentialManager/res/values-b+sr+Latn/strings.xml
index 10f80fe71a4b..1e7e92e1efc1 100644
--- a/packages/CredentialManager/res/values-b+sr+Latn/strings.xml
+++ b/packages/CredentialManager/res/values-b+sr+Latn/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Nastavi"</string>
<string name="string_more_options" msgid="7990658711962795124">"Još opcija"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Saznajte više"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"Prikažite lozinku"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Sakrijte lozinku"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Bezbednije uz pristupne kodove"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Uz pristupne kodove nema potrebe da pravite ili pamtite složene lozinke"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Pristupni kodovi su šifrovani digitalni kodovi koje pravite pomoću otiska prsta, lica ili zaključavanja ekrana"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Drugi menadžeri lozinki"</string>
<string name="close_sheet" msgid="1393792015338908262">"Zatvorite tabelu"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Vratite se na prethodnu stranicu"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Zatvorite predlog za radnju Menadžera akreditiva koji se prikazuje u dnu ekrana"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Zatvorite"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Želite da koristite sačuvani pristupni kôd za: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Želite da koristite sačuvane podatke za prijavljivanje za: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Odaberite sačuvano prijavljivanje za: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Opcije za prijavljivanje"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Za: <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Menadžeri zaključanih lozinki"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Dodirnite da biste otključali"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Nema podataka za prijavljivanje"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Nema podataka za prijavljivanje u: <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Upravljajte prijavljivanjima"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Sa drugog uređaja"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Koristi drugi uređaj"</string>
diff --git a/packages/CredentialManager/res/values-be/strings.xml b/packages/CredentialManager/res/values-be/strings.xml
index 39c820011d2b..f89454a58a53 100644
--- a/packages/CredentialManager/res/values-be/strings.xml
+++ b/packages/CredentialManager/res/values-be/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Далей"</string>
<string name="string_more_options" msgid="7990658711962795124">"Дадатковыя параметры"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Даведацца больш"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"Паказаць пароль"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Схаваць пароль"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"З ключамі доступу вам будзе бяспечней."</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Дзякуючы ключам доступу вам не трэба ствараць і запамінаць складаныя паролі."</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Ключы доступу – гэта зашыфраваныя лючбавыя ключы, створаныя вамі з дапамогай адбітка пальца, твару ці блакіроўкі экрана."</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Іншыя спосабы ўваходу"</string>
<string name="close_sheet" msgid="1393792015338908262">"Закрыць аркуш"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Вярнуцца да папярэдняй старонкі"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Закрыць прапанову ад Менеджара ўліковых даных унізе экрана"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Закрыць"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Скарыстаць захаваны ключ доступу для праграмы \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Скарыстаць захаваныя спосабы ўваходу для праграмы \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Выберыце захаваны спосаб уваходу для праграмы \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Спосабы ўваходу"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Для карыстальніка <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Заблакіраваныя спосабы ўваходу"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Націсніце, каб разблакіраваць"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Няма даных для ўваходу"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Ва ўліковым запісе <xliff:g id="SOURCE">%1$s</xliff:g> адсутнічае інфармацыя для ўваходу"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Кіраваць спосабамі ўваходу"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"З іншай прылады"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Скарыстаць іншую прыладу"</string>
diff --git a/packages/CredentialManager/res/values-bg/strings.xml b/packages/CredentialManager/res/values-bg/strings.xml
index c2923b8b9551..530c8230d18b 100644
--- a/packages/CredentialManager/res/values-bg/strings.xml
+++ b/packages/CredentialManager/res/values-bg/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Напред"</string>
<string name="string_more_options" msgid="7990658711962795124">"Още опции"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Научете повече"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"Показване на паролата"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Скриване на паролата"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"По-сигурно с помощта на кодове за достъп"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Когато използвате кодове за достъп, не е необходимо да създавате, нито да помните сложни пароли"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Кодовете за достъп са шифровани дигитални ключове, които създавате посредством отпечатъка, лицето си или опцията си за заключване на екрана"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Други мениджъри на пароли"</string>
<string name="close_sheet" msgid="1393792015338908262">"Затваряне на таблицата"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Назад към предишната страница"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Затваряне на предложението за действие от мениджъра за идентификационни данни, което се показва в долната част на екрана"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Затваряне"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Да се използва ли запазеният ви код за достъп за <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Да се използват ли запазените ви данни за вход за <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Изберете запазени данни за вход за <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Опции за влизане в профила"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"За <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Заключени мениджъри на пароли"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Докоснете, за да отключите"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Няма данни за вход"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> не съдържа данни за вход"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Управление на данните за вход"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"От друго устройство"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Използване на друго устройство"</string>
diff --git a/packages/CredentialManager/res/values-bn/strings.xml b/packages/CredentialManager/res/values-bn/strings.xml
index 6ede6933d7c1..c3f0e4b264b1 100644
--- a/packages/CredentialManager/res/values-bn/strings.xml
+++ b/packages/CredentialManager/res/values-bn/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"চালিয়ে যান"</string>
<string name="string_more_options" msgid="7990658711962795124">"আরও বিকল্প"</string>
<string name="string_learn_more" msgid="4541600451688392447">"আরও জানুন"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"পাসওয়ার্ড দেখুন"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"পাসওয়ার্ড লুকান"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"\'পাসকী\'-এর সাথে সুরক্ষিত"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"\'পাসকী\' ব্যবহার করলে জটিল পাসওয়ার্ড তৈরি করার বা মনে রাখার কোনও প্রয়োজন নেই"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"আপনার ফিঙ্গারপ্রিন্ট, ফেস মডেল বা \'স্ক্রিন লক\' ব্যবহার করে আপনি যে এনক্রিপটেড ডিজিটাল \'কী\' তৈরি করেন সেগুলিই হল \'পাসকী\'"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"অন্যান্য Password Manager"</string>
<string name="close_sheet" msgid="1393792015338908262">"শিট বন্ধ করুন"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"আগের পৃষ্ঠায় ফিরে যান"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"স্ক্রিনের নিচে দেখানো Credential Manager অ্যাকশন সংক্রান্ত সাজেশন বন্ধ করুন"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"বন্ধ করুন"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g>-এর জন্য আপনার সেভ করা পাসকী ব্যবহার করবেন?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g>-এর জন্য আপনার সেভ করা সাইন-ইন সম্পর্কিত ক্রেডেনশিয়াল ব্যবহার করবেন?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g>-এর জন্য সাইন-ইন করা সম্পর্কিত ক্রেডেনশিয়াল বেছে নিন"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"সাইন-ইন করার বিকল্প"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g>-এর জন্য"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"লক করা Password Manager"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"আনলক করতে ট্যাপ করুন"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"সাইন-ইন সম্পর্কিত তথ্য নেই"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g>-এ সাইন-ইন সম্পর্কিত কোনও তথ্য নেই"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"সাইন-ইন করার ক্রেডেনশিয়াল ম্যানেজ করুন"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"অন্য ডিভাইস থেকে"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"আলাদা ডিভাইস ব্যবহার করুন"</string>
diff --git a/packages/CredentialManager/res/values-bs/strings.xml b/packages/CredentialManager/res/values-bs/strings.xml
index ee42d75edabb..d98061432492 100644
--- a/packages/CredentialManager/res/values-bs/strings.xml
+++ b/packages/CredentialManager/res/values-bs/strings.xml
@@ -6,8 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Nastavi"</string>
<string name="string_more_options" msgid="7990658711962795124">"Više opcija"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Saznajte više"</string>
- <string name="content_description_show_password" msgid="3283502010388521607">"Prikaži zaporku"</string>
- <string name="content_description_hide_password" msgid="6841375971631767996">"Sakrij zaporku"</string>
+ <string name="content_description_show_password" msgid="3283502010388521607">"Prikaži lozinku"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Sakrij lozinku"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Sigurniji ste uz pristupne ključeve"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Uz pristupne ključeve ne morate kreirati ili pamtiti složene lozinke"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Pristupni ključevi su šifrirani digitalni ključevi koje kreirate pomoću otiska prsta, lica ili zaključavanja ekrana"</string>
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Drugi upravitelji lozinki"</string>
<string name="close_sheet" msgid="1393792015338908262">"Zatvaranje tabele"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Povratak na prethodnu stranicu"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Zatvaranje prijedloga radnje Upravitelja akreditiva koji se prikazuje na dnu ekrana"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Zatvaranje"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Koristiti sačuvani pristupni ključ za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Koristiti sačuvanu prijavu za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Odaberite sačuvanu prijavu za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Opcije prijave"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Za osobu <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Zaključani upravitelji lozinki"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Dodirnite da otključate"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Nema podataka za prijavu"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Nema informacija za prijavu na <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Upravljajte prijavama"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"S drugog uređaja"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Upotrijebite drugi uređaj"</string>
diff --git a/packages/CredentialManager/res/values-ca/strings.xml b/packages/CredentialManager/res/values-ca/strings.xml
index 6b898e1cae41..afbfe505d9b0 100644
--- a/packages/CredentialManager/res/values-ca/strings.xml
+++ b/packages/CredentialManager/res/values-ca/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Continua"</string>
<string name="string_more_options" msgid="7990658711962795124">"Més opcions"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Més informació"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"Mostra la contrasenya"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Amaga la contrasenya"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Més seguretat amb les claus d\'accés"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Amb les claus d\'accés, no cal que creïs ni recordis contrasenyes difícils"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Les claus d\'accés són claus digitals encriptades que pots crear amb la teva cara, l\'empremta digital o el bloqueig de pantalla"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Altres gestors de contrasenyes"</string>
<string name="close_sheet" msgid="1393792015338908262">"Tanca el full"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Torna a la pàgina anterior"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Tanca el suggeriment d\'acció del Gestor de credencials que es mostra a la part inferior de la pantalla"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Tanca"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Vols utilitzar la clau d\'accés desada per a <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Vols utilitzar l\'inici de sessió desat per a <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Tria un inici de sessió desat per a <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Opcions d\'inici de sessió"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Per a <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Gestors de contrasenyes bloquejats"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Toca per desbloquejar"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Sense informació d\'inici de sessió"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Sense informació d\'inici de sessió per a <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Gestiona els inicis de sessió"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Des d\'un altre dispositiu"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Utilitza un dispositiu diferent"</string>
diff --git a/packages/CredentialManager/res/values-cs/strings.xml b/packages/CredentialManager/res/values-cs/strings.xml
index 00c037bf6944..72e5525e220b 100644
--- a/packages/CredentialManager/res/values-cs/strings.xml
+++ b/packages/CredentialManager/res/values-cs/strings.xml
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Další správci hesel"</string>
<string name="close_sheet" msgid="1393792015338908262">"Zavřít list"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Zpět na předchozí stránku"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Zavřít návrh akce Správce oprávnění zobrazený ve spodní části obrazovky"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Zavřít"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Použít uložený přístupový klíč pro aplikaci <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Použít uložené přihlášení pro aplikaci <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Vyberte uložené přihlášení pro <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Možnosti přihlašování"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Pro uživatele <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Uzamčení správci hesel"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Klepnutím odemknete"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Žádné informace o přihlášení"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> neobsahuje žádné přihlašovací údaje"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Spravovat přihlášení"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Z jiného zařízení"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Použít jiné zařízení"</string>
diff --git a/packages/CredentialManager/res/values-da/strings.xml b/packages/CredentialManager/res/values-da/strings.xml
index 7583b7cb3c6f..148bba83be33 100644
--- a/packages/CredentialManager/res/values-da/strings.xml
+++ b/packages/CredentialManager/res/values-da/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Fortsæt"</string>
<string name="string_more_options" msgid="7990658711962795124">"Flere valgmuligheder"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Få flere oplysninger"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"Vis adgangskode"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Skjul adgangskode"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Øget beskyttelse med adgangsnøgler"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Når du bruger adgangsnøgler, behøver du ikke at oprette eller huske avancerede adgangskoder"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Adgangsnøgler er krypterede digitale nøgler, som du opretter ved hjælp af fingeraftryk, ansigtsgenkendelse eller skærmlås"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Andre adgangskodeadministratorer"</string>
<string name="close_sheet" msgid="1393792015338908262">"Luk arket"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Gå tilbage til den forrige side"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Luk handlingsforslaget for Loginstyring, som vises nederst på skærmen"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Luk"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Vil du bruge din gemte adgangsnøgle til <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Vil du bruge din gemte loginmetode til <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Vælg en gemt loginmetode til <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Valgmuligheder for login"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"For <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Låste adgangskodeadministratorer"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Tryk for at låse op"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Ingen loginoplysninger"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Der er ingen loginoplysninger i <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Administrer loginmetoder"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Fra en anden enhed"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Brug en anden enhed"</string>
diff --git a/packages/CredentialManager/res/values-de/strings.xml b/packages/CredentialManager/res/values-de/strings.xml
index 0946556775d3..103a3d2edc10 100644
--- a/packages/CredentialManager/res/values-de/strings.xml
+++ b/packages/CredentialManager/res/values-de/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Weiter"</string>
<string name="string_more_options" msgid="7990658711962795124">"Weitere Optionen"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Weitere Informationen"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"Passwort einblenden"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Passwort ausblenden"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Mehr Sicherheit mit Passkeys"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Mit Passkeys musst du keine komplizierten Passwörter erstellen oder dir merken"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Passkeys sind verschlüsselte digitale Schlüssel, die du mithilfe deines Fingerabdrucks, Gesichts oder deiner Displaysperre erstellst"</string>
@@ -49,7 +47,10 @@
<string name="other_password_manager" msgid="565790221427004141">"Andere Passwortmanager"</string>
<string name="close_sheet" msgid="1393792015338908262">"Tabellenblatt schließen"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Zurück zur vorherigen Seite"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Den Vorschlag des Anmeldedaten-Managers unten auf dem Bildschirm schließen"</string>
+ <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <skip />
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Gespeicherten Passkey für <xliff:g id="APP_NAME">%1$s</xliff:g> verwenden?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Gespeicherte Anmeldedaten für <xliff:g id="APP_NAME">%1$s</xliff:g> verwenden?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Gespeicherte Anmeldedaten für <xliff:g id="APP_NAME">%1$s</xliff:g> auswählen"</string>
@@ -59,9 +60,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Anmeldeoptionen"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Für <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Gesperrte Passwortmanager"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Zum Entsperren tippen"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Keine Anmeldedaten"</string>
+ <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
<skip />
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Anmeldedaten verwalten"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Von einem anderen Gerät"</string>
diff --git a/packages/CredentialManager/res/values-el/strings.xml b/packages/CredentialManager/res/values-el/strings.xml
index 909ec9755fff..8cb3f2816a26 100644
--- a/packages/CredentialManager/res/values-el/strings.xml
+++ b/packages/CredentialManager/res/values-el/strings.xml
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Άλλοι διαχειριστές κωδικών πρόσβασης"</string>
<string name="close_sheet" msgid="1393792015338908262">"Κλείσιμο φύλλου"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Επιστροφή στην προηγούμενη σελίδα"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Κλείσιμο της πρότασης για ενέργεια από το Credential Manager που εμφανίζεται στο κάτω μέρος της οθόνης"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Κλείσιμο"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Να χρησιμοποιηθεί το αποθηκευμένο κλειδί πρόσβασης για την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>;"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Να χρησιμοποιηθούν τα αποθηκευμένα στοιχεία σύνδεσης για την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>;"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Επιλογή αποθηκευμένων στοιχείων σύνδεσης για την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Επιλογές σύνδεσης"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Για τον χρήστη <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Κλειδωμένοι διαχειριστές κωδικών πρόσβασης"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Πατήστε για ξεκλείδωμα"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Δεν υπάρχουν στοιχεία σύνδεσης"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Δεν υπάρχουν στοιχεία σύνδεσης στο <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Διαχείριση στοιχείων σύνδεσης"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Από άλλη συσκευή"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Χρήση διαφορετικής συσκευής"</string>
diff --git a/packages/CredentialManager/res/values-en-rAU/strings.xml b/packages/CredentialManager/res/values-en-rAU/strings.xml
index 42f61b994fe4..ffba3ce6727b 100644
--- a/packages/CredentialManager/res/values-en-rAU/strings.xml
+++ b/packages/CredentialManager/res/values-en-rAU/strings.xml
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Other password managers"</string>
<string name="close_sheet" msgid="1393792015338908262">"Close sheet"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Go back to the previous page"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Close the Credential Manager action suggestion appearing at the bottom of the screen"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Close"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Use your saved passkey for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Use your saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Choose a saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Sign-in options"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"For <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Locked password managers"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Tap to unlock"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"No sign-in info"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"No sign-in info in <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Manage sign-ins"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"From another device"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Use a different device"</string>
diff --git a/packages/CredentialManager/res/values-en-rCA/strings.xml b/packages/CredentialManager/res/values-en-rCA/strings.xml
index 24d6bf29981a..32bbe449dde8 100644
--- a/packages/CredentialManager/res/values-en-rCA/strings.xml
+++ b/packages/CredentialManager/res/values-en-rCA/strings.xml
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Other password managers"</string>
<string name="close_sheet" msgid="1393792015338908262">"Close sheet"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Go back to the previous page"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Close the Credential Manager action suggestion appearing at the bottom of the screen"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Close"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Use your saved passkey for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Use your saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Choose a saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Sign-in options"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"For <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Locked password managers"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Tap to unlock"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"No sign-in info"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"No sign-in info in <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Manage sign-ins"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"From another device"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Use a different device"</string>
diff --git a/packages/CredentialManager/res/values-en-rGB/strings.xml b/packages/CredentialManager/res/values-en-rGB/strings.xml
index 42f61b994fe4..ffba3ce6727b 100644
--- a/packages/CredentialManager/res/values-en-rGB/strings.xml
+++ b/packages/CredentialManager/res/values-en-rGB/strings.xml
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Other password managers"</string>
<string name="close_sheet" msgid="1393792015338908262">"Close sheet"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Go back to the previous page"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Close the Credential Manager action suggestion appearing at the bottom of the screen"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Close"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Use your saved passkey for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Use your saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Choose a saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Sign-in options"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"For <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Locked password managers"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Tap to unlock"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"No sign-in info"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"No sign-in info in <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Manage sign-ins"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"From another device"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Use a different device"</string>
diff --git a/packages/CredentialManager/res/values-en-rIN/strings.xml b/packages/CredentialManager/res/values-en-rIN/strings.xml
index 42f61b994fe4..ffba3ce6727b 100644
--- a/packages/CredentialManager/res/values-en-rIN/strings.xml
+++ b/packages/CredentialManager/res/values-en-rIN/strings.xml
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Other password managers"</string>
<string name="close_sheet" msgid="1393792015338908262">"Close sheet"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Go back to the previous page"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Close the Credential Manager action suggestion appearing at the bottom of the screen"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Close"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Use your saved passkey for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Use your saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Choose a saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Sign-in options"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"For <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Locked password managers"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Tap to unlock"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"No sign-in info"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"No sign-in info in <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Manage sign-ins"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"From another device"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Use a different device"</string>
diff --git a/packages/CredentialManager/res/values-en-rXC/strings.xml b/packages/CredentialManager/res/values-en-rXC/strings.xml
index f646b490bd66..49db2fc56ee7 100644
--- a/packages/CredentialManager/res/values-en-rXC/strings.xml
+++ b/packages/CredentialManager/res/values-en-rXC/strings.xml
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‏‎‏‏‏‎‎‏‏‎‏‎‏‎‏‏‎‏‏‎‏‏‎‎‎‏‎‏‏‏‏‎‏‎‎‏‎‏‏‏‎‏‏‎‏‎Other password managers‎‏‎‎‏‎"</string>
<string name="close_sheet" msgid="1393792015338908262">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‏‎‏‎‏‎‏‏‏‏‎‏‏‏‏‏‎‎‏‏‏‎‏‎‎‎‎‎‎‏‏‎‏‎‎‎‎‏‏‎‏‎‎‏‎‏‎‏‎‎‏‏‎‎‏‏‎‎Close sheet‎‏‎‎‏‎"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‎‏‏‎‏‏‏‏‎‏‎‏‎‎‎‎‎‏‎‎‏‏‏‏‎‎‎‎‏‏‏‏‏‏‏‎‏‎‎‏‏‏‎‏‏‏‏‏‏‎‎‏‏‏‏‎‎‎Go back to the previous page‎‏‎‎‏‎"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‏‏‏‏‏‎‎‎‎‎‏‎‎‎‎‏‏‏‏‏‎‎‎‏‎‎‏‏‏‎‏‎‏‎‎‏‎‏‎‎‎‏‏‏‎‏‎‎‎‎‎‎‎‎‎Close the Credential Manager action suggestion appearing at the bottom of the screen‎‏‎‎‏‎"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‎‎‏‎‏‎‏‎‏‏‎‏‎‏‎‎‎‎‎‎‎‏‎‏‏‎‎‏‎‏‎‏‏‎‎‎‎‏‎‏‎‏‎‏‏‏‎‎‏‎‏‏‏‎Close‎‏‎‎‏‎"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‎‏‏‎‎‏‏‏‎‎‎‏‎‏‎‏‏‏‎‏‎‎‎‎‎‏‏‎‎‏‏‎‎‏‏‏‏‏‎‎‏‏‏‏‎‎‎‎‎‎‏‏‏‎Use your saved passkey for ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‏‎‏‎‎‎‏‎‏‎‏‎‏‏‏‎‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‎‎‎‎‏‎‏‏‏‏‎‏‏‎‎‎‏‏‏‏‎‏‎‎‎Use your saved sign-in for ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‏‏‏‎‎‏‎‏‏‏‎‎‏‎‎‎‏‏‏‏‏‎‏‎‏‎‎‏‎‎‏‎‏‎‏‎‏‏‎‎‏‎‏‏‎‎‏‎‏‎‎‎‎‏‎‏‎Choose a saved sign-in for ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‏‎‎‎‎‏‎‏‏‎‏‏‎‎‏‎‎‎‎‎‎‏‎‎‏‎‏‎‏‎‏‏‎‏‎‏‎‎‏‎‏‎‏‏‏‎‎‎‏‎‎‏‏‎‎‏‎‎Sign-in options‎‏‎‎‏‎"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‎‏‏‏‎‎‏‏‎‎‏‎‏‎‎‎‏‎‏‎‎‏‏‏‏‎‎‎‏‎‏‎‎‏‎‎‏‏‎‏‎‎‎‎For ‎‏‎‎‏‏‎<xliff:g id="USERNAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‎‎‎‎‎‎‏‏‏‏‏‎‎‎‏‎‏‎‏‏‎‏‏‏‎‏‏‏‏‏‎‎‎‏‎‏‏‏‏‎‎‎‎‏‏‎‎‏‎‎‎Locked password managers‎‏‎‎‏‎"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎‏‎‏‏‏‏‎‎‏‎‎‏‎‏‎‏‏‏‎‏‎‏‎‎‏‎‏‎‎‏‎‎‏‎‎‎‏‏‎‏‎‏‎‎‎‏‏‎‎‏‎‎‎‏‎Tap to unlock‎‏‎‎‏‎"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‏‏‎‎‏‏‎‏‏‎‎‎‎‏‏‎‏‎‏‎‎‏‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‏‎‎‎‎‎‎‏‏‏‏‎‏‎‏‎No sign-in info‎‏‎‎‏‎"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‏‎‏‎‎‏‏‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‏‎‎‎‏‏‏‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‏‎‎‏‎‎‎No sign-in info in ‎‏‎‎‏‏‎<xliff:g id="SOURCE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‏‎‎‎‏‎‏‎‏‎‎‎‏‎‎‏‏‏‎‎‏‏‏‎‏‏‏‎‎‏‏‏‏‎‎‎‎‏‏‏‏‎‎‎‏‏‏‎‏‎‏‏‏‎‎Manage sign-ins‎‏‎‎‏‎"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‏‎‎‎‎‏‏‏‏‎‎‎‎‏‏‎‎‎‎‎‏‎‏‏‎‏‏‎‏‏‎‎‏‎‎‏‏‏‏‏‎‏‏‎‏‏‏‏‎‏‎‎‎‎From another device‎‏‎‎‏‎"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‏‎‎‎‏‏‏‎‏‏‏‎‎‎‏‏‏‏‎‏‎‎‏‏‏‏‎‎‎‏‎‏‏‏‎‏‏‎‏‎‏‎‏‎‎‏‎‏‏‏‏‎‏‎Use a different device‎‏‎‎‏‎"</string>
diff --git a/packages/CredentialManager/res/values-es-rUS/strings.xml b/packages/CredentialManager/res/values-es-rUS/strings.xml
index ec00eb6d44fb..91afadc9df11 100644
--- a/packages/CredentialManager/res/values-es-rUS/strings.xml
+++ b/packages/CredentialManager/res/values-es-rUS/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Continuar"</string>
<string name="string_more_options" msgid="7990658711962795124">"Más opciones"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Más información"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"Mostrar contraseña"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Ocultar contraseña"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Más seguridad con llaves de acceso"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Con las llaves de acceso, no es necesario crear ni recordar contraseñas complejas"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Las llaves de acceso son claves digitales encriptadas que puedes crear usando tu huella dactilar, rostro o bloqueo de pantalla"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Otros administradores de contraseñas"</string>
<string name="close_sheet" msgid="1393792015338908262">"Cerrar hoja"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Volver a la página anterior"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Cierra la sugerencia de acción del Administrador de credenciales que aparece en la parte inferior de la pantalla"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Cerrar"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"¿Quieres usar tu llave de acceso guardada para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"¿Quieres usar tu acceso guardado para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Elige un acceso guardado para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Opciones de acceso"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Para <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Administradores de contraseñas bloqueados"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Presiona para desbloquear"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"No hay información de acceso"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"No hay información de acceso en <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Administrar accesos"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Desde otro dispositivo"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Usar otra voz"</string>
diff --git a/packages/CredentialManager/res/values-es/strings.xml b/packages/CredentialManager/res/values-es/strings.xml
index 94eaffd71e21..b1ff41411138 100644
--- a/packages/CredentialManager/res/values-es/strings.xml
+++ b/packages/CredentialManager/res/values-es/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Continuar"</string>
<string name="string_more_options" msgid="7990658711962795124">"Más opciones"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Más información"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"Mostrar contraseña"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Ocultar contraseña"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Más seguridad con las llaves de acceso"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Con las llaves de acceso, no tienes que crear ni recordar contraseñas complicadas"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Las llaves de acceso son claves digitales cifradas que puedes crear con tu huella digital, cara o bloqueo de pantalla"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Otros gestores de contraseñas"</string>
<string name="close_sheet" msgid="1393792015338908262">"Cerrar hoja"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Volver a la página anterior"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Cierra la sugerencia de acción del Gestor de credenciales de la parte inferior de la pantalla"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Cerrar"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"¿Usar la llave de acceso guardada para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"¿Usar el inicio de sesión guardado para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Elige un inicio de sesión guardado para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Opciones de inicio de sesión"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Para <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Gestores de contraseñas bloqueados"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Tocar para desbloquear"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"No hay información de inicio de sesión"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"No hay información de inicio de sesión en <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Gestionar inicios de sesión"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"De otro dispositivo"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Usar otro dispositivo"</string>
diff --git a/packages/CredentialManager/res/values-et/strings.xml b/packages/CredentialManager/res/values-et/strings.xml
index eb5071101bed..5bacae35d09c 100644
--- a/packages/CredentialManager/res/values-et/strings.xml
+++ b/packages/CredentialManager/res/values-et/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Jätka"</string>
<string name="string_more_options" msgid="7990658711962795124">"Rohkem valikuid"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Lisateave"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"Kuva parool"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Peida parool"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Pääsuvõtmed suurendavad turvalisust"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Pääsuvõtmetega ei pea te looma ega meelde jätma keerukaid paroole"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Pääsuvõtmed on digitaalsed krüpteeritud võtmed, mille loote sõrmejälje, näo või ekraanilukuga"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Muud paroolihaldurid"</string>
<string name="close_sheet" msgid="1393792015338908262">"Sule leht"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Minge tagasi eelmisele lehele"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Ekraanikuva allosas kuvatud mandaatide halduri toimingusoovituse sulgemine"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Sule"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Kas kasutada rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> jaoks salvestatud pääsuvõtit?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Kas kasutada rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> jaoks salvestatud sisselogimisandmeid?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Valige rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> jaoks salvestatud sisselogimisandmed"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Sisselogimise valikud"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Kasutajale <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Lukustatud paroolihaldurid"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Avamiseks puudutage"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Sisselogimisteave puudub"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Kontol <xliff:g id="SOURCE">%1$s</xliff:g> puudub sisselogimisteave"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Sisselogimisandmete haldamine"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Muus seadmes"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Kasuta teist seadet"</string>
diff --git a/packages/CredentialManager/res/values-eu/strings.xml b/packages/CredentialManager/res/values-eu/strings.xml
index 985d8977f085..9052bd2e0945 100644
--- a/packages/CredentialManager/res/values-eu/strings.xml
+++ b/packages/CredentialManager/res/values-eu/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Egin aurrera"</string>
<string name="string_more_options" msgid="7990658711962795124">"Aukera gehiago"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Lortu informazio gehiago"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"Erakutsi pasahitza"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Ezkutatu pasahitza"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Sarbide-gako seguruagoak"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Sarbide-gakoei esker, ez duzu pasahitz konplexurik sortu edo gogoratu beharrik"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Hatz-marka, aurpegia edo pantailaren blokeoa erabilita sortzen dituzun giltza digital enkriptatuak dira sarbide-gakoak"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Beste pasahitz-kudeatzaile batzuk"</string>
<string name="close_sheet" msgid="1393792015338908262">"Itxi orria"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Itzuli aurreko orrira"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Itxi pantailaren behealdean agertzen den kredentzialen kudeatzailearen ekintza iradokia"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Itxi"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikaziorako gorde duzun sarbide-gakoa erabili nahi duzu?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikaziorako gorde dituzun kredentzialak erabili nahi dituzu?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Aukeratu <xliff:g id="APP_NAME">%1$s</xliff:g> aplikaziorako gorde dituzun kredentzialak"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Saioa hasteko aukerak"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g> erabiltzailearenak"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Blokeatutako pasahitz-kudeatzaileak"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Desblokeatzeko, sakatu hau"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Ez dago saioa hasteko informaziorik"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Ez dago saioa hasteko informaziorik <xliff:g id="SOURCE">%1$s</xliff:g> kontuan"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Kudeatu kredentzialak"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Beste gailu batean gordetakoak"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Erabili beste gailu bat"</string>
diff --git a/packages/CredentialManager/res/values-fa/strings.xml b/packages/CredentialManager/res/values-fa/strings.xml
index a24e6cb2eb27..9e01bf0cef6b 100644
--- a/packages/CredentialManager/res/values-fa/strings.xml
+++ b/packages/CredentialManager/res/values-fa/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"ادامه"</string>
<string name="string_more_options" msgid="7990658711962795124">"گزینه‌های بیشتر"</string>
<string name="string_learn_more" msgid="4541600451688392447">"بیشتر بدانید"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"نمایش گذرواژه"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"پنهان کردن گذرواژه"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"فضایی ایمن‌تر با گذرکلید"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"با گذرکلیدها، لازم نیست گذرواژه پیچیده‌ای بسازید یا آن را به‌خاطر بسپارید"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"گذرکلیدها کلیدهای دیجیتالی رمزگذاری‌شده‌ای هستند که بااستفاده از اثر انگشت، چهره، یا قفل صفحه ایجاد می‌کنید"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"دیگر مدیران گذرواژه"</string>
<string name="close_sheet" msgid="1393792015338908262">"بستن برگ"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"برگشتن به صفحه قبلی"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"بستن پیشنهاد کنش «مدیر اطلاعات اعتباری» که در پایین صفحه نشان داده می‌شود"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"بستن"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"گذرکلید ذخیره‌شده برای <xliff:g id="APP_NAME">%1$s</xliff:g> استفاده شود؟"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"ورود به سیستم ذخیره‌شده برای <xliff:g id="APP_NAME">%1$s</xliff:g> استفاده شود؟"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"انتخاب ورود به سیستم ذخیره‌شده برای <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"گزینه‌های ورود به سیستم"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"برای <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"مدیران گذرواژه قفل‌شده"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"برای باز کردن قفل ضربه بزنید"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"اطلاعات ورود به سیستم موجود نیست"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"هیچ اطلاعات ورود به سیستمی در <xliff:g id="SOURCE">%1$s</xliff:g> وجود ندارد"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"مدیریت ورود به سیستم‌ها"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"از دستگاهی دیگر"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"استفاده از دستگاه دیگری"</string>
diff --git a/packages/CredentialManager/res/values-fi/strings.xml b/packages/CredentialManager/res/values-fi/strings.xml
index 73a964a19225..268dbca45a58 100644
--- a/packages/CredentialManager/res/values-fi/strings.xml
+++ b/packages/CredentialManager/res/values-fi/strings.xml
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Muut salasanojen ylläpitotyökalut"</string>
<string name="close_sheet" msgid="1393792015338908262">"Sulje taulukko"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Takaisin edelliselle sivulle"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Sulje näytön alaosassa näkyvä Kirjautumistietojen hallinta ‑toiminnon ehdotus"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Sulje"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Käytetäänkö tallennettua avainkoodiasi täällä: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Käytetäänkö tallennettuja kirjautumistietoja täällä: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Valitse tallennetut kirjautumistiedot (<xliff:g id="APP_NAME">%1$s</xliff:g>)"</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Kirjautumisvaihtoehdot"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Käyttäjä: <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Lukitut salasanojen ylläpitotyökalut"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Avaa napauttamalla"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Ei kirjautumistietoja"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Ei kirjautumistietoja (<xliff:g id="SOURCE">%1$s</xliff:g>)"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Muuta kirjautumistietoja"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Toiselta laitteelta"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Käytä toista laitetta"</string>
diff --git a/packages/CredentialManager/res/values-fr-rCA/strings.xml b/packages/CredentialManager/res/values-fr-rCA/strings.xml
index c79e5004d893..d5fd858a7867 100644
--- a/packages/CredentialManager/res/values-fr-rCA/strings.xml
+++ b/packages/CredentialManager/res/values-fr-rCA/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Continuer"</string>
<string name="string_more_options" msgid="7990658711962795124">"Autres options"</string>
<string name="string_learn_more" msgid="4541600451688392447">"En savoir plus"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"Afficher le mot de passe"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Masquer le mot de passe"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Une sécurité accrue grâce aux clés d\'accès"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Avec les clés d\'accès, nul besoin de créer ou de mémoriser des mots de passe complexes"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Les clés d\'accès sont des clés numériques chiffrées que vous créez en utilisant votre empreinte digitale, votre visage ou le verrouillage de votre écran"</string>
@@ -49,7 +47,10 @@
<string name="other_password_manager" msgid="565790221427004141">"Autres gestionnaires de mots de passe"</string>
<string name="close_sheet" msgid="1393792015338908262">"Fermer la feuille"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Retourner à la page précédente"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Fermez l\'action suggérée par le gestionnaire d\'authentifiants qui est affichée au bas de l\'écran"</string>
+ <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+ <skip />
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Utiliser votre clé d\'accès enregistrée pour <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Utiliser votre connexion enregistrée pour <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Choisir une connexion enregistrée pour <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -59,9 +60,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Options de connexion"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Pour <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Gestionnaires de mots de passe verrouillés"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Touchez pour déverrouiller"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Aucun renseignement de connexion"</string>
+ <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
<skip />
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Gérer les connexions"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"À partir d\'un autre appareil"</string>
diff --git a/packages/CredentialManager/res/values-fr/strings.xml b/packages/CredentialManager/res/values-fr/strings.xml
index 27354d30e693..95917e10481a 100644
--- a/packages/CredentialManager/res/values-fr/strings.xml
+++ b/packages/CredentialManager/res/values-fr/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Continuer"</string>
<string name="string_more_options" msgid="7990658711962795124">"Autres options"</string>
<string name="string_learn_more" msgid="4541600451688392447">"En savoir plus"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"Afficher le mot de passe"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Masquer le mot de passe"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Sécurité renforcée grâce aux clés d\'accès"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Avec les clés d\'accès, plus besoin de créer ni de mémoriser des mots de passe complexes"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Les clés d\'accès sont des clés numériques chiffrées que vous créez à l\'aide de votre empreinte digitale, de votre visage ou du verrouillage de l\'écran"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Autres gestionnaires de mots de passe"</string>
<string name="close_sheet" msgid="1393792015338908262">"Fermer la feuille"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Revenir à la page précédente"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Fermer la suggestion d\'action du gestionnaire d\'identifiants qui apparaît en bas de l\'écran"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Fermer"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Utiliser votre clé d\'accès enregistrée pour <xliff:g id="APP_NAME">%1$s</xliff:g> ?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Utiliser vos informations de connexion enregistrées pour <xliff:g id="APP_NAME">%1$s</xliff:g> ?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Choisir des informations de connexion enregistrées pour <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Options de connexion"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Pour <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Gestionnaires de mots de passe verrouillés"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Appuyer pour déverrouiller"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Aucune information de connexion"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Aucune info de connexion dans <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Gérer les connexions"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Depuis un autre appareil"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Utiliser un autre appareil"</string>
diff --git a/packages/CredentialManager/res/values-gl/strings.xml b/packages/CredentialManager/res/values-gl/strings.xml
index 260933c8587e..88dc4a0afa20 100644
--- a/packages/CredentialManager/res/values-gl/strings.xml
+++ b/packages/CredentialManager/res/values-gl/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Continuar"</string>
<string name="string_more_options" msgid="7990658711962795124">"Máis opcións"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Máis información"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"Mostrar contrasinal"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Ocultar contrasinal"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Máis protección coas claves de acceso"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Cunha clave de acceso, non é necesario que crees ou lembres contrasinais complexos"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"As claves de acceso son claves dixitais encriptadas que creas usando a túa impresión dixital, a túa cara ou o teu bloqueo de pantalla"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Outros xestores de contrasinais"</string>
<string name="close_sheet" msgid="1393792015338908262">"Pechar folla"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Volver á páxina anterior"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Pechar suxestión de acción do Xestor de credenciais mostrada na parte inferior da pantalla"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Pechar"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Queres usar a clave de acceso gardada para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Queres usar o método de inicio de sesión gardado para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Escolle un método de inicio de sesión gardado para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Opcións de inicio de sesión"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Para <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Xestores de contrasinais bloqueados"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Toca para desbloquear"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Sen información de inicio de sesión"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Non hai información de inicio de sesión para <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Xestionar os métodos de inicio de sesión"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Doutro dispositivo"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Usar outro dispositivo"</string>
diff --git a/packages/CredentialManager/res/values-gu/strings.xml b/packages/CredentialManager/res/values-gu/strings.xml
index bdf0257ab183..1237483f1b59 100644
--- a/packages/CredentialManager/res/values-gu/strings.xml
+++ b/packages/CredentialManager/res/values-gu/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"ચાલુ રાખો"</string>
<string name="string_more_options" msgid="7990658711962795124">"વધુ વિકલ્પો"</string>
<string name="string_learn_more" msgid="4541600451688392447">"વધુ જાણો"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"પાસવર્ડ બતાવો"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"પાસવર્ડ છુપાવો"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"પાસકી સાથે વધુ સલામત"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"પાસકી હોવાથી, તમારે જટિલ પાસવર્ડ બનાવવાની કે યાદ રાખવાની જરૂર રહેતી નથી"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"પાસકી એ એન્ક્રિપ્ટેડ ડિજિટલ કી છે, જેને તમે તમારી ફિંગરપ્રિન્ટ, ચહેરા અથવા સ્ક્રીન લૉકનો ઉપયોગ કરીને બનાવો છો"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"અન્ય પાસવર્ડ મેનેજર"</string>
<string name="close_sheet" msgid="1393792015338908262">"શીટ બંધ કરો"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"પાછલા પેજ પર પરત જાઓ"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"સ્ક્રીન પર સૌથી નીચે દેખાતું, લૉગ ઇન વિગતના મેનેજરનું ક્રિયા માટેનું સૂચન બંધ કરો"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"બંધ કરો"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> માટે શું તમારી સાચવેલી પાસકીનો ઉપયોગ કરીએ?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> માટે શું તમારા સાચવેલા સાઇન-ઇનનો ઉપયોગ કરીએ?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> માટે કોઈ સાચવેલું સાઇન-ઇન પસંદ કરો"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"સાઇન-ઇનના વિકલ્પો"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g> માટે"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"લૉક કરેલા પાસવર્ડ મેનેજર"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"અનલૉક કરવા માટે ટૅપ કરો"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"સાઇન-ઇનની કોઈ માહિતી નથી"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g>માં સાઇન-ઇનની કોઈ માહિતી નથી"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"સાઇન-ઇન મેનેજ કરો"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"કોઈ અન્ય ડિવાઇસમાંથી"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"કોઈ અન્ય ડિવાઇસનો ઉપયોગ કરો"</string>
diff --git a/packages/CredentialManager/res/values-hi/strings.xml b/packages/CredentialManager/res/values-hi/strings.xml
index 653336219032..7f3bb4937988 100644
--- a/packages/CredentialManager/res/values-hi/strings.xml
+++ b/packages/CredentialManager/res/values-hi/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"जारी रखें"</string>
<string name="string_more_options" msgid="7990658711962795124">"ज़्यादा विकल्प"</string>
<string name="string_learn_more" msgid="4541600451688392447">"ज़्यादा जानें"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"पासवर्ड दिखाएं"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"पासवर्ड छिपाएं"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"पासकी के साथ सुरक्षित रहें"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"पासकी होने पर, आपको जटिल पासवर्ड बनाने या याद रखने की ज़रूरत नहीं पड़ती"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"पासकी, एन्क्रिप्ट (सुरक्षित) की गई डिजिटल की होती हैं. इन्हें फ़िंगरप्रिंट, चेहरे या स्क्रीन लॉक का इस्तेमाल करके बनाया जाता है"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"दूसरे पासवर्ड मैनेजर"</string>
<string name="close_sheet" msgid="1393792015338908262">"शीट बंद करें"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"पिछले पेज पर वापस जाएं"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"स्क्रीन के सबसे नीचे दिख रहे, क्रेडेंशियल मैनेजर की कार्रवाई के सुझाव को बंद करें"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"बंद करें"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"क्या आपको <xliff:g id="APP_NAME">%1$s</xliff:g> पर साइन इन करने के लिए, सेव की गई पासकी का इस्तेमाल करना है?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"क्या आपको <xliff:g id="APP_NAME">%1$s</xliff:g> पर साइन इन करने के लिए, सेव की गई जानकारी का इस्तेमाल करना है?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> पर साइन इन करने के लिए, सेव की गई जानकारी में से चुनें"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"साइन इन करने के विकल्प"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g> के लिए"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"लॉक किए गए पासवर्ड मैनेजर"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"अनलॉक करने के लिए टैप करें"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"साइन-इन करने से जुड़ी कोई जानकारी उपलब्ध नहीं है"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> में साइन-इन की जानकारी नहीं है"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"साइन इन करने की सुविधा को मैनेज करें"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"किसी दूसरे डिवाइस से"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"दूसरे डिवाइस का इस्तेमाल करें"</string>
diff --git a/packages/CredentialManager/res/values-hr/strings.xml b/packages/CredentialManager/res/values-hr/strings.xml
index 392a8ed26b57..7a8354ac770e 100644
--- a/packages/CredentialManager/res/values-hr/strings.xml
+++ b/packages/CredentialManager/res/values-hr/strings.xml
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Drugi upravitelji zaporki"</string>
<string name="close_sheet" msgid="1393792015338908262">"Zatvaranje lista"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Vratite se na prethodnu stranicu"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Zatvorite prijedlog radnje upravitelja vjerodajnicama koji se pojavljuje na dnu zaslona"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Zatvori"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Želite li upotrijebiti spremljeni pristupni ključ za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Želite li upotrijebiti spremljene podatke za prijavu za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Odaberite spremljene podatke za prijavu za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Opcije prijave"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Za korisnika <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Upravitelji zaključanih zaporki"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Dodirnite za otključavanje"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Nema podataka o prijavi"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Nema podataka o prijavi u aplikaciji <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Upravljanje prijavama"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Na drugom uređaju"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Upotrijebite drugi uređaj"</string>
diff --git a/packages/CredentialManager/res/values-hu/strings.xml b/packages/CredentialManager/res/values-hu/strings.xml
index e7ecc79e0011..ae136be950cb 100644
--- a/packages/CredentialManager/res/values-hu/strings.xml
+++ b/packages/CredentialManager/res/values-hu/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Folytatás"</string>
<string name="string_more_options" msgid="7990658711962795124">"További lehetőségek"</string>
<string name="string_learn_more" msgid="4541600451688392447">"További információ"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"Jelszó megjelenítése"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Jelszó elrejtése"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Fokozott biztonság – azonosítókulccsal"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Azonosítókulcs birtokában nincs szükség összetett jelszavak létrehozására vagy megjegyzésére"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Az azonosítókulcsok olyan digitális kulcsok, amelyeket ujjlenyomata, arca vagy képernyőzár használatával hoz létre"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Egyéb jelszókezelők"</string>
<string name="close_sheet" msgid="1393792015338908262">"Munkalap bezárása"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Vissza az előző oldalra"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"A Tanúsítványkezelő képernyő alján megjelenő műveletjavaslat bezárása"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Bezárás"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Szeretné a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazáshoz mentett azonosítókulcsot használni?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Szeretné a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazáshoz mentett bejelentkezési adatait használni?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Mentett bejelentkezési adatok választása a következő számára: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Bejelentkezési beállítások"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Zárolt jelszókezelők"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Koppintson a feloldáshoz"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Nincsenek bejelentkezési adatok"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Nem találhatók bejelentkezési adatok itt: <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Bejelentkezési adatok kezelése"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Másik eszközről"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Másik eszköz használata"</string>
diff --git a/packages/CredentialManager/res/values-hy/strings.xml b/packages/CredentialManager/res/values-hy/strings.xml
index d47154b6a0b7..6b7c97317504 100644
--- a/packages/CredentialManager/res/values-hy/strings.xml
+++ b/packages/CredentialManager/res/values-hy/strings.xml
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Գաղտնաբառերի այլ կառավարիչներ"</string>
<string name="close_sheet" msgid="1393792015338908262">"Փակել թերթը"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Անցնել նախորդ էջ"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Փակել Մուտքի տվյալների կառավարչի հուշումը, որը ցուցադրվում է էկրանի ներքևի հատվածում"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Փակել"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Օգտագործե՞լ պահված անցաբառը <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի համար"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Օգտագործե՞լ մուտքի պահված տվյալները <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի համար"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Ընտրեք մուտքի պահված տվյալներ <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի համար"</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Մուտքի տարբերակներ"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g>-ի համար"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Գաղտնաբառերի կողպված կառավարիչներ"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Հպեք ապակողպելու համար"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Մուտքի տվյալներ չկան"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Մուտքի տվյալներ չկան այստեղ՝ <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Մուտքի կառավարում"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Մեկ այլ սարքից"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Օգտագործել այլ սարք"</string>
diff --git a/packages/CredentialManager/res/values-in/strings.xml b/packages/CredentialManager/res/values-in/strings.xml
index d62de2f9bccd..9eb3c659e306 100644
--- a/packages/CredentialManager/res/values-in/strings.xml
+++ b/packages/CredentialManager/res/values-in/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Lanjutkan"</string>
<string name="string_more_options" msgid="7990658711962795124">"Opsi lainnya"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Pelajari lebih lanjut"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"Tampilkan sandi"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Sembunyikan sandi"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Lebih aman dengan kunci sandi"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Dengan kunci sandi, Anda tidak perlu membuat atau mengingat sandi yang rumit"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Kunci sandi adalah kunci digital terenkripsi yang Anda buat menggunakan sidik jari, wajah, atau kunci layar"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Pengelola sandi lainnya"</string>
<string name="close_sheet" msgid="1393792015338908262">"Tutup sheet"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Kembali ke halaman sebelumnya"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Tutup saran tindakan Pengelola Kredensial yang muncul di bagian bawah layar"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Tutup"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Gunakan kunci sandi tersimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Gunakan info login tersimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Pilih info login tersimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Opsi login"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Untuk <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Pengelola sandi terkunci"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Ketuk untuk membuka kunci"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Tidak ada info login"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Tidak ada info login di <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Kelola login"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Dari perangkat lain"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Gunakan perangkat lain"</string>
diff --git a/packages/CredentialManager/res/values-is/strings.xml b/packages/CredentialManager/res/values-is/strings.xml
index 5339ece625de..b6270580cd11 100644
--- a/packages/CredentialManager/res/values-is/strings.xml
+++ b/packages/CredentialManager/res/values-is/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Áfram"</string>
<string name="string_more_options" msgid="7990658711962795124">"Fleiri valkostir"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Nánar"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"Sýna aðgangsorð"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Fela aðgangsorð"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Aukið öryggi með aðgangslyklum"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Með aðgangslyklum þarftu hvorki að búa til né muna flókin aðgangsorð"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Aðgangslyklar eru dulkóðaðir stafrænir lyklar sem þú býrð til með fingrafarinu þínu, andliti eða skjálás."</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Önnur aðgangsorðastjórnun"</string>
<string name="close_sheet" msgid="1393792015338908262">"Loka blaði"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Fara aftur á fyrri síðu"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Loka aðgerðartillögu frá skilríkjastjórnun sem birtist neðst á skjánum"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Loka"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Notað vistaðan aðgangslykil fyrir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Nota vistaða innskráningu fyrir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Veldu vistaða innskráningu fyrir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Innskráningarkostir"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Fyrir: <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Læst aðgangsorðastjórnun"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Ýttu til að opna"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Engar innskráningarupplýsingar"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Engar innskráningarupplýsingar á <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Stjórna innskráningu"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Úr öðru tæki"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Nota annað tæki"</string>
diff --git a/packages/CredentialManager/res/values-it/strings.xml b/packages/CredentialManager/res/values-it/strings.xml
index d9b67fe9b5ba..9497ceae9f53 100644
--- a/packages/CredentialManager/res/values-it/strings.xml
+++ b/packages/CredentialManager/res/values-it/strings.xml
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Altri gestori delle password"</string>
<string name="close_sheet" msgid="1393792015338908262">"Chiudi il foglio"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Torna alla pagina precedente"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Chiudi l\'azione suggerita di Gestore delle credenziali visualizzata nella parte inferiore dello schermo"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Chiudi"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Vuoi usare la passkey salvata per <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Vuoi usare l\'accesso salvato per <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Scegli un accesso salvato per <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Opzioni di accesso"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Per <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Gestori delle password bloccati"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Tocca per sbloccare"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Nessuna informazione di accesso"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Non sono presenti dati di accesso in <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Gestisci gli accessi"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Da un altro dispositivo"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Usa un dispositivo diverso"</string>
diff --git a/packages/CredentialManager/res/values-iw/strings.xml b/packages/CredentialManager/res/values-iw/strings.xml
index 900c0379a37d..9197ac65c416 100644
--- a/packages/CredentialManager/res/values-iw/strings.xml
+++ b/packages/CredentialManager/res/values-iw/strings.xml
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"מנהלי סיסמאות אחרים"</string>
<string name="close_sheet" msgid="1393792015338908262">"סגירת הגיליון"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"חזרה לדף הקודם"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"הצעה לפעולה \'סגירה של מנהל פרטי הכניסה\' שמופיעה בתחתית המסך"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"סגירה"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"להשתמש במפתח גישה שנשמר עבור <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"להשתמש בפרטי הכניסה שנשמרו עבור <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"בחירת פרטי כניסה שמורים עבור <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"אפשרויות כניסה לחשבון"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"עבור <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"מנהלי סיסמאות נעולים"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"יש להקיש כדי לבטל את הנעילה"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"אין פרטי כניסה"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"אין פרטי כניסה ב-<xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"ניהול כניסות"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"ממכשיר אחר"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"צריך להשתמש במכשיר אחר"</string>
diff --git a/packages/CredentialManager/res/values-ja/strings.xml b/packages/CredentialManager/res/values-ja/strings.xml
index 48d73e43696c..3c97777637bf 100644
--- a/packages/CredentialManager/res/values-ja/strings.xml
+++ b/packages/CredentialManager/res/values-ja/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"続行"</string>
<string name="string_more_options" msgid="7990658711962795124">"その他のオプション"</string>
<string name="string_learn_more" msgid="4541600451688392447">"詳細"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"パスワードを表示する"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"パスワードを表示しない"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"パスキーでより安全に"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"パスキーがあれば、複雑なパスワードを作成したり覚えたりする必要はありません"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"パスキーは、指紋認証、顔認証、または画面ロックを使って作成される暗号化されたデジタルキーです"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"他のパスワード マネージャー"</string>
<string name="close_sheet" msgid="1393792015338908262">"シートを閉じます"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"前のページに戻ります"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"画面下に表示されている認証情報マネージャーのおすすめの操作を閉じます"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"閉じる"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> の保存したパスキーを使用しますか?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> の保存したログイン情報を使用しますか?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> の保存したログイン情報の選択"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"ログイン オプション"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g> 用"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"パスワード マネージャー ロック中"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"タップしてロック解除"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"ログイン情報がありません"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> のログイン情報はありません"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"ログインを管理"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"別のデバイスを使う"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"別のデバイスを使用"</string>
diff --git a/packages/CredentialManager/res/values-ka/strings.xml b/packages/CredentialManager/res/values-ka/strings.xml
index 15b7c981b54c..4d0d9f7e6d95 100644
--- a/packages/CredentialManager/res/values-ka/strings.xml
+++ b/packages/CredentialManager/res/values-ka/strings.xml
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"პაროლების სხვა მმართველები"</string>
<string name="close_sheet" msgid="1393792015338908262">"ფურცლის დახურვა"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"წინა გვერდზე დაბრუნება"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"დახურეთ ავტორიზაციის მონაცემების მმართველის მოქმედებების შემოთავაზებები, რომლებიც ეკრანის ქვემოთ ჩნდება"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"დახურვა"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"გსურთ თქვენი დამახსოვრებული წვდომის გასაღების გამოყენება აპისთვის: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"გსურთ თქვენი დამახსოვრებული სისტემაში შესვლის მონაცემების გამოყენება აპისთვის: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"აირჩიეთ სისტემაში შესვლის ინფორმაცია აპისთვის: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"სისტემაში შესვლის ვარიანტები"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g>-ისთვის"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"ჩაკეტილი პაროლის მმართველები"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"შეეხეთ განსაბლოკად"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"შესვლის ინფორმაცია არ არის"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g>-ში არ არის შესვლის ინფორმაცია"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"სისტემაში შესვლის მონაცემების მართვა"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"სხვა მოწყობილობიდან"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"გამოიყენეთ სხვა მოწყობილობა"</string>
diff --git a/packages/CredentialManager/res/values-kk/strings.xml b/packages/CredentialManager/res/values-kk/strings.xml
index 3a481cb41913..4be32d86d48e 100644
--- a/packages/CredentialManager/res/values-kk/strings.xml
+++ b/packages/CredentialManager/res/values-kk/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Жалғастыру"</string>
<string name="string_more_options" msgid="7990658711962795124">"Басқа опциялар"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Толық ақпарат"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"Құпия сөзді көрсету"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Құпия сөзді жасыру"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Кіру кілттерімен қауіпсіздеу"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Кіру кілттері бар кезде күрделі құпия сөздер жасаудың немесе оларды есте сақтаудың қажеті жоқ."</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Кіру кілттері — саусақ ізі, бет не экран құлпы арқылы жасалатын шифрланған цифрлық кілттер."</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Басқа құпия сөз менеджерлері"</string>
<string name="close_sheet" msgid="1393792015338908262">"Парақты жабу"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Алдыңғы бетке оралу"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Экранның төменгі жағында шығатын тіркелу деректері менеджерінің әрекет ұсынысын жабады."</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Жабу"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> үшін сақталған кіру кілті пайдаланылсын ба?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> үшін сақталған тіркелу деректері пайдаланылсын ба?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> үшін сақталған тіркелу деректерін таңдаңыз"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Кіру опциялары"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g> үшін"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Құлыпталған құпия сөз менеджерлері"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Құлыпты ашу үшін түртіңіз."</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Кіру ақпараты жоқ."</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> аккаунтында кіру туралы ешқандай ақпарат жоқ."</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Кіру әрекеттерін басқару"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Басқа құрылғыдан жасау"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Басқа құрылғыны пайдалану"</string>
diff --git a/packages/CredentialManager/res/values-km/strings.xml b/packages/CredentialManager/res/values-km/strings.xml
index f4ac3e2d5b8e..313c0c552512 100644
--- a/packages/CredentialManager/res/values-km/strings.xml
+++ b/packages/CredentialManager/res/values-km/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"បន្ត"</string>
<string name="string_more_options" msgid="7990658711962795124">"ជម្រើសច្រើនទៀត"</string>
<string name="string_learn_more" msgid="4541600451688392447">"ស្វែងយល់បន្ថែម"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"បង្ហាញពាក្យសម្ងាត់"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"លាក់​ពាក្យ​សម្ងាត់"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"កាន់តែមានសុវត្ថិភាពដោយប្រើកូដសម្ងាត់"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"តាមរយៈ​កូដសម្ងាត់ អ្នកមិនចាំបាច់​បង្កើត ឬចងចាំពាក្យសម្ងាត់ស្មុគស្មាញ​នោះទេ"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"កូដសម្ងាត់​ត្រូវបានអ៊ីនគ្រីប​ឃីឌីជីថលដែលអ្នកបង្កើតដោយប្រើ​ស្នាមម្រាមដៃ មុខ ឬចាក់សោអេក្រង់​របស់អ្នក"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"កម្មវិធីគ្រប់គ្រងពាក្យសម្ងាត់ផ្សេងទៀត"</string>
<string name="close_sheet" msgid="1393792015338908262">"បិទសន្លឹក"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"ត្រឡប់ទៅ​ទំព័រ​មុនវិញ"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"បិទការណែនាំសកម្មភាពរបស់កម្មវិធី​គ្រប់គ្រង​ព័ត៌មាន​ផ្ទៀងផ្ទាត់ដែលបង្ហាញនៅផ្នែកខាងក្រោម​នៃ​អេក្រង់"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"បិទ"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"ប្រើកូដសម្ងាត់ដែលបានរក្សាទុករបស់អ្នកសម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g> ឬ?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"ប្រើការចូល​គណនីដែលបានរក្សាទុករបស់អ្នកសម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g> ឬ?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"ជ្រើសរើសការចូលគណនីដែលបានរក្សាទុកសម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"ជម្រើស​ចូលគណនី"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"សម្រាប់ <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"កម្មវិធីគ្រប់គ្រងពាក្យសម្ងាត់ដែលបានចាក់សោ"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"ចុចដើម្បីដោះសោ"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"គ្មានព័ត៌មានចូលគណនីទេ"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"មិនមានព័ត៌មានចូលគណនីនៅក្នុង <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"គ្រប់គ្រងការចូល​គណនី"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"ពីឧបករណ៍ផ្សេងទៀត"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"ប្រើឧបករណ៍ផ្សេង"</string>
diff --git a/packages/CredentialManager/res/values-kn/strings.xml b/packages/CredentialManager/res/values-kn/strings.xml
index 2e039da01a68..750c51bf0c81 100644
--- a/packages/CredentialManager/res/values-kn/strings.xml
+++ b/packages/CredentialManager/res/values-kn/strings.xml
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"ಇತರ ಪಾಸ್‌ವರ್ಡ್ ನಿರ್ವಾಹಕರು"</string>
<string name="close_sheet" msgid="1393792015338908262">"ಶೀಟ್ ಮುಚ್ಚಿರಿ"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"ಹಿಂದಿನ ಪುಟಕ್ಕೆ ಹಿಂದಿರುಗಿ"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"ಸ್ಕ್ರೀನ್‌ನ ಕೆಳಭಾಗದಲ್ಲಿ ಗೋಚರಿಸುವ ರುಜುವಾತು ನಿರ್ವಾಹಕ ಕ್ರಿಯೆಯ ಸಲಹೆಯನ್ನು ಮುಚ್ಚಿ"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"ಮುಚ್ಚಿರಿ"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಗಾಗಿ ಉಳಿಸಲಾದ ನಿಮ್ಮ ಪಾಸ್‌ಕೀ ಅನ್ನು ಬಳಸಬೇಕೆ?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಗಾಗಿ ಉಳಿಸಲಾದ ನಿಮ್ಮ ಸೈನ್-ಇನ್ ಅನ್ನು ಬಳಸಬೇಕೆ?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಗಾಗಿ ಉಳಿಸಲಾದ ಸೈನ್-ಇನ್ ಮಾಹಿತಿಯನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"ಸೈನ್ ಇನ್ ಆಯ್ಕೆಗಳು"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g> ಗಾಗಿ"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"ಪಾಸ್‌ವರ್ಡ್ ನಿರ್ವಾಹಕರನ್ನು ಲಾಕ್ ಮಾಡಲಾಗಿದೆ"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"ಅನ್‌ಲಾಕ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"ಯಾವುದೇ ಸೈನ್ ಇನ್ ಮಾಹಿತಿಯಿಲ್ಲ"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> ನಲ್ಲಿ ಯಾವುದೇ ಸೈನ್-ಇನ್ ಮಾಹಿತಿ ಇಲ್ಲ"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"ಸೈನ್-ಇನ್‌ಗಳನ್ನು ನಿರ್ವಹಿಸಿ"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"ಮತ್ತೊಂದು ಸಾಧನದಿಂದ"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"ಬೇರೆ ಸಾಧನವನ್ನು ಬಳಸಿ"</string>
diff --git a/packages/CredentialManager/res/values-ko/strings.xml b/packages/CredentialManager/res/values-ko/strings.xml
index 21fce5dd3ce2..89b5a3f977f6 100644
--- a/packages/CredentialManager/res/values-ko/strings.xml
+++ b/packages/CredentialManager/res/values-ko/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"계속"</string>
<string name="string_more_options" msgid="7990658711962795124">"옵션 더보기"</string>
<string name="string_learn_more" msgid="4541600451688392447">"자세히 알아보기"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"비밀번호 표시"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"비밀번호 숨기기"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"패스키로 더 안전하게"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"패스키를 사용하면 복잡한 비밀번호를 만들거나 기억하지 않아도 됩니다."</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"패스키는 지문, 얼굴 또는 화면 잠금으로 생성하는 암호화된 디지털 키입니다."</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"기타 비밀번호 관리자"</string>
<string name="close_sheet" msgid="1393792015338908262">"시트 닫기"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"이전 페이지로 돌아가기"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"화면 하단에 표시되는 인증 관리자 작업 제안 닫기"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"닫기"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> 앱용 저장된 패스키를 사용하시겠습니까?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> 앱용 저장된 로그인 정보를 사용하시겠습니까?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> 앱용 저장된 로그인 정보 선택"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"로그인 옵션"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g>님의 로그인 정보"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"잠긴 비밀번호 관리자"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"탭하여 잠금 해제"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"로그인 정보 없음"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g>의 로그인 정보 없음"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"로그인 관리"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"다른 기기에서"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"다른 기기 사용"</string>
diff --git a/packages/CredentialManager/res/values-ky/strings.xml b/packages/CredentialManager/res/values-ky/strings.xml
index 37e078a09b83..3e172b4ace67 100644
--- a/packages/CredentialManager/res/values-ky/strings.xml
+++ b/packages/CredentialManager/res/values-ky/strings.xml
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Башка сырсөздөрдү башкаргычтар"</string>
<string name="close_sheet" msgid="1393792015338908262">"Баракты жабуу"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Мурунку бетке кайтуу"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Экрандын ылдый жагындагы Credential Manager кызматынын сунушун жабуу"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Жабуу"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> үчүн сакталган мүмкүндүк алуу ачкычын колдоносузбу?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> үчүн сакталган кирүү параметрин колдоносузбу?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> үчүн кирүү маалыматын тандаңыз"</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Аккаунтка кирүү параметрлери"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g> үчүн"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Кулпуланган сырсөздөрдү башкаргычтар"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Кулпусун ачуу үчүн таптаңыз"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Аккаунтка кирүү тууралуу маалымат жок"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> аккаунтунда кирүү маалыматы жок"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Кирүү параметрлерин тескөө"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Башка түзмөктөн"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Башка түзмөктү колдонуу"</string>
diff --git a/packages/CredentialManager/res/values-lo/strings.xml b/packages/CredentialManager/res/values-lo/strings.xml
index 1213259edcf2..f08d522c71a0 100644
--- a/packages/CredentialManager/res/values-lo/strings.xml
+++ b/packages/CredentialManager/res/values-lo/strings.xml
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"ຕົວຈັດການລະຫັດຜ່ານອື່ນໆ"</string>
<string name="close_sheet" msgid="1393792015338908262">"ປິດຊີດ"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"ກັບຄືນໄປຫາໜ້າກ່ອນໜ້ານີ້"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"ປິດການແນະນຳການດຳເນີນການຂອງຕົວຈັດການຂໍ້ມູນການເຂົ້າສູ່ລະບົບເຊິ່ງປາກົດຢູ່ລຸ່ມສຸດຂອງໜ້າຈໍ"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"ປິດ"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"ໃຊ້ກະແຈຜ່ານທີ່ບັນທຶກໄວ້ຂອງທ່ານສຳລັບ <xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"ໃຊ້ການເຂົ້າສູ່ລະບົບທີ່ບັນທຶກໄວ້ຂອງທ່ານສຳລັບ <xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"ເລືອກການເຂົ້າສູ່ລະບົບທີ່ບັນທຶກໄວ້ສຳລັບ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"ຕົວເລືອກການເຂົ້າສູ່ລະບົບ"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"ສຳລັບ <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"ຕົວຈັດການລະຫັດຜ່ານທີ່ລັອກໄວ້"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"ແຕະເພື່ອປົດລັອກ"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"ບໍ່ມີຂໍ້ມູນການເຂົ້າສູ່ລະບົບ"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"ບໍ່ມີຂໍ້ມູນການເຂົ້າສູ່ລະບົບໃນ <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"ຈັດການການເຂົ້າສູ່ລະບົບ"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"ຈາກອຸປະກອນອື່ນ"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"ໃຊ້ອຸປະກອນອື່ນ"</string>
diff --git a/packages/CredentialManager/res/values-lt/strings.xml b/packages/CredentialManager/res/values-lt/strings.xml
index 011d745542c3..71b50a834c07 100644
--- a/packages/CredentialManager/res/values-lt/strings.xml
+++ b/packages/CredentialManager/res/values-lt/strings.xml
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Kitos slaptažodžių tvarkyklės"</string>
<string name="close_sheet" msgid="1393792015338908262">"Uždaryti lapą"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Grįžti į ankstesnį puslapį"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Uždaryti prisijungimo duomenų tvarkytuvės veiksmo pasiūlymą, rodomą ekrano apačioje"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Uždaryti"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Naudoti išsaugotą „passkey“ programai „<xliff:g id="APP_NAME">%1$s</xliff:g>“?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Naudoti išsaugotą prisijungimo informaciją programai „<xliff:g id="APP_NAME">%1$s</xliff:g>“?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Pasirinkite išsaugotą prisijungimo informaciją programai „<xliff:g id="APP_NAME">%1$s</xliff:g>“"</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Prisijungimo parinktys"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Skirta <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Užrakintos slaptažodžių tvarkyklės"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Palieskite, kad atrakintumėte"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Prisijungimo informacijos nėra"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Nėra prisijungimo informacijos <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Tvarkyti prisijungimo informaciją"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Naudojant kitą įrenginį"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Naudoti kitą įrenginį"</string>
diff --git a/packages/CredentialManager/res/values-lv/strings.xml b/packages/CredentialManager/res/values-lv/strings.xml
index 899dc3d9fd21..86a7b8ac65f4 100644
--- a/packages/CredentialManager/res/values-lv/strings.xml
+++ b/packages/CredentialManager/res/values-lv/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Turpināt"</string>
<string name="string_more_options" msgid="7990658711962795124">"Citas opcijas"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Uzzināt vairāk"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"Rādīt paroli"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Slēpt paroli"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Lielāka drošība ar piekļuves atslēgām"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Izmantojot piekļuves atslēgas, nav jāveido vai jāatceras sarežģītas paroles."</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Piekļuves atslēgas ir šifrētas digitālas atslēgas, ko varat izveidot, izmantojot pirksta nospiedumu, seju vai ekrāna bloķēšanas informāciju."</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Citi paroļu pārvaldnieki"</string>
<string name="close_sheet" msgid="1393792015338908262">"Aizvērt lapu"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Atgriezties iepriekšējā lapā"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Aizvērt Akreditācijas datu pārvaldnieka darbības ieteikumu, kas tiek rādīts ekrāna apakšdaļā"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Aizvērt"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Vai izmantot saglabāto piekļuves atslēgu lietotnei <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Vai izmantot saglabāto pierakstīšanās informāciju lietotnei <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Saglabātas pierakstīšanās informācijas izvēle lietotnei <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Pierakstīšanās opcijas"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Lietotājam <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Paroļu pārvaldnieki, kuros nepieciešams autentificēties"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Pieskarieties, lai atbloķētu"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Nav pierakstīšanās informācijas"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Kontā <xliff:g id="SOURCE">%1$s</xliff:g> nav pierakstīšanās informācijas."</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Pierakstīšanās informācijas pārvaldība"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"No citas ierīces"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Izmantot citu ierīci"</string>
diff --git a/packages/CredentialManager/res/values-mk/strings.xml b/packages/CredentialManager/res/values-mk/strings.xml
index ba7f029c1c3a..393bca1dd836 100644
--- a/packages/CredentialManager/res/values-mk/strings.xml
+++ b/packages/CredentialManager/res/values-mk/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Продолжи"</string>
<string name="string_more_options" msgid="7990658711962795124">"Повеќе опции"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Дознајте повеќе"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"Прикажи ја лозинката"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Сокриј ја лозинката"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Побезбедно со криптографски клучеви"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Со криптографските клучеви нема потреба да создавате или да помните сложени лозинки"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Криптографските клучеви се шифрирани дигитални клучеви што ги создавате со вашиот отпечаток, лик или заклучување екран"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Други управници со лозинки"</string>
<string name="close_sheet" msgid="1393792015338908262">"Затворете го листот"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Врати се на претходната страница"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Затворете го предложеното дејство за „Управникот со акредитиви“ што се појавува најдолу на екранот"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Затвори"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Да се користи вашиот зачуван криптографски клуч за <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Да се користи вашето зачувано најавување за <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Изберете зачувано најавување за <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Опции за најавување"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"За <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Заклучени управници со лозинки"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Допрете за да отклучите"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Нема податоци за најавување"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Нема податоци за најавување во <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Управувајте со најавувањата"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Од друг уред"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Употребете друг уред"</string>
diff --git a/packages/CredentialManager/res/values-ml/strings.xml b/packages/CredentialManager/res/values-ml/strings.xml
index 4c18ba0e0154..efe614c2c04f 100644
--- a/packages/CredentialManager/res/values-ml/strings.xml
+++ b/packages/CredentialManager/res/values-ml/strings.xml
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"മറ്റ് പാസ്‌വേഡ് മാനേജർമാർ"</string>
<string name="close_sheet" msgid="1393792015338908262">"ഷീറ്റ് അടയ്ക്കുക"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"മുമ്പത്തെ പേജിലേക്ക് മടങ്ങുക"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"സ്ക്രീന്റെ ചുവടെ ദൃശ്യമാകുന്ന ക്രെഡൻഷ്യൽ മാനേജർ പ്രവർത്തന നിർദ്ദേശം അടയ്ക്കുക"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"അടയ്ക്കുക"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിനായി നിങ്ങൾ സംരക്ഷിച്ച പാസ്‌കീ ഉപയോഗിക്കണോ?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിനായി നിങ്ങൾ സംരക്ഷിച്ച സൈൻ ഇൻ ഉപയോഗിക്കണോ?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിനായി ഒരു സംരക്ഷിച്ച സൈൻ ഇൻ തിരഞ്ഞെടുക്കുക"</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"സൈൻ ഇൻ ഓപ്ഷനുകൾ"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g> എന്നയാൾക്ക്"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"ലോക്ക് ചെയ്‌ത പാസ്‌വേഡ് സൈൻ ഇൻ മാനേജർമാർ"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"അൺലോക്ക് ചെയ്യാൻ ടാപ്പ് ചെയ്യുക"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"സൈൻ ഇൻ ചെയ്യാനുള്ള വിവരങ്ങളൊന്നുമില്ല"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> എന്നതിൽ സൈൻ ഇൻ വിവരങ്ങളില്ല"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"സൈൻ ഇന്നുകൾ മാനേജ് ചെയ്യുക"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"മറ്റൊരു ഉപകരണത്തിൽ നിന്ന്"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"മറ്റൊരു ഉപകരണം ഉപയോഗിക്കുക"</string>
diff --git a/packages/CredentialManager/res/values-mn/strings.xml b/packages/CredentialManager/res/values-mn/strings.xml
index 8b91f3b5dede..6c7ba7a49f32 100644
--- a/packages/CredentialManager/res/values-mn/strings.xml
+++ b/packages/CredentialManager/res/values-mn/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Үргэлжлүүлэх"</string>
<string name="string_more_options" msgid="7990658711962795124">"Бусад сонголт"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Нэмэлт мэдээлэл авах"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"Нууц үгийг харуулах"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Нууц үгийг нуух"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Passkey-тэй байхад илүү аюулгүй"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Passkey-н тусламжтай та нарийн төвөгтэй нууц үг үүсгэх эсвэл санах шаардлагагүй"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Passkey нь таны хурууны хээ, царай эсвэл дэлгэцийн түгжээгээ ашиглан үүсгэсэн шифрлэгдсэн дижитал түлхүүр юм"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Нууц үгний бусад менежер"</string>
<string name="close_sheet" msgid="1393792015338908262">"Хүснэгтийг хаах"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Өмнөх хуудас руу буцах"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Дэлгэцийн доод талд гарч ирэх Мандат үнэмлэхийн менежерийн үйлдлийн зөвлөмжийг хаана"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Хаах"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g>-д өөрийн хадгалсан passkey-г ашиглах уу?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g>-д хадгалсан нэвтрэх мэдээллээ ашиглах уу?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g>-д зориулж хадгалсан нэвтрэх мэдээллийг сонгоно уу"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Нэвтрэх сонголт"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g>-д"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Түгжээтэй нууц үгний менежерүүд"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Түгжээг тайлахын тулд товшино уу"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Ямар ч нэвтрэх мэдээлэл байхгүй"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g>-д ямар ч нэвтрэх мэдээлэл алга"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Нэвтрэлтийг удирдах"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Өөр төхөөрөмжөөс"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Өөр төхөөрөмж ашиглах"</string>
diff --git a/packages/CredentialManager/res/values-mr/strings.xml b/packages/CredentialManager/res/values-mr/strings.xml
index 0ac9ce6b96aa..ca0480c59b24 100644
--- a/packages/CredentialManager/res/values-mr/strings.xml
+++ b/packages/CredentialManager/res/values-mr/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"पुढे सुरू ठेवा"</string>
<string name="string_more_options" msgid="7990658711962795124">"आणखी पर्याय"</string>
<string name="string_learn_more" msgid="4541600451688392447">"अधिक जाणून घ्या"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"पासवर्ड दाखवा"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"पासवर्ड लपवा"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"पासकीसह आणखी सुरक्षित"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"पासकीसोबत, तुम्हाला क्लिष्ट पासवर्ड तयार करण्याची किंवा लक्षात ठेवण्याची आवश्यकता नाही"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"पासकी या तुम्ही तुमचे फिंगरप्रिंट, फेस किंवा स्क्रीन लॉक वापरून तयार करता अशा एंक्रिप्ट केलेल्या डिजिटल की आहेत"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"इतर पासवर्ड व्यवस्थापक"</string>
<string name="close_sheet" msgid="1393792015338908262">"शीट बंद करा"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"मागील पेजवर परत जा"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"स्क्रीनच्या तळाशी दिसणाऱ्या क्रेडेंशियल व्यवस्थापक कृती सूचना बंद करा"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"बंद करा"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> साठी तुमची सेव्ह केलेली पासकी वापरायची का?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> साठी तुमचे सेव्ह केलेले साइन-इन वापरायचे का?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> साठी सेव्ह केलेले साइन-इन निवडा"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"साइन इन पर्याय"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g> साठी"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"लॉक केलेले पासवर्ड व्यवस्थापक"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"अनलॉक करण्यासाठी टॅप करा"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"साइन-इन माहिती नाही"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> मध्ये कोणतीही साइन-इन माहिती नाही"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"साइन-इन व्यवस्थापित करा"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"दुसऱ्या डिव्हाइस वरून"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"वेगळे डिव्हाइस वापरा"</string>
diff --git a/packages/CredentialManager/res/values-ms/strings.xml b/packages/CredentialManager/res/values-ms/strings.xml
index d762bed9e487..7719f91575d4 100644
--- a/packages/CredentialManager/res/values-ms/strings.xml
+++ b/packages/CredentialManager/res/values-ms/strings.xml
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Password Manager lain"</string>
<string name="close_sheet" msgid="1393792015338908262">"Tutup helaian"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Kembali ke halaman sebelumnya"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Tutup cadangan tindakan Pengurus Bukti Kelayakan yang muncul di bahagian bawah skrin"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Tutup"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Gunakan kunci laluan anda yang telah disimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Gunakan maklumat log masuk anda yang telah disimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Pilih log masuk yang telah disimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Pilihan log masuk"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Untuk <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Password Manager dikunci"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Ketik untuk membuka kunci"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Tiada maklumat log masuk"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Tiada maklumat log masuk pada <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Urus log masuk"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Daripada peranti lain"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Gunakan peranti yang lain"</string>
diff --git a/packages/CredentialManager/res/values-my/strings.xml b/packages/CredentialManager/res/values-my/strings.xml
index 0a03356b3e97..9b60d5c0a6c3 100644
--- a/packages/CredentialManager/res/values-my/strings.xml
+++ b/packages/CredentialManager/res/values-my/strings.xml
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"အခြားစကားဝှက်မန်နေဂျာများ"</string>
<string name="close_sheet" msgid="1393792015338908262">"စာမျက်နှာ ပိတ်ရန်"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"ယခင်စာမျက်နှာကို ပြန်သွားပါ"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"ဖန်သားပြင်အောက်ခြေတွင် ပြထားသော ‘အထောက်အထားမန်နေဂျာ’ လုပ်ဆောင်မှု အကြံပြုချက်ကို ပိတ်နိုင်သည်"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"ပိတ်ရန်"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> အတွက် သိမ်းထားသောလျှို့ဝှက်ကီး သုံးမလား။"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> အတွက် သိမ်းထားသောလက်မှတ်ထိုးဝင်မှု သုံးမလား။"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> အတွက် သိမ်းထားသော လက်မှတ်ထိုးဝင်မှုကို ရွေးပါ"</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"လက်မှတ်ထိုးဝင်ရန် နည်းလမ်းများ"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g> အတွက်"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"လော့ခ်ချထားသည့် စကားဝှက်မန်နေဂျာများ"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"ဖွင့်ရန် တို့ပါ"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"လက်မှတ်ထိုးဝင်သည့် အချက်အလက် မရှိပါ"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> တွင် လက်မှတ်ထိုးဝင်ရန်အချက်အလက် မရှိပါ"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"လက်မှတ်ထိုးဝင်မှုများ စီမံခြင်း"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"စက်နောက်တစ်ခုမှ"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"အခြားစက်သုံးရန်"</string>
diff --git a/packages/CredentialManager/res/values-nb/strings.xml b/packages/CredentialManager/res/values-nb/strings.xml
index 774b35b63a97..88692cb8513f 100644
--- a/packages/CredentialManager/res/values-nb/strings.xml
+++ b/packages/CredentialManager/res/values-nb/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Fortsett"</string>
<string name="string_more_options" msgid="7990658711962795124">"Flere alternativer"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Finn ut mer"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"Vis passordet"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Skjul passordet"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Tryggere med tilgangsnøkler"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Med tilgangsnøkler trenger du ikke å lage eller huske kompliserte passord"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Tilgangsnøkler er krypterte digitale nøkler du oppretter med fingeravtrykket, ansiktet eller skjermlåsen"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Andre løsninger for passordlagring"</string>
<string name="close_sheet" msgid="1393792015338908262">"Lukk arket"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Gå tilbake til den forrige siden"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Lukk handlingsforslaget fra legitimasjonslagring som vises nedest på skjermen"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Lukk"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Vil du bruke den lagrede tilgangsnøkkelen for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Vil du bruke den lagrede påloggingen for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Velg en lagret pålogging for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Påloggingsalternativer"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"For <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Låste løsninger for passordlagring"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Trykk for å låse opp"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Ingen påloggingsinformasjon"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Ingen påloggingsinformasjon i <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Administrer pålogginger"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Fra en annen enhet"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Bruk en annen enhet"</string>
diff --git a/packages/CredentialManager/res/values-ne/strings.xml b/packages/CredentialManager/res/values-ne/strings.xml
index ca501bddc8a9..45c9f8ce0fcb 100644
--- a/packages/CredentialManager/res/values-ne/strings.xml
+++ b/packages/CredentialManager/res/values-ne/strings.xml
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"अन्य पासवर्ड म्यानेजरहरू"</string>
<string name="close_sheet" msgid="1393792015338908262">"पाना बन्द गर्नुहोस्"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"अघिल्लो पेजमा फर्कनुहोस्"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"स्क्रिनको फेदमा देखिएको क्रिडेन्सियल म्यानेजरको कारबाहीसम्बन्धी सुझाव बन्द गर्नुहोस्"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"बन्द गर्नुहोस्"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"आफूले सेभ गरेको पासकी प्रयोग गरी <xliff:g id="APP_NAME">%1$s</xliff:g> मा साइन इन गर्ने हो?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"आफूले सेभ गरेको साइन इनसम्बन्धी जानकारी प्रयोग गरी <xliff:g id="APP_NAME">%1$s</xliff:g> मा साइन इन गर्ने हो?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> मा साइन इन गर्नका लागि सेभ गरिएका साइन इनसम्बन्धी जानकारी छनौट गर्नुहोस्"</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"साइन‍ इनसम्बन्धी विकल्पहरू"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g> का लागि"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"लक गरिएका पासवर्ड म्यानेजरहरू"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"अनलक गर्न ट्याप गर्नुहोस्"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"साइन गर्न प्रयोग गरिनु पर्ने जानकारी उपलब्ध छैन"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> मा साइन इन गर्नेसम्बन्धी कुनै पनि जानकारी छैन"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"साइन इनसम्बन्धी विकल्पहरू व्यवस्थापन गर्नुहोस्"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"अर्को डिभाइसका लागि"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"अर्कै डिभाइस प्रयोग गरी हेर्नुहोस्"</string>
diff --git a/packages/CredentialManager/res/values-nl/strings.xml b/packages/CredentialManager/res/values-nl/strings.xml
index ccba75592616..32307ea2910f 100644
--- a/packages/CredentialManager/res/values-nl/strings.xml
+++ b/packages/CredentialManager/res/values-nl/strings.xml
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Andere wachtwoordmanagers"</string>
<string name="close_sheet" msgid="1393792015338908262">"Blad sluiten"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Ga terug naar de vorige pagina"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Sluit de aanbevolen actie voor de Credential Manager onderaan het scherm"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Sluiten"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Je opgeslagen toegangssleutel voor <xliff:g id="APP_NAME">%1$s</xliff:g> gebruiken?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Je opgeslagen inloggegevens voor <xliff:g id="APP_NAME">%1$s</xliff:g> gebruiken?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Opgeslagen inloggegevens kiezen voor <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Opties voor inloggen"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Voor <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Vergrendelde wachtwoordmanagers"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Tik om te ontgrendelen"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Geen inloggegevens"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Geen inloggevens in <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Inloggegevens beheren"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Via een ander apparaat"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Een ander apparaat gebruiken"</string>
diff --git a/packages/CredentialManager/res/values-or/strings.xml b/packages/CredentialManager/res/values-or/strings.xml
index 73d5104e887f..953e9b2b3a29 100644
--- a/packages/CredentialManager/res/values-or/strings.xml
+++ b/packages/CredentialManager/res/values-or/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"ଜାରି ରଖନ୍ତୁ"</string>
<string name="string_more_options" msgid="7990658711962795124">"ଅଧିକ ବିକଳ୍ପ"</string>
<string name="string_learn_more" msgid="4541600451688392447">"ଅଧିକ ଜାଣନ୍ତୁ"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"ପାସୱାର୍ଡ ଦେଖାନ୍ତୁ"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"ପାସୱାର୍ଡ ଲୁଚାନ୍ତୁ"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"ପାସକୀ ସହ ଅଧିକ ସୁରକ୍ଷିତ"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"ପାସକୀଗୁଡ଼ିକ ସହ ଆପଣଙ୍କୁ ଜଟିଳ ପାସୱାର୍ଡଗୁଡ଼ିକ ତିଆରି କରିବା କିମ୍ବା ମନେରଖିବାର ଆବଶ୍ୟକତା ନାହିଁ"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"ପାସକୀଗୁଡ଼ିକ ହେଉଛି ଆପଣ ଆପଣଙ୍କ ଟିପଚିହ୍ନ, ଫେସ କିମ୍ବା ସ୍କ୍ରିନ ଲକ ବ୍ୟବହାର କରି ତିଆରି କରୁଥିବା ଏକକ୍ରିପ୍ଟ କରାଯାଇଥିବା ଡିଜିଟାଲ କୀ"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"ଅନ୍ୟ Password Manager"</string>
<string name="close_sheet" msgid="1393792015338908262">"ସିଟ ବନ୍ଦ କରନ୍ତୁ"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"ପୂର୍ବବର୍ତ୍ତୀ ପୃଷ୍ଠାକୁ ଫେରନ୍ତୁ"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"ସ୍କ୍ରିନର ନିମ୍ନରେ ଦେଖାଯାଉଥିବା କ୍ରେଡେନସିଆଲ ମେନେଜର ଆକ୍ସନ ବିଷୟରେ ପରାମର୍ଶକୁ ବନ୍ଦ କରନ୍ତୁ"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"ବନ୍ଦ କରନ୍ତୁ"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> ପାଇଁ ସେଭ କରାଯାଇଥିବା ଆପଣଙ୍କ ପାସକୀ ବ୍ୟବହାର କରିବେ?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> ପାଇଁ ସେଭ କରାଯାଇଥିବା ଆପଣଙ୍କ ସାଇନ-ଇନ ବ୍ୟବହାର କରିବେ?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> ପାଇଁ ସେଭ କରାଯାଇଥିବା ଏକ ସାଇନ-ଇନ ବାଛନ୍ତୁ"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"ସାଇନ ଇନ ବିକଳ୍ପଗୁଡ଼ିକ"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g>ରେ"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"ଲକ ଥିବା Password Manager"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"ଅନଲକ କରିବାକୁ ଟାପ କରନ୍ତୁ"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"କୌଣସି ସାଇନ-ଇନ ସୂଚନା ନାହିଁ"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g>ରେ କୌଣସି ସାଇନ-ଇନ ସୂଚନା ନାହିଁ"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"ସାଇନ-ଇନ ପରିଚାଳନା କରନ୍ତୁ"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"ଅନ୍ୟ ଏକ ଡିଭାଇସରୁ"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"ଏକ ଭିନ୍ନ ଡିଭାଇସ ବ୍ୟବହାର କରନ୍ତୁ"</string>
diff --git a/packages/CredentialManager/res/values-pa/strings.xml b/packages/CredentialManager/res/values-pa/strings.xml
index aa6d8534a168..2dd6a2ca2e3e 100644
--- a/packages/CredentialManager/res/values-pa/strings.xml
+++ b/packages/CredentialManager/res/values-pa/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"ਜਾਰੀ ਰੱਖੋ"</string>
<string name="string_more_options" msgid="7990658711962795124">"ਹੋਰ ਵਿਕਲਪ"</string>
<string name="string_learn_more" msgid="4541600451688392447">"ਹੋਰ ਜਾਣੋ"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"ਪਾਸਵਰਡ ਦਿਖਾਓ"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"ਪਾਸਵਰਡ ਲੁਕਾਓ"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"ਪਾਸਕੀਆਂ ਨਾਲ ਸੁਰੱਖਿਅਤ"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"ਪਾਸਕੀਆਂ ਨਾਲ, ਤੁਹਾਨੂੰ ਜਟਿਲ ਪਾਸਵਰਡ ਬਣਾਉਣ ਜਾਂ ਯਾਦ ਰੱਖਣ ਦੀ ਲੋੜ ਨਹੀਂ ਹੁੰਦੀ"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"ਪਾਸਕੀਆਂ ਇਨਕ੍ਰਿਪਟਡ ਡਿਜੀਟਲ ਕੁੰਜੀਆਂ ਹੁੰਦੀਆਂ ਹਨ ਜੋ ਤੁਹਾਡੇ ਵੱਲੋਂ ਤੁਹਾਡੇ ਫਿੰਗਰਪ੍ਰਿੰਟ, ਚਿਹਰੇ ਜਾਂ ਸਕ੍ਰੀਨ ਲਾਕ ਦੀ ਵਰਤੋਂ ਕਰ ਕੇ ਬਣਾਈਆਂ ਜਾਂਦੀਆਂ ਹਨ"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"ਹੋਰ ਪਾਸਵਰਡ ਪ੍ਰਬੰਧਕ"</string>
<string name="close_sheet" msgid="1393792015338908262">"ਸ਼ੀਟ ਬੰਦ ਕਰੋ"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"ਪਿਛਲੇ ਪੰਨੇ \'ਤੇ ਵਾਪਸ ਜਾਓ"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਾਂ ਦਿਖਾਈ ਦੇ ਰਹੇ ਕ੍ਰੀਡੈਂਸ਼ੀਅਲ ਪ੍ਰਬੰਧਕ ਦੀ ਕਾਰਵਾਈ ਦੇ ਸੁਝਾਅ ਨੂੰ ਬੰਦ ਕਰੋ"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"ਬੰਦ ਕਰੋ"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"ਕੀ <xliff:g id="APP_NAME">%1$s</xliff:g> ਲਈ ਆਪਣੀ ਰੱਖਿਅਤ ਕੀਤੀ ਪਾਸਕੀ ਦੀ ਵਰਤੋਂ ਕਰਨੀ ਹੈ?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"ਕੀ <xliff:g id="APP_NAME">%1$s</xliff:g> ਲਈ ਆਪਣੀ ਰੱਖਿਅਤ ਕੀਤੀ ਸਾਈਨ-ਇਨ ਜਾਣਕਾਰੀ ਦੀ ਵਰਤੋਂ ਕਰਨੀ ਹੈ?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਲਈ ਰੱਖਿਅਤ ਕੀਤੀ ਸਾਈਨ-ਇਨ ਜਾਣਕਾਰੀ ਚੁਣੋ"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"ਸਾਈਨ-ਇਨ ਕਰਨ ਦੇ ਵਿਕਲਪ"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g> ਲਈ"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"ਲਾਕ ਕੀਤੇ ਪਾਸਵਰਡ ਪ੍ਰਬੰਧਕ"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"ਅਣਲਾਕ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"ਸਾਈਨ-ਇਨ ਜਾਣਕਾਰੀ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> ਵਿੱਚ ਕੋਈ ਸਾਈਨ-ਇਨ ਜਾਣਕਾਰੀ ਨਹੀਂ"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"ਸਾਈਨ-ਇਨਾਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"ਹੋਰ ਡੀਵਾਈਸ ਤੋਂ"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"ਵੱਖਰੇ ਡੀਵਾਈਸ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
diff --git a/packages/CredentialManager/res/values-pl/strings.xml b/packages/CredentialManager/res/values-pl/strings.xml
index 8aca7ce70896..74a0d8fddfdc 100644
--- a/packages/CredentialManager/res/values-pl/strings.xml
+++ b/packages/CredentialManager/res/values-pl/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Dalej"</string>
<string name="string_more_options" msgid="7990658711962795124">"Więcej opcji"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Więcej informacji"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"Pokaż hasło"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Ukryj hasło"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Klucze zwiększają Twoje bezpieczeństwo"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Dzięki kluczom nie musisz tworzyć ani zapamiętywać skomplikowanych haseł"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Klucze są szyfrowanymi kluczami cyfrowymi, które tworzysz za pomocą funkcji rozpoznawania odcisku palca lub twarzy bądź blokady ekranu"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Inne menedżery haseł"</string>
<string name="close_sheet" msgid="1393792015338908262">"Zamknij arkusz"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Wróć do poprzedniej strony"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Zamknij sugestię działania w Menedżerze danych logowania na dole ekranu"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Zamknij"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Użyć zapisanego klucza dla aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Użyć zapisanych danych logowania dla aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Wybierz zapisane dane logowania dla aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Opcje logowania"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Zablokowane menedżery haseł"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Kliknij, aby odblokować"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Brak danych logowania"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g>: brak danych logowania"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Zarządzanie danymi logowania"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Na innym urządzeniu"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Użyj innego urządzenia"</string>
diff --git a/packages/CredentialManager/res/values-pt-rBR/strings.xml b/packages/CredentialManager/res/values-pt-rBR/strings.xml
index ed0f27531497..9eaf99bc4056 100644
--- a/packages/CredentialManager/res/values-pt-rBR/strings.xml
+++ b/packages/CredentialManager/res/values-pt-rBR/strings.xml
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Outros gerenciadores de senha"</string>
<string name="close_sheet" msgid="1393792015338908262">"Fechar página"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Voltar à página anterior"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Fechar a sugestão de ação do Gerenciador de Credenciais mostrada na parte de baixo da tela"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Fechar"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Usar sua chave de acesso salva para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Usar suas informações de login salvas para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Escolher um login salvo para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Opções de login"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Para <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Gerenciadores de senha bloqueados"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Toque para desbloquear"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Nenhuma informação de login"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Sem informações de login em <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Gerenciar logins"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"De outro dispositivo"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Usar um dispositivo diferente"</string>
diff --git a/packages/CredentialManager/res/values-pt-rPT/strings.xml b/packages/CredentialManager/res/values-pt-rPT/strings.xml
index d9884aa67e9f..ad927e0110ca 100644
--- a/packages/CredentialManager/res/values-pt-rPT/strings.xml
+++ b/packages/CredentialManager/res/values-pt-rPT/strings.xml
@@ -14,7 +14,7 @@
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"São guardadas num gestor de palavras-passe para que possa iniciar sessão noutros dispositivos"</string>
<string name="more_about_passkeys_title" msgid="7797903098728837795">"Mais acerca das chaves de acesso"</string>
<string name="passwordless_technology_title" msgid="2497513482056606668">"Tecnologia sem palavras-passe"</string>
- <string name="passwordless_technology_detail" msgid="6853928846532955882">"As chaves de acesso permitem-lhe iniciar sessão sem depender das palavras-passe. Basta usar a impressão digital, o reconhecimento facial, o PIN ou o padrão de deslize para validar a sua identidade e criar uma chave de acesso."</string>
+ <string name="passwordless_technology_detail" msgid="6853928846532955882">"As chaves de acesso permitem-lhe iniciar sessão sem depender das palavras-passe. Basta usar a impressão digital, o reconhecimento facial, o PIN ou o padrão de deslize para validar a sua identidade e criar uma token de acesso."</string>
<string name="public_key_cryptography_title" msgid="6751970819265298039">"Criptografia de chaves públicas"</string>
<string name="public_key_cryptography_detail" msgid="6937631710280562213">"Baseadas na FIDO Alliance e no W3C, as palavras de acesso usam pares de chaves criptográficas. Ao contrário do nome de utilizador e da string de carateres das palavras-passe, cria-se um par de chaves públicas/privadas para a app ou Website. A chave privada é armazenada de forma segura no dispositivo ou gestor de palavras-passe e confirma a identidade. A chave pública é partilhada com o servidor do Website ou app. Com as chaves correspondentes, pode registar-se e iniciar sessão instantaneamente."</string>
<string name="improved_account_security_title" msgid="1069841917893513424">"Segurança melhorada nas contas"</string>
@@ -23,17 +23,17 @@
<string name="seamless_transition_detail" msgid="4475509237171739843">"À medida que avançamos para um futuro sem palavras-passe, as palavras-passe continuam disponíveis juntamente com as chaves de acesso."</string>
<string name="choose_provider_title" msgid="8870795677024868108">"Escolha onde guardar as suas <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
<string name="choose_provider_body" msgid="4967074531845147434">"Selecione um gestor de palavras-passe para guardar as suas informações e iniciar sessão mais rapidamente da próxima vez"</string>
- <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Criar uma chave de acesso para a app <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
+ <string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Criar uma token de acesso para a app <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Guardar a palavra-passe da app <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Guardar as informações de início de sessão da app <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="passkey" msgid="632353688396759522">"chave de acesso"</string>
+ <string name="passkey" msgid="632353688396759522">"token de acesso"</string>
<string name="password" msgid="6738570945182936667">"palavra-passe"</string>
<string name="passkeys" msgid="5733880786866559847">"chaves de acesso"</string>
<string name="passwords" msgid="5419394230391253816">"palavras-passe"</string>
<string name="sign_ins" msgid="4710739369149469208">"inícios de sessão"</string>
<string name="sign_in_info" msgid="2627704710674232328">"informações de início de sessão"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Guarde <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> em"</string>
- <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Criar chave de acesso noutro dispositivo?"</string>
+ <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Criar token de acesso noutro dispositivo?"</string>
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Usar <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> para todos os seus inícios de sessão?"</string>
<string name="use_provider_for_all_description" msgid="8466427781848268490">"Este gestor de palavras-passe armazena as suas palavras-passe e chaves de acesso para ajudar a iniciar sessão facilmente"</string>
<string name="set_as_default" msgid="4415328591568654603">"Definir como predefinição"</string>
@@ -47,8 +47,10 @@
<string name="other_password_manager" msgid="565790221427004141">"Outros gestores de palavras-passe"</string>
<string name="close_sheet" msgid="1393792015338908262">"Fechar folha"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Volte à página anterior"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Feche a sugestão de ação do Gestor de credenciais apresentada na parte inferior do ecrã"</string>
- <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Usar a sua chave de acesso guardada na app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Fechar"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
+ <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Usar a sua token de acesso guardada na app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Usar o seu início de sessão guardado na app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Escolha um início de sessão guardado para a app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Iniciar sessão de outra forma"</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Opções de início de sessão"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Para <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Gestores de palavras-passe bloqueados"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Tocar para desbloquear"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Sem informações de início de sessão"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Sem informações de início de sessão em <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Faça a gestão dos inícios de sessão"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"De outro dispositivo"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Use um dispositivo diferente"</string>
diff --git a/packages/CredentialManager/res/values-pt/strings.xml b/packages/CredentialManager/res/values-pt/strings.xml
index ed0f27531497..9eaf99bc4056 100644
--- a/packages/CredentialManager/res/values-pt/strings.xml
+++ b/packages/CredentialManager/res/values-pt/strings.xml
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Outros gerenciadores de senha"</string>
<string name="close_sheet" msgid="1393792015338908262">"Fechar página"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Voltar à página anterior"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Fechar a sugestão de ação do Gerenciador de Credenciais mostrada na parte de baixo da tela"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Fechar"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Usar sua chave de acesso salva para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Usar suas informações de login salvas para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Escolher um login salvo para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Opções de login"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Para <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Gerenciadores de senha bloqueados"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Toque para desbloquear"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Nenhuma informação de login"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Sem informações de login em <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Gerenciar logins"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"De outro dispositivo"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Usar um dispositivo diferente"</string>
diff --git a/packages/CredentialManager/res/values-ro/strings.xml b/packages/CredentialManager/res/values-ro/strings.xml
index e2a243caa14d..198ff1d65a9a 100644
--- a/packages/CredentialManager/res/values-ro/strings.xml
+++ b/packages/CredentialManager/res/values-ro/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Continuă"</string>
<string name="string_more_options" msgid="7990658711962795124">"Mai multe opțiuni"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Află mai multe"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"Afișează parola"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Ascunde parola"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Mai în siguranță cu chei de acces"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Dacă folosești chei de acces, nu este nevoie să creezi sau să reții parole complexe"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Cheile de acces sunt chei digitale criptate pe care le creezi folosindu-ți amprenta, fața sau blocarea ecranului"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Alți manageri de parole"</string>
<string name="close_sheet" msgid="1393792015338908262">"Închide foaia"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Revino la pagina precedentă"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Închide sugestia de acțiune de la Managerul de date de conectare, care apare în partea de jos a ecranului"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Închide"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Folosești cheia de acces salvată pentru <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Folosești datele de conectare salvate pentru <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Alege o conectare salvată pentru <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Opțiuni de conectare"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Pentru <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Manageri de parole blocate"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Atinge pentru a debloca"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Fără informații de conectare"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Nu există informații de conectare în contul <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Gestionează acreditările"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"De pe alt dispozitiv"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Folosește alt dispozitiv"</string>
diff --git a/packages/CredentialManager/res/values-ru/strings.xml b/packages/CredentialManager/res/values-ru/strings.xml
index 3542edccb0c8..846df541961e 100644
--- a/packages/CredentialManager/res/values-ru/strings.xml
+++ b/packages/CredentialManager/res/values-ru/strings.xml
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Другие менеджеры паролей"</string>
<string name="close_sheet" msgid="1393792015338908262">"Закрыть лист"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Вернуться на предыдущую страницу"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Закрыть подсказку Менеджера учетных данных в нижней части экрана"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Закрыть"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Использовать сохраненный ключ доступа для приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Использовать сохраненные учетные данные для приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Выберите сохраненные данные для приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Варианты входа"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Для пользователя <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Заблокированные менеджеры паролей"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Нажмите для разблокировки"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Необходимо ввести учетные данные"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"В аккаунте <xliff:g id="SOURCE">%1$s</xliff:g> нет учетных данных"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Управление входом"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"С другого устройства"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Использовать другое устройство"</string>
diff --git a/packages/CredentialManager/res/values-si/strings.xml b/packages/CredentialManager/res/values-si/strings.xml
index 3064d2601879..1df8ea236be8 100644
--- a/packages/CredentialManager/res/values-si/strings.xml
+++ b/packages/CredentialManager/res/values-si/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"ඉදිරියට යන්න"</string>
<string name="string_more_options" msgid="7990658711962795124">"තවත් විකල්ප"</string>
<string name="string_learn_more" msgid="4541600451688392447">"තව දැන ගන්න"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"මුරපදය පෙන්වන්න"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"මුරපදය සඟවන්න"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"මුරයතුරු සමග සුරක්ෂිතයි"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"මුරයතුරු සමග, ඔබට සංකීර්ණ මුරපද තැනීමට හෝ මතක තබා ගැනීමට අවශ්‍ය නොවේ"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"මුරයතුරු යනු ඔබේ ඇඟිලි සලකුණ, මුහුණ, හෝ තිර අගුල භාවිතයෙන් ඔබ තනන සංකේතාත්මක ඩිජිටල් යතුරු වේ"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"වෙනත් මුරපද කළමනාකරුවන්"</string>
<string name="close_sheet" msgid="1393792015338908262">"පත්‍රය වසන්න"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"පෙර පිටුවට ආපසු යන්න"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"තිරයේ පහළින් දිස්වන අක්තපත්‍ර කළමනාකරු ක්‍රියා යෝජනාව වසන්න"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"වසන්න"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> සඳහා ඔබේ සුරැකි මුරයතුර භාවිතා කරන්න ද?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> සඳහා ඔබේ සුරැකි පුරනය භාවිතා කරන්න ද?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> සඳහා සුරැකි පුරනයක් තෝරා ගන්න"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"පුරනය වීමේ විකල්ප"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g> සඳහා"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"අගුළු දැමූ මුරපද කළමනාකරුවන්"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"අගුළු හැරීමට තට්ටු කරන්න"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"පුරනය වීමේ තතු නැත"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> තුළ පුරනය වීමේ තතු නැත"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"පුරනය වීම් කළමනාකරණය කරන්න"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"වෙනත් උපාංගයකින්"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"වෙනස් උපාංගයක් භාවිතා කරන්න"</string>
diff --git a/packages/CredentialManager/res/values-sk/strings.xml b/packages/CredentialManager/res/values-sk/strings.xml
index b7c3d2e217d0..eb187965dd8c 100644
--- a/packages/CredentialManager/res/values-sk/strings.xml
+++ b/packages/CredentialManager/res/values-sk/strings.xml
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Iní správcovia hesiel"</string>
<string name="close_sheet" msgid="1393792015338908262">"Zavrieť hárok"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Prejsť späť na predchádzajúcu stránku"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Zavrieť návrh akcie správcu prihlasovacích údajov dole na obrazovke"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Zavrieť"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Chcete pre aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g> použiť uložený prístupový kľúč?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Chcete pre aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g> použiť uložené prihlasovacie údaje?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Vyberte uložené prihlasovacie údaje pre aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Možnosti prihlásenia"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Pre používateľa <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Správcovia uzamknutých hesiel"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Odomknúť klepnutím"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Žiadne prihlasovacie údaje"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Žiadne prihlasovacie údaje v zdroji <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Spravovať prihlasovacie údaje"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Z iného zariadenia"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Použiť iné zariadenie"</string>
diff --git a/packages/CredentialManager/res/values-sl/strings.xml b/packages/CredentialManager/res/values-sl/strings.xml
index 3d70707cb598..15bcbae8c133 100644
--- a/packages/CredentialManager/res/values-sl/strings.xml
+++ b/packages/CredentialManager/res/values-sl/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Naprej"</string>
<string name="string_more_options" msgid="7990658711962795124">"Več možnosti"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Več o tem"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"Prikaz gesla"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Skrivanje gesla"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Večja varnost s ključi za dostop"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Po zaslugi ključev za dostop vam ni treba ustvarjati ali si zapomniti zapletenih gesel."</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Ključi za dostop so šifrirani digitalni ključi, ki jih ustvarite s prstnim odtisom, obrazom ali načinom zaklepanja zaslona."</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Drugi upravitelji gesel"</string>
<string name="close_sheet" msgid="1393792015338908262">"Zapri list"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Nazaj na prejšnjo stran"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Zaprtje na dnu zaslona prikazanega predloga dejanja upravitelja poverilnic"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Zapri"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Želite uporabiti shranjeni ključ za dostop do aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Želite uporabiti shranjene podatke za prijavo v aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Izberite shranjene podatke za prijavo v aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Možnosti prijave"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Za uporabnika <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Zaklenjeni upravitelji gesel"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Dotaknite se, da odklenete"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Ni nobenih podatkov za prijavo"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Ni nobenih podatkov za prijavo v »<xliff:g id="SOURCE">%1$s</xliff:g>«"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Upravljanje podatkov za prijavo"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Iz druge naprave"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Uporaba druge naprave"</string>
diff --git a/packages/CredentialManager/res/values-sq/strings.xml b/packages/CredentialManager/res/values-sq/strings.xml
index 4b7ff962fc75..1e4653836789 100644
--- a/packages/CredentialManager/res/values-sq/strings.xml
+++ b/packages/CredentialManager/res/values-sq/strings.xml
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Menaxherët e tjerë të fjalëkalimeve"</string>
<string name="close_sheet" msgid="1393792015338908262">"Mbyll fletën"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Kthehu te faqja e mëparshme"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Mbyll sugjerimin për veprimin e \"Menaxherit të kredencialeve\" që shfaqet në fund të ekranit"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Mbyll"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Të përdoret fjalëkalimi yt i ruajtur për <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Të përdoret identifikimi yt i ruajtur për <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Zgjidh një identifikim të ruajtur për <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Opsionet e identifikimit"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Për <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Menaxherët e fjalëkalimeve të kyçura"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Trokit për të shkyçur"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Nuk ka informacione për identifikimin"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Nuk ka informacione regjistrimi në <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Identifikimet e menaxhimit"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Nga një pajisje tjetër"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Përdor një pajisje tjetër"</string>
diff --git a/packages/CredentialManager/res/values-sr/strings.xml b/packages/CredentialManager/res/values-sr/strings.xml
index 6cd5d8d90fd4..bbb54633084d 100644
--- a/packages/CredentialManager/res/values-sr/strings.xml
+++ b/packages/CredentialManager/res/values-sr/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Настави"</string>
<string name="string_more_options" msgid="7990658711962795124">"Још опција"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Сазнајте више"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"Прикажите лозинку"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Сакријте лозинку"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Безбедније уз приступне кодове"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Уз приступне кодове нема потребе да правите или памтите сложене лозинке"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Приступни кодови су шифровани дигитални кодови које правите помоћу отиска прста, лица или закључавања екрана"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Други менаџери лозинки"</string>
<string name="close_sheet" msgid="1393792015338908262">"Затворите табелу"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Вратите се на претходну страницу"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Затворите предлог за радњу Менаџера акредитива који се приказује у дну екрана"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Затворите"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Желите да користите сачувани приступни кôд за: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Желите да користите сачуване податке за пријављивање за: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Одаберите сачувано пријављивање за: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Опције за пријављивање"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"За: <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Менаџери закључаних лозинки"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Додирните да бисте откључали"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Нема података за пријављивање"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Нема података за пријављивање у: <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Управљајте пријављивањима"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Са другог уређаја"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Користи други уређај"</string>
diff --git a/packages/CredentialManager/res/values-sv/strings.xml b/packages/CredentialManager/res/values-sv/strings.xml
index e061c9bcd25c..3d85e14ebb27 100644
--- a/packages/CredentialManager/res/values-sv/strings.xml
+++ b/packages/CredentialManager/res/values-sv/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Fortsätt"</string>
<string name="string_more_options" msgid="7990658711962795124">"Fler alternativ"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Läs mer"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"Visa lösenord"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Dölj lösenord"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Säkrare med nycklar"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Med nycklar behöver du inte skapa eller komma ihop invecklade lösenord"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Nycklar är krypterade digitala nycklar som du skapar med ditt fingeravtryck, ansikte eller skärmlås"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Andra lösenordshanterare"</string>
<string name="close_sheet" msgid="1393792015338908262">"Stäng kalkylarket"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Gå tillbaka till föregående sida"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Förslaget om att stänga Credential Manager visas längst ned på skärmen"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Stäng"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Vill du använda din sparade nyckel för <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Vill du använda dina sparade inloggningsuppgifter för <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Välj en sparad inloggning för <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Inloggningsalternativ"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"För <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Låsta lösenordshanterare"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Tryck för att låsa upp"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Ingen inloggningsinformation"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Det finns inga inloggningsuppgifter i <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Hantera inloggningar"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Via en annan enhet"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Använd en annan enhet"</string>
diff --git a/packages/CredentialManager/res/values-sw/strings.xml b/packages/CredentialManager/res/values-sw/strings.xml
index 9f30dbb860a0..f0f1db5ef08c 100644
--- a/packages/CredentialManager/res/values-sw/strings.xml
+++ b/packages/CredentialManager/res/values-sw/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Endelea"</string>
<string name="string_more_options" msgid="7990658711962795124">"Chaguo zaidi"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Pata maelezo zaidi"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"Onyesha nenosiri"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Ficha nenosiri"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Ni salama ukitumia funguo za siri"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Kwa kutumia funguo za siri, huhitaji kuunda au kukumbuka manenosiri changamano"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Funguo za siri ni funguo dijitali zilizosimbwa kwa njia fiche unazounda kwa kutumia alama yako ya kidole, uso au mbinu ya kufunga skrini"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Vidhibiti vinginevyo vya manenosiri"</string>
<string name="close_sheet" msgid="1393792015338908262">"Funga laha"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Rudi kwenye ukurasa uliotangulia"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Funga pendekezo la kitendo cha Kidhibiti cha Vitambulisho linaloonekana kwenye sehemu ya chini ya skrini"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Funga"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Ungependa kutumia ufunguo wa siri uliohifadhiwa wa<xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Ungependa kutumia kitambulisho kilichohifadhiwa cha kuingia katika akaunti ya <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Chagua vitambulisho vilivyohifadhiwa kwa ajili ya kuingia katika akaunti ya <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Chaguo za kuingia katika akaunti"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Kwa ajili ya <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Vidhibiti vya manenosiri vilivyofungwa"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Gusa ili ufungue"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Hakuna maelezo ya kuingia katika akaunti"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Hakuna maelezo ya kuingia katika akaunti kwenye <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Dhibiti michakato ya kuingia katika akaunti"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Kutoka kwenye kifaa kingine"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Tumia kifaa tofauti"</string>
diff --git a/packages/CredentialManager/res/values-ta/strings.xml b/packages/CredentialManager/res/values-ta/strings.xml
index 40410663a257..09a4fcbbd3f5 100644
--- a/packages/CredentialManager/res/values-ta/strings.xml
+++ b/packages/CredentialManager/res/values-ta/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"தொடர்க"</string>
<string name="string_more_options" msgid="7990658711962795124">"கூடுதல் விருப்பங்கள்"</string>
<string name="string_learn_more" msgid="4541600451688392447">"மேலும் அறிக"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"கடவுச்சொல்லைக் காட்டும்"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"கடவுச்சொல்லை மறைக்கும்"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"கடவுச்சாவிகள் மூலம் பாதுகாப்பாக வைத்திருங்கள்"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"கடவுச்சாவிகளைப் பயன்படுத்துவதன் மூலம் கடினமான கடவுச்சொற்களை உருவாக்கவோ நினைவில்கொள்ளவோ தேவையில்லை"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"கடவுச்சாவிகள் என்பவை உங்கள் கைரேகை, முகம் அல்லது திரைப் பூட்டு மூலம் உருவாக்கப்படும் என்க்ரிப்ஷன் செய்யப்பட்ட டிஜிட்டல் சாவிகள் ஆகும்"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"பிற கடவுச்சொல் நிர்வாகிகள்"</string>
<string name="close_sheet" msgid="1393792015338908262">"ஷீட்டை மூடும்"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"முந்தைய பக்கத்திற்குச் செல்லும்"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"அனுமதிச் சான்று நிர்வாகியின் நடவடிக்கை குறித்து திரையின் கீழ்ப்பகுதியில் காட்டப்படும் பரிந்துரையை மூடும்"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"மூடும்"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸுக்கு ஏற்கெனவே சேமிக்கப்பட்ட கடவுக்குறியீட்டைப் பயன்படுத்தவா?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸுக்கு ஏற்கெனவே சேமிக்கப்பட்ட உள்நுழைவுத் தகவலைப் பயன்படுத்தவா?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸுக்கு ஏற்கெனவே சேமிக்கப்பட்ட உள்நுழைவுத் தகவலைத் தேர்வுசெய்யவும்"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"உள்நுழைவு விருப்பங்கள்"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g>க்கு"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"பூட்டப்பட்ட கடவுச்சொல் நிர்வாகிகள்"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"அன்லாக் செய்ய தட்டவும்"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"உள்நுழைவு விவரங்கள் இல்லை"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> கணக்கில் உள்நுழைவு விவரங்கள் இல்லை"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"உள்நுழைவுகளை நிர்வகித்தல்"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"மற்றொரு சாதனத்திலிருந்து பயன்படுத்து"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"வேறு சாதனத்தைப் பயன்படுத்து"</string>
diff --git a/packages/CredentialManager/res/values-te/strings.xml b/packages/CredentialManager/res/values-te/strings.xml
index 6dd8204d4322..e93ff204f981 100644
--- a/packages/CredentialManager/res/values-te/strings.xml
+++ b/packages/CredentialManager/res/values-te/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"కొనసాగించండి"</string>
<string name="string_more_options" msgid="7990658711962795124">"మరిన్ని ఆప్షన్‌లు"</string>
<string name="string_learn_more" msgid="4541600451688392447">"మరింత తెలుసుకోండి"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"పాస్‌వర్డ్‌ను చూపండి"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"పాస్‌వర్డ్‌ను చూపవద్దు"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"పాస్-కీలతో సురక్షితంగా చెల్లించవచ్చు"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"పాస్-కీలతో, మీరు క్లిష్టమైన పాస్‌వర్డ్‌లను క్రియేట్ చేయనవసరం లేదు లేదా గుర్తుంచుకోనవసరం లేదు"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"పాస్-కీలు అనేవి మీ వేలిముద్రను, ముఖాన్ని లేదా స్క్రీన్ లాక్‌ను ఉపయోగించి మీరు క్రియేట్ చేసే ఎన్‌క్రిప్ట్ చేసిన డిజిటల్ కీలు"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"ఇతర పాస్‌వర్డ్ మేనేజర్‌లు"</string>
<string name="close_sheet" msgid="1393792015338908262">"షీట్‌ను మూసివేయండి"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"మునుపటి పేజీకి తిరిగి వెళ్లండి"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"స్క్రీన్ దిగువున కనిపించే ఆధారాల మేనేజర్ చర్య సూచనను మూసివేయండి"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"మూసివేస్తుంది"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> కోసం మీ సేవ్ చేసిన పాస్-కీ వివరాలను ఉపయోగించాలా?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> కోసం మీరు సేవ్ చేసిన సైన్ ఇన్ వివరాలను ఉపయోగించాలా?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> కోసం సేవ్ చేసిన సైన్ ఇన్ వివరాలను ఎంచుకోండి"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"సైన్ ఇన్ ఆప్షన్‌లు"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g> కోసం"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"లాక్ చేయబడిన పాస్‌వర్డ్ మేనేజర్‌లు"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"అన్‌లాక్ చేయడానికి ట్యాప్ చేయండి"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"సైన్ ఇన్ సమాచారం ఏదీ లేదు"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g>‌లో సైన్ ఇన్ సమాచారం లేదు"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"సైన్‌ ఇన్‌లను మేనేజ్ చేయండి"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"మరొక పరికరం నుండి"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"వేరే పరికరాన్ని ఉపయోగించండి"</string>
diff --git a/packages/CredentialManager/res/values-th/strings.xml b/packages/CredentialManager/res/values-th/strings.xml
index 78f89fc99fa0..e44a66d043b8 100644
--- a/packages/CredentialManager/res/values-th/strings.xml
+++ b/packages/CredentialManager/res/values-th/strings.xml
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"เครื่องมือจัดการรหัสผ่านอื่นๆ"</string>
<string name="close_sheet" msgid="1393792015338908262">"ปิดชีต"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"กลับไปยังหน้าก่อนหน้า"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"ปิดการแนะนำการดำเนินการของเครื่องมือจัดการข้อมูลเข้าสู่ระบบซึ่งปรากฏที่ด้านล่างของหน้าจอ"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"ปิด"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"ใช้พาสคีย์ที่บันทึกไว้สำหรับ \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" ใช่ไหม"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"ใช้การลงชื่อเข้าใช้ที่บันทึกไว้สำหรับ \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" ใช่ไหม"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"เลือกการลงชื่อเข้าใช้ที่บันทึกไว้สำหรับ \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"ตัวเลือกการลงชื่อเข้าใช้"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"สำหรับ <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"เครื่องมือจัดการรหัสผ่านที่ล็อกไว้"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"แตะเพื่อปลดล็อก"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"ไม่มีข้อมูลการลงชื่อเข้าใช้"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"ไม่มีข้อมูลการลงชื่อเข้าใช้ใน <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"จัดการการลงชื่อเข้าใช้"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"จากอุปกรณ์อื่น"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"ใช้อุปกรณ์อื่น"</string>
diff --git a/packages/CredentialManager/res/values-tl/strings.xml b/packages/CredentialManager/res/values-tl/strings.xml
index 431ce07bc572..6b48af148bca 100644
--- a/packages/CredentialManager/res/values-tl/strings.xml
+++ b/packages/CredentialManager/res/values-tl/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Magpatuloy"</string>
<string name="string_more_options" msgid="7990658711962795124">"Higit pang opsyon"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Matuto pa"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"Ipakita ang password"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Itago ang password"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Mas ligtas gamit ang mga passkey"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Gamit ang mga passkey, hindi mo na kailangang gumawa o tumanda ng mga komplikadong password"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Ang mga passkey ay mga naka-encrypt na digital na susi na ginagawa mo gamit ang iyong fingerprint, mukha, o lock ng screen"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Iba pang password manager"</string>
<string name="close_sheet" msgid="1393792015338908262">"Isara ang sheet"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Bumalik sa nakaraang page"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Isara ang suhestyon sa pagkilos ng Manager ng Kredensyal na lumalabas sa ibaba ng screen"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Isara"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Gamitin ang iyong naka-save na passkey para sa <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Gamitin ang iyong naka-save na sign-in para sa <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Pumili ng naka-save na sign-in para sa <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Mga opsyon sa pag-sign in"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Para kay <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Mga naka-lock na password manager"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"I-tap para i-unlock"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Walang impormasyon sa pag-sign in"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Walang impormasyon sa pag-sign in sa <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Pamahalaan ang mga sign-in"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Mula sa ibang device"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Gumamit ng ibang device"</string>
diff --git a/packages/CredentialManager/res/values-tr/strings.xml b/packages/CredentialManager/res/values-tr/strings.xml
index 0cf5cfd9c376..b0a354c7ce51 100644
--- a/packages/CredentialManager/res/values-tr/strings.xml
+++ b/packages/CredentialManager/res/values-tr/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Devam"</string>
<string name="string_more_options" msgid="7990658711962795124">"Diğer seçenekler"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Daha fazla bilgi"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"Şifreyi göster"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Şifreyi gizle"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Şifre anahtarlarıyla daha yüksek güvenlik"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Şifre anahtarı kullandığınızda karmaşık şifreler oluşturmanız veya bunları hatırlamanız gerekmez"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Şifre anahtarları; parmak iziniz, yüzünüz veya ekran kilidinizi kullanarak oluşturduğunuz şifrelenmiş dijital anahtarlardır"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Diğer şifre yöneticileri"</string>
<string name="close_sheet" msgid="1393792015338908262">"Sayfayı kapat"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Önceki sayfaya geri dön"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Ekranın altında görünen Kimlik Bilgisi Yöneticisi işlem önerisini kapatın"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Kapat"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> için kayıtlı şifre anahtarınız kullanılsın mı?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> için kayıtlı oturum açma bilgileriniz kullanılsın mı?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> için kayıtlı oturum açma bilgilerini kullanın"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Oturum açma seçenekleri"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g> için"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Kilitli şifre yöneticileri"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Kilidi açmak için dokunun"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Oturum açma bilgisi yok"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> hesabında oturum açma bilgisi yok"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Oturum açma bilgilerini yönetin"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Başka bir cihazdan"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Farklı bir cihaz kullan"</string>
diff --git a/packages/CredentialManager/res/values-uk/strings.xml b/packages/CredentialManager/res/values-uk/strings.xml
index 30c085e9e1e9..ec12bc6df62a 100644
--- a/packages/CredentialManager/res/values-uk/strings.xml
+++ b/packages/CredentialManager/res/values-uk/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Продовжити"</string>
<string name="string_more_options" msgid="7990658711962795124">"Інші опції"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Докладніше"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"Показати пароль"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Сховати пароль"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Ключі доступу покращують безпеку"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Маючи ключі доступу, не потрібно створювати чи запам’ятовувати складні паролі"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Ключі доступу – це зашифровані цифрові ключі, які ви створюєте за допомогою відбитка пальця, фейс-контролю чи засобу розблокування екрана"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Інші менеджери паролів"</string>
<string name="close_sheet" msgid="1393792015338908262">"Закрити аркуш"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Повернутися на попередню сторінку"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Закрити пропозицію Диспетчера облікових даних, що відображається внизу екрана"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Закрити"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Використати збережений ключ доступу для додатка <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Використати збережені дані для входу для додатка <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Виберіть збережені дані для входу в додаток <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Опції входу"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Для користувача <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Заблоковані менеджери паролів"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Торкніться, щоб розблокувати"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Немає даних для входу"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Немає даних для входу в обліковий запис <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Керування даними для входу"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"З іншого пристрою"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Використовувати інший пристрій"</string>
diff --git a/packages/CredentialManager/res/values-ur/strings.xml b/packages/CredentialManager/res/values-ur/strings.xml
index e1e530bf738f..b4bf77f060b2 100644
--- a/packages/CredentialManager/res/values-ur/strings.xml
+++ b/packages/CredentialManager/res/values-ur/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"جاری رکھیں"</string>
<string name="string_more_options" msgid="7990658711962795124">"مزید اختیارات"</string>
<string name="string_learn_more" msgid="4541600451688392447">"مزید جانیں"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"پاس ورڈ دکھائیں"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"پاس ورڈ چھپائیں"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"پاس کیز کے ساتھ زیادہ محفوظ"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"پاس کیز کے ساتھ آپ کو پیچیدہ پاس ورڈز تخلیق کرنے یا انہیں یاد رکھنے کی ضرورت نہیں ہے"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"پاس کیز مرموز کردہ ڈیجیٹل کلیدیں ہیں جنہیں آپ اپنا فنگر پرنٹ، چہرہ یا اسکرین لاک استعمال کرتے ہوئے تخلیق کرتے ہیں"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"دیگر پاس ورڈ مینیجرز"</string>
<string name="close_sheet" msgid="1393792015338908262">"شیٹ بند کریں"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"گزشتہ صفحے پر واپس جائیں"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"اسکرین کے نیچے ظاہر ہونے والے سند مینیجر کی کاروائی کی تجویز بند کریں"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"بند کریں"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> کے لیے اپنی محفوظ کردہ پاس کی استعمال کریں؟"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> کے لیے اپنے محفوظ کردہ سائن ان کو استعمال کریں؟"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> کے لیے محفوظ کردہ سائن انز منتخب کریں"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"سائن ان کے اختیارات"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g> کے لیے"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"مقفل کردہ پاس ورڈ مینیجرز"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"غیر مقفل کرنے کیلئے تھپتھپائیں"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"سائن ان کی کوئی معلومات نہیں"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> میں سائن ان کی کوئی معلومات نہیں ہے"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"سائن انز کا نظم کریں"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"دوسرے آلے سے"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"ایک مختلف آلہ استعمال کریں"</string>
diff --git a/packages/CredentialManager/res/values-uz/strings.xml b/packages/CredentialManager/res/values-uz/strings.xml
index 96bcbc89c0a5..92c40eea8ab3 100644
--- a/packages/CredentialManager/res/values-uz/strings.xml
+++ b/packages/CredentialManager/res/values-uz/strings.xml
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Boshqa parol menejerlari"</string>
<string name="close_sheet" msgid="1393792015338908262">"Varaqni yopish"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Avvalgi sahifaga qaytish"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Ekranning pastki qismida chiqadigan Hisob maʼlumotlari menejeri amali taklifini yoping"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Yopish"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> uchun saqlangan kalit ishlatilsinmi?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> uchun saqlangan maʼlumotlar ishlatilsinmi?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> hisob maʼlumotlarini tanlang"</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Kirish parametrlari"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g> uchun"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Qulfli parol menejerlari"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Qulfni ochish uchun bosing"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Kirishga oid axborot topilmadi"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> kirish axboroti mavjud emas"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Hisob maʼlumotlarini boshqarish"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Boshqa qurilmada"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Boshqa qurilmadan foydalanish"</string>
diff --git a/packages/CredentialManager/res/values-vi/strings.xml b/packages/CredentialManager/res/values-vi/strings.xml
index 61b425eee5a0..dd0aeed5cd9b 100644
--- a/packages/CredentialManager/res/values-vi/strings.xml
+++ b/packages/CredentialManager/res/values-vi/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"Tiếp tục"</string>
<string name="string_more_options" msgid="7990658711962795124">"Tuỳ chọn khác"</string>
<string name="string_learn_more" msgid="4541600451688392447">"Tìm hiểu thêm"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"Hiện mật khẩu"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"Ẩn mật khẩu"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"An toàn hơn nhờ mã xác thực"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Mã xác thực giúp bạn tránh được việc phải tạo và ghi nhớ mật khẩu phức tạp"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Mã xác thực là các khoá kỹ thuật số được mã hoá mà bạn tạo bằng cách dùng vân tay, khuôn mặt hoặc phương thức khoá màn hình của mình"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Trình quản lý mật khẩu khác"</string>
<string name="close_sheet" msgid="1393792015338908262">"Đóng trang tính"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Quay lại trang trước"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Đóng đề xuất hành động của Trình quản lý thông tin xác thực xuất hiện ở cuối màn hình"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Đóng"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Dùng mã xác thực bạn đã lưu cho <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Dùng thông tin đăng nhập bạn đã lưu cho <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Chọn thông tin đăng nhập đã lưu cho <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Tuỳ chọn đăng nhập"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Cho <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Trình quản lý mật khẩu đã khoá"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Nhấn để mở khoá"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Không có thông tin đăng nhập"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Không có thông tin đăng nhập trong <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Quản lý thông tin đăng nhập"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Từ một thiết bị khác"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Dùng thiết bị khác"</string>
diff --git a/packages/CredentialManager/res/values-zh-rCN/strings.xml b/packages/CredentialManager/res/values-zh-rCN/strings.xml
index d03be7727759..87bdce3ead2d 100644
--- a/packages/CredentialManager/res/values-zh-rCN/strings.xml
+++ b/packages/CredentialManager/res/values-zh-rCN/strings.xml
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"其他密码管理工具"</string>
<string name="close_sheet" msgid="1393792015338908262">"关闭工作表"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"返回上一页"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"关闭屏幕底部显示的 Credential Manager 操作建议"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"关闭"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"将您已保存的通行密钥用于<xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"将您已保存的登录信息用于<xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"为<xliff:g id="APP_NAME">%1$s</xliff:g>选择已保存的登录信息"</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"登录选项"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"用户:<xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"已锁定的密码管理工具"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"点按即可解锁"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"无登录信息"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> 中没有任何登录信息"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"管理登录信息"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"通过另一台设备"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"使用其他设备"</string>
diff --git a/packages/CredentialManager/res/values-zh-rHK/strings.xml b/packages/CredentialManager/res/values-zh-rHK/strings.xml
index 8ddd4bef8e4d..b8d5fc56d5f9 100644
--- a/packages/CredentialManager/res/values-zh-rHK/strings.xml
+++ b/packages/CredentialManager/res/values-zh-rHK/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"繼續"</string>
<string name="string_more_options" msgid="7990658711962795124">"更多選項"</string>
<string name="string_learn_more" msgid="4541600451688392447">"瞭解詳情"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"顯示密碼"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"隱藏密碼"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"使用密鑰確保帳戶安全"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"有了密鑰,您便無需建立或記住複雜的密碼"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"密鑰是您使用指紋、面孔或螢幕鎖定時建立的加密數碼鑰匙"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"其他密碼管理工具"</string>
<string name="close_sheet" msgid="1393792015338908262">"閂工作表"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"返回上一頁"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"閂顯示喺螢幕底部嘅憑證管理工具操作建議"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"關閉"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"要使用已儲存的「<xliff:g id="APP_NAME">%1$s</xliff:g>」密鑰嗎?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"要使用已儲存的「<xliff:g id="APP_NAME">%1$s</xliff:g>」登入資料嗎?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"選擇已儲存的「<xliff:g id="APP_NAME">%1$s</xliff:g>」登入資料"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"登入選項"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g> 專用"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"已鎖定的密碼管理工具"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"輕按即可解鎖"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"沒有登入資料"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> 中沒有登入資料"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"管理登入資料"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"透過其他裝置"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"使用其他裝置"</string>
diff --git a/packages/CredentialManager/res/values-zh-rTW/strings.xml b/packages/CredentialManager/res/values-zh-rTW/strings.xml
index 7e42d5693d89..885753ac4280 100644
--- a/packages/CredentialManager/res/values-zh-rTW/strings.xml
+++ b/packages/CredentialManager/res/values-zh-rTW/strings.xml
@@ -6,10 +6,8 @@
<string name="string_continue" msgid="1346732695941131882">"繼續"</string>
<string name="string_more_options" msgid="7990658711962795124">"更多選項"</string>
<string name="string_learn_more" msgid="4541600451688392447">"瞭解詳情"</string>
- <!-- no translation found for content_description_show_password (3283502010388521607) -->
- <skip />
- <!-- no translation found for content_description_hide_password (6841375971631767996) -->
- <skip />
+ <string name="content_description_show_password" msgid="3283502010388521607">"顯示密碼"</string>
+ <string name="content_description_hide_password" msgid="6841375971631767996">"隱藏密碼"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"使用密碼金鑰確保帳戶安全"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"有了密碼金鑰,就不必建立或記住複雜的密碼"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"密碼金鑰是你利用指紋、臉孔或螢幕鎖定功能建立的加密數位金鑰"</string>
@@ -49,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"其他密碼管理工具"</string>
<string name="close_sheet" msgid="1393792015338908262">"關閉功能表"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"返回上一頁"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"關閉顯示在畫面底部的憑證管理工具操作建議"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"關閉"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"要使用已儲存的「<xliff:g id="APP_NAME">%1$s</xliff:g>」密碼金鑰嗎?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"要使用已儲存的「<xliff:g id="APP_NAME">%1$s</xliff:g>」登入資訊嗎?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"選擇已儲存的「<xliff:g id="APP_NAME">%1$s</xliff:g>」登入資訊"</string>
@@ -59,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"登入選項"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"<xliff:g id="USERNAME">%1$s</xliff:g> 專用"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"已鎖定的密碼管理工具"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"輕觸即可解鎖"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"沒有登入資訊"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> 中沒有登入資訊"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"管理登入資訊"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"透過其他裝置"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"使用其他裝置"</string>
diff --git a/packages/CredentialManager/res/values-zu/strings.xml b/packages/CredentialManager/res/values-zu/strings.xml
index 7a407716ee13..f077d571e8a7 100644
--- a/packages/CredentialManager/res/values-zu/strings.xml
+++ b/packages/CredentialManager/res/values-zu/strings.xml
@@ -47,7 +47,9 @@
<string name="other_password_manager" msgid="565790221427004141">"Abanye abaphathi bephasiwedi"</string>
<string name="close_sheet" msgid="1393792015338908262">"Vala ishidi"</string>
<string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Buyela emuva ekhasini langaphambilini"</string>
- <string name="accessibility_close_button" msgid="2953807735590034688">"Vala isiphakamiso sesenzo Somphathi Wezimfanelo esivela phansi esikrinini"</string>
+ <string name="accessibility_close_button" msgid="1163435587545377687">"Vala"</string>
+ <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+ <skip />
<string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Sebenzisa ukhiye wakho wokungena olondoloziwe <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Sebenzisa ukungena kwakho ngemvume okulondoloziwe <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
<string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Khetha ukungena ngemvume okulondoloziwe kwakho <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -57,10 +59,9 @@
<string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Okungakhethwa kukho kokungena ngemvume"</string>
<string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Okuka-<xliff:g id="USERNAME">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Abaphathi bephasiwedi abakhiyiwe"</string>
- <!-- no translation found for locked_credential_entry_label_subtext_tap_to_unlock (6390367581393605009) -->
- <skip />
- <!-- no translation found for locked_credential_entry_label_subtext_no_sign_in (8131725029983174901) -->
- <skip />
+ <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Thepha ukuze uvule"</string>
+ <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Alukho ulwazi lokungena ngemvume"</string>
+ <string name="no_sign_in_info_in" msgid="2641118151920288356">"Alukho ulwazi lokungena ngemvume lwe-<xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Phatha ukungena ngemvume"</string>
<string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Kusukela kwenye idivayisi"</string>
<string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Sebenzisa idivayisi ehlukile"</string>
diff --git a/packages/CredentialManager/res/values/strings.xml b/packages/CredentialManager/res/values/strings.xml
index 3eb58f1532d8..f655d6b174d5 100644
--- a/packages/CredentialManager/res/values/strings.xml
+++ b/packages/CredentialManager/res/values/strings.xml
@@ -42,7 +42,7 @@
<!-- Title for subsection of "Learn more about passkeys" screen about seamless transition. [CHAR LIMIT=80] -->
<string name="seamless_transition_title">Seamless transition</string>
<!-- Detail for subsection of "Learn more about passkeys" screen about seamless transition. [CHAR LIMIT=500] -->
- <string name="seamless_transition_detail">As we move towards a passwordless future, passwords will still be available alongside passkeys.</string>
+ <string name="seamless_transition_detail">As we move towards a passwordless future, passwords will still be available alongside passkeys</string>
<!-- This appears as the title of the modal bottom sheet which provides all available providers for users to choose. [CHAR LIMIT=200] -->
<string name="choose_provider_title">Choose where to save your <xliff:g id="createTypes" example="passkeys">%1$s</xliff:g></string>
<!-- This appears as the description body of the modal bottom sheet which provides all available providers for users to choose. [CHAR LIMIT=200] -->
@@ -67,9 +67,8 @@
<string name="create_passkey_in_other_device_title">Create passkey in another device?</string>
<!-- This appears as the title of the modal bottom sheet for users to confirm whether they should use the selected provider as default or not. [CHAR LIMIT=200] -->
<string name="use_provider_for_all_title">Use <xliff:g id="providerInfoDisplayName" example="Google Password Manager">%1$s</xliff:g> for all your sign-ins?</string>
- <!-- TODO: Check the wording here. -->
- <!-- This appears as the description body of the modal bottom sheet for users to confirm whether they should use the selected provider as default or not. [CHAR LIMIT=200] -->
- <string name="use_provider_for_all_description">This password manager will store your passwords and passkeys to help you easily sign in</string>
+ <!-- This appears as the description body of the modal bottom sheet for users to confirm whether they should use the selected provider as default or not. [CHAR LIMIT=300] -->
+ <string name="use_provider_for_all_description">This password manager for <xliff:g id="username" example="becket@gmail.com">%1$s</xliff:g> will store your passwords and passkeys to help you easily sign in</string>
<!-- This is a label for a button that sets this password manager as the default. [CHAR LIMIT=20] -->
<string name="set_as_default">Set as default</string>
<!-- This is a label for a button that makes this password manager be used just in this specific case. [CHAR LIMIT=20] -->
@@ -94,6 +93,8 @@
<string name="accessibility_back_arrow_button">"Go back to the previous page"</string>
<!-- Spoken content description of the close "X" icon button. -->
<string name="accessibility_close_button">Close</string>
+ <!-- Spoken content description of the close "X" icon button. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_snackbar_dismiss">Dismiss</string>
<!-- Strings for the get flow. -->
<!-- This appears as the title of the modal bottom sheet asking for user confirmation to use the single previously saved passkey to sign in to the app. [CHAR LIMIT=200] -->
@@ -109,7 +110,7 @@
<!-- This is a label for a button that takes user to the next screen. [CHAR LIMIT=20] -->
<string name="get_dialog_button_label_continue">Continue</string>
<!-- Separator for sign-in type and username in a sign-in entry. -->
- <string name="get_dialog_sign_in_type_username_separator" translatable="false">" - "</string>
+ <string name="get_dialog_sign_in_type_username_separator" translatable="false">" • "</string>
<!-- This text is followed by a list of one or more options. [CHAR LIMIT=80] -->
<string name="get_dialog_title_sign_in_options">Sign-in options</string>
<!-- Column heading for displaying sign-ins for a specific username. [CHAR LIMIT=80] -->
diff --git a/packages/CredentialManager/res/values/themes.xml b/packages/CredentialManager/res/values/themes.xml
index a58a0383b9b2..428c85ac721f 100644
--- a/packages/CredentialManager/res/values/themes.xml
+++ b/packages/CredentialManager/res/values/themes.xml
@@ -1,13 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
-
- <style name="Theme.CredentialSelector" parent="@android:style/ThemeOverlay.Material">
- <item name="android:statusBarColor">@android:color/transparent</item>
+ <style name="Theme.CredentialSelector" parent="@*android:style/ThemeOverlay.DeviceDefault.Accent.DayNight">
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowIsTranslucent">true</item>
- <item name="android:colorBackgroundCacheHint">@null</item>
- <item name="fontFamily">google-sans</item>
</style>
</resources> \ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
index 0d25bece62a6..a2d1e4de8e35 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
@@ -16,8 +16,6 @@
package com.android.credentialmanager
-import android.app.slice.Slice
-import android.app.slice.SliceSpec
import android.content.Context
import android.content.Intent
import android.credentials.CreateCredentialRequest
@@ -25,6 +23,7 @@ import android.credentials.Credential.TYPE_PASSWORD_CREDENTIAL
import android.credentials.CredentialOption
import android.credentials.GetCredentialRequest
import android.credentials.ui.AuthenticationEntry
+import android.credentials.ui.CancelUiRequest
import android.credentials.ui.Constants
import android.credentials.ui.Entry
import android.credentials.ui.CreateCredentialProviderData
@@ -35,7 +34,6 @@ import android.credentials.ui.RequestInfo
import android.credentials.ui.BaseDialogResult
import android.credentials.ui.ProviderPendingIntentResponse
import android.credentials.ui.UserSelectionDialogResult
-import android.net.Uri
import android.os.IBinder
import android.os.Binder
import android.os.Bundle
@@ -47,6 +45,8 @@ import com.android.credentialmanager.getflow.GetCredentialUiState
import androidx.credentials.CreateCredentialRequest.DisplayInfo
import androidx.credentials.CreatePublicKeyCredentialRequest
import androidx.credentials.CreatePasswordRequest
+import androidx.credentials.GetPasswordOption
+import androidx.credentials.GetPublicKeyCredentialOption
import java.time.Instant
@@ -73,7 +73,13 @@ class CredentialManagerRepo(
requestInfo = intent.extras?.getParcelable(
RequestInfo.EXTRA_REQUEST_INFO,
RequestInfo::class.java
- ) ?: testCreatePasskeyRequestInfo()
+ ) ?: testGetRequestInfo()
+
+ val originName: String? = when (requestInfo.type) {
+ RequestInfo.TYPE_CREATE -> requestInfo.createCredentialRequest?.origin
+ RequestInfo.TYPE_GET -> requestInfo.getCredentialRequest?.origin
+ else -> null
+ }
providerEnabledList = when (requestInfo.type) {
RequestInfo.TYPE_CREATE ->
@@ -108,15 +114,15 @@ class CredentialManagerRepo(
val isPasskeyFirstUse = userConfigRepo.getIsPasskeyFirstUse()
val providerEnableListUiState = getCreateProviderEnableListInitialUiState()
val providerDisableListUiState = getCreateProviderDisableListInitialUiState()
- val requestDisplayInfoUiState = getCreateRequestDisplayInfoInitialUiState()!!
+ val requestDisplayInfoUiState =
+ getCreateRequestDisplayInfoInitialUiState(originName)!!
UiState(
createCredentialUiState = CreateFlowUtils.toCreateCredentialUiState(
providerEnableListUiState,
providerDisableListUiState,
defaultProviderId,
requestDisplayInfoUiState,
- /** isOnPasskeyIntroStateAlready = */
- false,
+ isOnPasskeyIntroStateAlready = false,
isPasskeyFirstUse
)!!,
getCredentialUiState = null,
@@ -124,7 +130,7 @@ class CredentialManagerRepo(
}
RequestInfo.TYPE_GET -> UiState(
createCredentialUiState = null,
- getCredentialUiState = getCredentialInitialUiState()!!,
+ getCredentialUiState = getCredentialInitialUiState(originName)!!,
)
else -> throw IllegalStateException("Unrecognized request type: ${requestInfo.type}")
}
@@ -175,11 +181,11 @@ class CredentialManagerRepo(
}
// IMPORTANT: new invocation should be mindful that this method can throw.
- private fun getCredentialInitialUiState(): GetCredentialUiState? {
+ private fun getCredentialInitialUiState(originName: String?): GetCredentialUiState? {
val providerEnabledList = GetFlowUtils.toProviderList(
providerEnabledList as List<GetCredentialProviderData>, context
)
- val requestDisplayInfo = GetFlowUtils.toRequestDisplayInfo(requestInfo, context)
+ val requestDisplayInfo = GetFlowUtils.toRequestDisplayInfo(requestInfo, context, originName)
return GetCredentialUiState(
providerEnabledList,
requestDisplayInfo ?: return null,
@@ -201,8 +207,10 @@ class CredentialManagerRepo(
)
}
- private fun getCreateRequestDisplayInfoInitialUiState(): RequestDisplayInfo? {
- return CreateFlowUtils.toRequestDisplayInfo(requestInfo, context)
+ private fun getCreateRequestDisplayInfoInitialUiState(
+ originName: String?
+ ): RequestDisplayInfo? {
+ return CreateFlowUtils.toRequestDisplayInfo(requestInfo, context, originName)
}
companion object {
@@ -217,6 +225,14 @@ class CredentialManagerRepo(
resultReceiver.send(cancelCode, resultData)
}
}
+
+ /** Return the request token whose UI should be cancelled, or null otherwise. */
+ fun getCancelUiRequestToken(intent: Intent): IBinder? {
+ return intent.extras?.getParcelable(
+ CancelUiRequest.EXTRA_CANCEL_UI_REQUEST,
+ CancelUiRequest::class.java
+ )?.token
+ }
}
// TODO: below are prototype functionalities. To be removed for productionization.
@@ -230,7 +246,8 @@ class CredentialManagerRepo(
context,
"key1", "subkey-1", "elisa.beckett@gmail.com",
20, 7, 27, Instant.ofEpochSecond(10L),
- "Legal note"
+ "You can use your passkey on this or other devices. It is saved to " +
+ "the Password Manager for elisa.beckett@gmail.com."
),
CreateTestUtils.newCreateEntry(
context,
@@ -239,11 +256,9 @@ class CredentialManagerRepo(
null
),
)
- )
- .setRemoteEntry(
- newRemoteEntry("key2", "subkey-1")
- )
- .build(),
+ ).setRemoteEntry(
+ CreateTestUtils.newRemoteCreateEntry(context, "key2", "subkey-1")
+ ).build(),
CreateCredentialProviderData
.Builder("com.dashlane")
.setSaveEntries(
@@ -258,11 +273,11 @@ class CredentialManagerRepo(
context,
"key1", "subkey-4", "elisa.work@dashlane.com",
20, 7, 27, Instant.ofEpochSecond(14L),
- null
+ "You can use your passkey on this or other devices. It is saved to " +
+ "the Password Manager for elisa.work@dashlane.com"
),
)
- )
- .build(),
+ ).build(),
)
}
@@ -318,7 +333,7 @@ class CredentialManagerRepo(
),
)
).setRemoteEntry(
- newRemoteEntry("key4", "subkey-1")
+ GetTestUtils.newRemoteCredentialEntry(context, "key4", "subkey-1")
).build(),
GetCredentialProviderData.Builder("com.dashlane")
.setCredentialEntries(
@@ -333,10 +348,12 @@ class CredentialManagerRepo(
),
)
).setAuthenticationEntries(
- listOf(GetTestUtils.newAuthenticationEntry(
- context, "key2", "subkey-1", "foo@email.com",
- AuthenticationEntry.STATUS_UNLOCKED_BUT_EMPTY_LESS_RECENT
- ))
+ listOf(
+ GetTestUtils.newAuthenticationEntry(
+ context, "key2", "subkey-1", "foo@email.com",
+ AuthenticationEntry.STATUS_UNLOCKED_BUT_EMPTY_LESS_RECENT,
+ )
+ )
).setActionChips(
listOf(
GetTestUtils.newActionEntry(
@@ -348,20 +365,6 @@ class CredentialManagerRepo(
)
}
-
- private fun newRemoteEntry(
- key: String,
- subkey: String,
- ): Entry {
- return Entry(
- key,
- subkey,
- Slice.Builder(
- Uri.EMPTY, SliceSpec("type", 1)
- ).build()
- )
- }
-
private fun testCreatePasskeyRequestInfo(): RequestInfo {
val request = CreatePublicKeyCredentialRequest(
"{\"extensions\": {\n" +
@@ -398,34 +401,31 @@ class CredentialManagerRepo(
" \"authenticatorSelection\": {\n" +
" \"residentKey\": \"required\",\n" +
" \"requireResidentKey\": true\n" +
- " }}"
+ " }}",
+ preferImmediatelyAvailableCredentials = true,
)
val credentialData = request.credentialData
return RequestInfo.newCreateRequestInfo(
- Binder(),
- CreateCredentialRequest(
- "androidx.credentials.TYPE_PUBLIC_KEY_CREDENTIAL",
- credentialData,
- /*candidateQueryData=*/ Bundle(),
- /*isSystemProviderRequired=*/ false,
- /*alwaysSendAppInfoToProvider=*/ true
- ),
- "com.google.android.youtube"
+ Binder(),
+ CreateCredentialRequest.Builder("androidx.credentials.TYPE_PUBLIC_KEY_CREDENTIAL",
+ credentialData, Bundle())
+ .setIsSystemProviderRequired(false)
+ .setAlwaysSendAppInfoToProvider(true)
+ .build(),
+ "com.google.android.youtube"
)
}
private fun testCreatePasswordRequestInfo(): RequestInfo {
val request = CreatePasswordRequest("beckett-bakert@gmail.com", "password123")
return RequestInfo.newCreateRequestInfo(
- Binder(),
- CreateCredentialRequest(
- TYPE_PASSWORD_CREDENTIAL,
- request.credentialData,
- request.candidateQueryData,
- /*isSystemProviderRequired=*/ false,
- /*alwaysSendAppInfoToProvider=*/ true
- ),
- "com.google.android.youtube"
+ Binder(),
+ CreateCredentialRequest.Builder(TYPE_PASSWORD_CREDENTIAL,
+ request.credentialData, request.candidateQueryData)
+ .setIsSystemProviderRequired(false)
+ .setAlwaysSendAppInfoToProvider(true)
+ .build(),
+ "com.google.android.youtube"
)
}
@@ -437,32 +437,38 @@ class CredentialManagerRepo(
displayInfo.toBundle()
)
return RequestInfo.newCreateRequestInfo(
- Binder(),
- CreateCredentialRequest(
- "other-sign-ins",
- data,
- /*candidateQueryData=*/ Bundle(),
- /*isSystemProviderRequired=*/ false,
- /*alwaysSendAppInfoToProvider=*/ true
- ),
- "com.google.android.youtube"
+ Binder(),
+ CreateCredentialRequest.Builder("other-sign-ins", data, Bundle())
+ .setIsSystemProviderRequired(false)
+ .setAlwaysSendAppInfoToProvider(true)
+ .build(),
+ "com.google.android.youtube"
)
}
private fun testGetRequestInfo(): RequestInfo {
+ val passwordOption = GetPasswordOption()
+ val passkeyOption = GetPublicKeyCredentialOption(
+ "json", preferImmediatelyAvailableCredentials = false)
return RequestInfo.newGetRequestInfo(
Binder(),
GetCredentialRequest.Builder(
Bundle()
).addCredentialOption(
CredentialOption(
- "androidx.credentials.TYPE_PUBLIC_KEY_CREDENTIAL",
- Bundle(),
- Bundle(), /*isSystemProviderRequired=*/
- false
+ passwordOption.type,
+ passwordOption.requestData,
+ passwordOption.candidateQueryData,
+ passwordOption.isSystemProviderRequired
)
- )
- .build(),
+ ).addCredentialOption(
+ CredentialOption(
+ passkeyOption.type,
+ passkeyOption.requestData,
+ passkeyOption.candidateQueryData,
+ passkeyOption.isSystemProviderRequired
+ )
+ ).build(),
"com.google.android.youtube"
)
}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialProviderReceiver.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialProviderReceiver.kt
new file mode 100644
index 000000000000..ee8cffed7f7d
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialProviderReceiver.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 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.credentialmanager
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.util.Log
+import com.android.credentialmanager.common.Constants
+
+
+class CredentialProviderReceiver : BroadcastReceiver() {
+
+ override fun onReceive(context: Context?, intent: Intent?) {
+ Log.d(Constants.LOG_TAG, "Received intent in CredentialProviderReceiver")
+
+ val sharedPreferences = context?.getSharedPreferences(context?.packageName,
+ Context.MODE_PRIVATE)
+ sharedPreferences?.edit()?.remove(UserConfigRepo.DEFAULT_PROVIDER)?.commit()
+ }
+} \ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
index d618e746f4b8..e8e39741c3bd 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
@@ -39,7 +39,7 @@ import com.android.credentialmanager.createflow.CreateCredentialScreen
import com.android.credentialmanager.createflow.hasContentToDisplay
import com.android.credentialmanager.getflow.GetCredentialScreen
import com.android.credentialmanager.getflow.hasContentToDisplay
-import com.android.credentialmanager.ui.theme.CredentialSelectorTheme
+import com.android.credentialmanager.ui.theme.PlatformTheme
@ExperimentalMaterialApi
class CredentialSelectorActivity : ComponentActivity() {
@@ -47,10 +47,16 @@ class CredentialSelectorActivity : ComponentActivity() {
super.onCreate(savedInstanceState)
Log.d(Constants.LOG_TAG, "Creating new CredentialSelectorActivity")
try {
+ if (CredentialManagerRepo.getCancelUiRequestToken(intent) != null) {
+ Log.d(
+ Constants.LOG_TAG, "Received UI cancellation intent; cancelling the activity.")
+ this.finish()
+ return
+ }
val userConfigRepo = UserConfigRepo(this)
val credManRepo = CredentialManagerRepo(this, intent, userConfigRepo)
setContent {
- CredentialSelectorTheme {
+ PlatformTheme {
CredentialManagerBottomSheet(
credManRepo,
userConfigRepo
@@ -67,10 +73,19 @@ class CredentialSelectorActivity : ComponentActivity() {
setIntent(intent)
Log.d(Constants.LOG_TAG, "Existing activity received new intent")
try {
- val userConfigRepo = UserConfigRepo(this)
- val credManRepo = CredentialManagerRepo(this, intent, userConfigRepo)
+ val cancelUiRequestToken = CredentialManagerRepo.getCancelUiRequestToken(intent)
val viewModel: CredentialSelectorViewModel by viewModels()
- viewModel.onNewCredentialManagerRepo(credManRepo)
+ if (cancelUiRequestToken != null &&
+ viewModel.shouldCancelCurrentUi(cancelUiRequestToken)) {
+ Log.d(
+ Constants.LOG_TAG, "Received UI cancellation intent; cancelling the activity.")
+ this.finish()
+ return
+ } else {
+ val userConfigRepo = UserConfigRepo(this)
+ val credManRepo = CredentialManagerRepo(this, intent, userConfigRepo)
+ viewModel.onNewCredentialManagerRepo(credManRepo)
+ }
} catch (e: Exception) {
onInitializationError(e, intent)
}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
index a1e0823e4f96..a5c749432753 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
@@ -17,6 +17,7 @@
package com.android.credentialmanager
import android.app.Activity
+import android.os.IBinder
import android.util.Log
import androidx.activity.compose.ManagedActivityResultLauncher
import androidx.activity.result.ActivityResult
@@ -129,12 +130,22 @@ class CredentialSelectorViewModel(
onInternalError()
}
+ fun onIllegalUiState(errorMessage: String) {
+ Log.w(Constants.LOG_TAG, errorMessage)
+ onInternalError()
+ }
+
private fun onInternalError() {
Log.w(Constants.LOG_TAG, "UI closed due to illegal internal state")
credManRepo.onParsingFailureCancel()
uiState = uiState.copy(dialogState = DialogState.COMPLETE)
}
+ /** Return true if the current UI's request token matches the UI cancellation request token. */
+ fun shouldCancelCurrentUi(cancelRequestToken: IBinder): Boolean {
+ return credManRepo.requestInfo.token.equals(cancelRequestToken)
+ }
+
/**************************************************************************/
/***** Get Flow Callbacks *****/
/**************************************************************************/
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
index aa0959c82b4b..96e2d3f4e357 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
@@ -50,7 +50,9 @@ import com.android.credentialmanager.getflow.RemoteEntryInfo
import androidx.credentials.CreateCredentialRequest
import androidx.credentials.CreateCustomCredentialRequest
import androidx.credentials.CreatePasswordRequest
+import androidx.credentials.CredentialOption
import androidx.credentials.CreatePublicKeyCredentialRequest
+import androidx.credentials.GetPublicKeyCredentialOption
import androidx.credentials.PublicKeyCredential.Companion.TYPE_PUBLIC_KEY_CREDENTIAL
import androidx.credentials.provider.Action
import androidx.credentials.provider.AuthenticationAction
@@ -147,7 +149,10 @@ class GetFlowUtils {
icon = providerIcon,
displayName = providerLabel,
credentialEntryList = getCredentialOptionInfoList(
- it.providerFlattenedComponentName, it.credentialEntries, context
+ providerId = it.providerFlattenedComponentName,
+ providerLabel = providerLabel,
+ credentialEntries = it.credentialEntries,
+ context = context
),
authenticationEntryList = getAuthenticationEntryList(
it.providerFlattenedComponentName,
@@ -170,10 +175,27 @@ class GetFlowUtils {
fun toRequestDisplayInfo(
requestInfo: RequestInfo,
context: Context,
+ originName: String?,
): com.android.credentialmanager.getflow.RequestDisplayInfo? {
+ val getCredentialRequest = requestInfo.getCredentialRequest ?: return null
+ val preferImmediatelyAvailableCredentials = getCredentialRequest.credentialOptions.any {
+ val credentialOptionJetpack = CredentialOption.createFrom(
+ it.type,
+ it.credentialRetrievalData,
+ it.credentialRetrievalData,
+ it.isSystemProviderRequired
+ )
+ if (credentialOptionJetpack is GetPublicKeyCredentialOption) {
+ credentialOptionJetpack.preferImmediatelyAvailableCredentials
+ } else {
+ false
+ }
+ }
return com.android.credentialmanager.getflow.RequestDisplayInfo(
- appName = getAppLabel(context.packageManager, requestInfo.appPackageName)
- ?: return null
+ appName = originName
+ ?: getAppLabel(context.packageManager, requestInfo.appPackageName)
+ ?: return null,
+ preferImmediatelyAvailableCredentials = preferImmediatelyAvailableCredentials
)
}
@@ -183,6 +205,7 @@ class GetFlowUtils {
*/
private fun getCredentialOptionInfoList(
providerId: String,
+ providerLabel: String,
credentialEntries: List<Entry>,
context: Context,
): List<CredentialEntryInfo> {
@@ -193,6 +216,7 @@ class GetFlowUtils {
is PasswordCredentialEntry -> {
result.add(CredentialEntryInfo(
providerId = providerId,
+ providerDisplayName = providerLabel,
entryKey = it.key,
entrySubkey = it.subkey,
pendingIntent = credentialEntry.pendingIntent,
@@ -201,13 +225,14 @@ class GetFlowUtils {
credentialTypeDisplayName = credentialEntry.typeDisplayName.toString(),
userName = credentialEntry.username.toString(),
displayName = credentialEntry.displayName?.toString(),
- icon = credentialEntry.icon?.loadDrawable(context),
+ icon = credentialEntry.icon.loadDrawable(context),
lastUsedTimeMillis = credentialEntry.lastUsedTime,
))
}
is PublicKeyCredentialEntry -> {
result.add(CredentialEntryInfo(
providerId = providerId,
+ providerDisplayName = providerLabel,
entryKey = it.key,
entrySubkey = it.subkey,
pendingIntent = credentialEntry.pendingIntent,
@@ -216,13 +241,14 @@ class GetFlowUtils {
credentialTypeDisplayName = credentialEntry.typeDisplayName.toString(),
userName = credentialEntry.username.toString(),
displayName = credentialEntry.displayName?.toString(),
- icon = credentialEntry.icon?.loadDrawable(context),
+ icon = credentialEntry.icon.loadDrawable(context),
lastUsedTimeMillis = credentialEntry.lastUsedTime,
))
}
is CustomCredentialEntry -> {
result.add(CredentialEntryInfo(
providerId = providerId,
+ providerDisplayName = providerLabel,
entryKey = it.key,
entrySubkey = it.subkey,
pendingIntent = credentialEntry.pendingIntent,
@@ -231,7 +257,7 @@ class GetFlowUtils {
credentialTypeDisplayName = credentialEntry.typeDisplayName.toString(),
userName = credentialEntry.title.toString(),
displayName = credentialEntry.subtitle?.toString(),
- icon = credentialEntry.icon?.loadDrawable(context),
+ icon = credentialEntry.icon.loadDrawable(context),
lastUsedTimeMillis = credentialEntry.lastUsedTime,
))
}
@@ -287,6 +313,7 @@ class GetFlowUtils {
pendingIntent = structuredAuthEntry.pendingIntent,
fillInIntent = entry.frameworkExtrasIntent,
title = title,
+ providerDisplayName = providerDisplayName,
icon = providerIcon,
isUnlockedAndEmpty = entry.status != AuthenticationEntry.STATUS_LOCKED,
isLastUnlocked =
@@ -394,8 +421,10 @@ class CreateFlowUtils {
fun toRequestDisplayInfo(
requestInfo: RequestInfo,
context: Context,
+ originName: String?,
): RequestDisplayInfo? {
- val appLabel = getAppLabel(context.packageManager, requestInfo.appPackageName)
+ val appLabel = originName
+ ?: getAppLabel(context.packageManager, requestInfo.appPackageName)
?: return null
val createCredentialRequest = requestInfo.createCredentialRequest ?: return null
val createCredentialRequestJetpack = CreateCredentialRequest.createFrom(
@@ -410,24 +439,16 @@ class CreateFlowUtils {
createCredentialRequestJetpack.password,
CredentialType.PASSWORD,
appLabel,
- context.getDrawable(R.drawable.ic_password)!!
+ context.getDrawable(R.drawable.ic_password_24) ?: return null,
+ preferImmediatelyAvailableCredentials = false,
)
is CreatePublicKeyCredentialRequest -> {
- val requestJson = createCredentialRequestJetpack.requestJson
- val json = JSONObject(requestJson)
- var name = ""
- var displayName = ""
- if (json.has("user")) {
- val user: JSONObject = json.getJSONObject("user")
- name = user.getString("name")
- displayName = user.getString("displayName")
- }
- RequestDisplayInfo(
- name,
- displayName,
- CredentialType.PASSKEY,
- appLabel,
- context.getDrawable(R.drawable.ic_passkey)!!
+ newRequestDisplayInfoFromPasskeyJson(
+ requestJson = createCredentialRequestJetpack.requestJson,
+ appLabel = appLabel,
+ context = context,
+ preferImmediatelyAvailableCredentials =
+ createCredentialRequestJetpack.preferImmediatelyAvailableCredentials,
)
}
is CreateCustomCredentialRequest -> {
@@ -436,12 +457,13 @@ class CreateFlowUtils {
.parseFromCredentialDataBundle(createCredentialRequest.credentialData)
?: return null
RequestDisplayInfo(
- title = displayInfo.userId,
- subtitle = displayInfo.userDisplayName,
+ title = displayInfo.userId.toString(),
+ subtitle = displayInfo.userDisplayName?.toString(),
type = CredentialType.UNKNOWN,
appName = appLabel,
typeIcon = displayInfo.credentialTypeIcon?.loadDrawable(context)
- ?: context.getDrawable(R.drawable.ic_other_sign_in)!!
+ ?: context.getDrawable(R.drawable.ic_other_sign_in_24) ?: return null,
+ preferImmediatelyAvailableCredentials = false,
)
}
else -> null
@@ -608,5 +630,29 @@ class CreateFlowUtils {
)
} else null
}
+
+ private fun newRequestDisplayInfoFromPasskeyJson(
+ requestJson: String,
+ appLabel: String,
+ context: Context,
+ preferImmediatelyAvailableCredentials: Boolean,
+ ): RequestDisplayInfo? {
+ val json = JSONObject(requestJson)
+ var name = ""
+ var displayName = ""
+ if (json.has("user")) {
+ val user: JSONObject = json.getJSONObject("user")
+ name = user.getString("name")
+ displayName = user.getString("displayName")
+ }
+ return RequestDisplayInfo(
+ name,
+ displayName,
+ CredentialType.PASSKEY,
+ appLabel,
+ context.getDrawable(R.drawable.ic_passkey_24) ?: return null,
+ preferImmediatelyAvailableCredentials,
+ )
+ }
}
}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/TestUtils.kt b/packages/CredentialManager/src/com/android/credentialmanager/TestUtils.kt
index eb3d188eab07..75b12ff756ad 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/TestUtils.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/TestUtils.kt
@@ -25,10 +25,15 @@ import android.credentials.Credential.TYPE_PASSWORD_CREDENTIAL
import android.credentials.ui.AuthenticationEntry
import android.credentials.ui.Entry
import android.net.Uri
+import android.os.Bundle
import android.provider.Settings
+import androidx.credentials.provider.BeginGetPasswordOption
+import androidx.credentials.provider.BeginGetPublicKeyCredentialOption
import androidx.credentials.provider.CreateEntry
import androidx.credentials.provider.PasswordCredentialEntry
import androidx.credentials.provider.PublicKeyCredentialEntry
+import androidx.credentials.provider.RemoteCreateEntry
+import androidx.credentials.provider.RemoteCredentialEntry
import java.time.Instant
@@ -69,6 +74,23 @@ class GetTestUtils {
)
}
+ internal fun newRemoteCredentialEntry(
+ context: Context,
+ key: String,
+ subkey: String,
+ ): Entry {
+ val intent = Intent(Settings.ACTION_SYNC_SETTINGS)
+ val pendingIntent =
+ PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
+ return Entry(
+ key,
+ subkey,
+ RemoteCredentialEntry(pendingIntent, BeginGetPublicKeyCredentialOption(
+ Bundle(), "id", "requestjson"
+ )).slice
+ )
+ }
+
internal fun newActionEntry(
context: Context,
key: String,
@@ -120,7 +142,8 @@ class GetTestUtils {
intent, (PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
or PendingIntent.FLAG_ONE_SHOT)
)
- val passwordEntry = PasswordCredentialEntry.Builder(context, userName, pendingIntent)
+ val passwordEntry = PasswordCredentialEntry.Builder(
+ context, userName, pendingIntent, BeginGetPasswordOption(Bundle(), "id"))
.setDisplayName(userDisplayName).setLastUsedTime(lastUsedTime).build()
return Entry(key, subkey, passwordEntry.slice, Intent())
}
@@ -141,8 +164,12 @@ class GetTestUtils {
intent, (PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
or PendingIntent.FLAG_ONE_SHOT)
)
- val passkeyEntry = PublicKeyCredentialEntry.Builder(context, userName, pendingIntent)
- .setDisplayName(userDisplayName).setLastUsedTime(lastUsedTime).build()
+ val passkeyEntry = PublicKeyCredentialEntry.Builder(
+ context,
+ userName,
+ pendingIntent,
+ BeginGetPublicKeyCredentialOption(Bundle(), "id", "requestjson")
+ ).setDisplayName(userDisplayName).setLastUsedTime(lastUsedTime).build()
return Entry(key, subkey, passkeyEntry.slice, Intent())
}
}
@@ -203,5 +230,20 @@ class CreateTestUtils {
Intent()
)
}
+
+ internal fun newRemoteCreateEntry(
+ context: Context,
+ key: String,
+ subkey: String,
+ ): Entry {
+ val intent = Intent(Settings.ACTION_SYNC_SETTINGS)
+ val pendingIntent =
+ PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
+ return Entry(
+ key,
+ subkey,
+ RemoteCreateEntry(pendingIntent).slice
+ )
+ }
}
} \ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/DialogResult.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/DialogResult.kt
index 6d07df70e7bf..297143309d14 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/DialogResult.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/DialogResult.kt
@@ -24,8 +24,6 @@ enum class DialogState {
enum class ResultState {
COMPLETE,
- NORMAL_CANCELED,
- LAUNCH_SETTING_CANCELED
}
data class DialogResult(
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/material/ModalBottomSheet.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/material/ModalBottomSheet.kt
index 58edb25336f8..307d95313ec8 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/material/ModalBottomSheet.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/material/ModalBottomSheet.kt
@@ -306,10 +306,6 @@ fun rememberModalBottomSheetState(
* @param sheetContentColor The preferred content color provided by the bottom sheet to its
* children. Defaults to the matching content color for [sheetBackgroundColor], or if that is not
* a color from the theme, this will keep the same content color set above the bottom sheet.
- * @param scrimColor The color of the scrim that is applied to the rest of the screen when the
- * bottom sheet is visible. If the color passed is [Color.Unspecified], then a scrim will no
- * longer be applied and the bottom sheet will not block interaction with the rest of the screen
- * when visible.
* @param content The content of rest of the screen.
*/
@Composable
@@ -322,7 +318,6 @@ fun ModalBottomSheetLayout(
sheetElevation: Dp = ModalBottomSheetDefaults.Elevation,
sheetBackgroundColor: Color = MaterialTheme.colorScheme.surface,
sheetContentColor: Color = contentColorFor(sheetBackgroundColor),
- scrimColor: Color = ModalBottomSheetDefaults.scrimColor,
content: @Composable () -> Unit
) {
val scope = rememberCoroutineScope()
@@ -332,7 +327,7 @@ fun ModalBottomSheetLayout(
Box(Modifier.fillMaxSize()) {
content()
Scrim(
- color = scrimColor,
+ color = ModalBottomSheetDefaults.scrimColor,
onDismiss = {
if (sheetState.confirmStateChange(Hidden)) {
scope.launch { sheetState.hide() }
@@ -451,7 +446,7 @@ private fun Modifier.bottomSheetSwipeable(
}
@Composable
-private fun Scrim(
+internal fun Scrim(
color: Color,
onDismiss: () -> Unit,
visible: Boolean
@@ -505,5 +500,5 @@ object ModalBottomSheetDefaults {
*/
val scrimColor: Color
@Composable
- get() = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.32f)
+ get() = MaterialTheme.colorScheme.scrim.copy(alpha = .32f)
} \ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ActionButton.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ActionButton.kt
index 984057a1c960..04a2c07da388 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ActionButton.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ActionButton.kt
@@ -16,6 +16,8 @@
package com.android.credentialmanager.common.ui
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.padding
import com.android.credentialmanager.R
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
@@ -24,7 +26,6 @@ import androidx.compose.material.icons.outlined.Visibility
import androidx.compose.material.icons.outlined.VisibilityOff
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
@@ -32,17 +33,19 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
-import com.android.credentialmanager.ui.theme.LocalAndroidColorScheme
+import androidx.compose.ui.unit.dp
@Composable
fun ActionButton(text: String, onClick: () -> Unit) {
TextButton(
+ modifier = Modifier.padding(vertical = 4.dp),
onClick = onClick,
colors = ButtonDefaults.textButtonColors(
contentColor = MaterialTheme.colorScheme.primary,
- )
+ ),
+ contentPadding = PaddingValues(start = 12.dp, top = 10.dp, end = 12.dp, bottom = 10.dp),
) {
- Text(text = text)
+ LargeLabelText(text = text)
}
}
@@ -64,7 +67,7 @@ fun ToggleVisibilityButton(modifier: Modifier = Modifier, onToggle: (Boolean) ->
contentDescription = if (toggleState.value)
stringResource(R.string.content_description_show_password) else
stringResource(R.string.content_description_hide_password),
- tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant
+ tint = MaterialTheme.colorScheme.onSurfaceVariant,
)
}
} \ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/BottomSheet.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/BottomSheet.kt
index c4d96ccf51f8..edc902e41e9a 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/BottomSheet.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/BottomSheet.kt
@@ -18,7 +18,6 @@ package com.android.credentialmanager.common.ui
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.ColumnScope
-import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier
@@ -27,6 +26,7 @@ import com.android.credentialmanager.common.material.ModalBottomSheetLayout
import com.android.credentialmanager.common.material.ModalBottomSheetValue
import com.android.credentialmanager.common.material.rememberModalBottomSheetState
import com.android.credentialmanager.ui.theme.EntryShape
+import com.android.credentialmanager.ui.theme.LocalAndroidColorScheme
/** Draws a modal bottom sheet with the same styles and effects shared by various flows. */
@Composable
@@ -39,11 +39,10 @@ fun ModalBottomSheet(
skipHalfExpanded = true
)
ModalBottomSheetLayout(
- sheetBackgroundColor = MaterialTheme.colorScheme.surface,
+ sheetBackgroundColor = LocalAndroidColorScheme.current.colorSurfaceBright,
modifier = Modifier.background(Color.Transparent),
sheetState = state,
sheetContent = sheetContent,
- scrimColor = MaterialTheme.colorScheme.scrim.copy(alpha = 0.8f),
sheetShape = EntryShape.TopRoundedCorner,
) {}
LaunchedEffect(state.currentValue) {
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Cards.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Cards.kt
index 85e5c1ee69d5..3976f9a305ab 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Cards.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Cards.kt
@@ -16,33 +16,76 @@
package com.android.credentialmanager.common.ui
-import androidx.compose.foundation.BorderStroke
+import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.wrapContentHeight
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
-import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.unit.dp
+import com.android.credentialmanager.ui.theme.Shapes
+import com.android.credentialmanager.ui.theme.LocalAndroidColorScheme
/**
- * By default the card is filled with surfaceVariant color. This container card instead fills the
- * background color with surface corlor.
+ * Container card for the whole sheet.
+ *
+ * Surface 1 color. No vertical padding. 24dp horizontal padding. 24dp bottom padding. 24dp top
+ * padding if [topAppBar] is not present, and none otherwise.
+ */
+@Composable
+fun SheetContainerCard(
+ topAppBar: (@Composable () -> Unit)? = null,
+ modifier: Modifier = Modifier,
+ contentVerticalArrangement: Arrangement.Vertical = Arrangement.Top,
+ content: LazyListScope.() -> Unit,
+) {
+ Card(
+ modifier = modifier.fillMaxWidth().wrapContentHeight(),
+ border = null,
+ colors = CardDefaults.cardColors(
+ containerColor = LocalAndroidColorScheme.current.colorSurfaceBright,
+ ),
+ ) {
+ if (topAppBar != null) {
+ topAppBar()
+ }
+ LazyColumn(
+ modifier = Modifier.padding(
+ start = 24.dp,
+ end = 24.dp,
+ bottom = 18.dp,
+ top = if (topAppBar == null) 24.dp else 0.dp
+ ).fillMaxWidth().wrapContentHeight(),
+ horizontalAlignment = Alignment.CenterHorizontally,
+ content = content,
+ verticalArrangement = contentVerticalArrangement,
+ )
+ }
+}
+
+/**
+ * Container card for the entries.
+ *
+ * Surface 3 color. No padding. Four rounded corner shape.
*/
@Composable
-fun ContainerCard(
+fun CredentialContainerCard(
modifier: Modifier = Modifier,
- shape: Shape = CardDefaults.shape,
- border: BorderStroke? = null,
content: @Composable ColumnScope.() -> Unit,
) {
Card(
- modifier = modifier.fillMaxWidth(),
- shape = shape,
- border = border,
+ modifier = modifier.fillMaxWidth().wrapContentHeight(),
+ shape = Shapes.medium,
+ border = null,
colors = CardDefaults.cardColors(
- containerColor = MaterialTheme.colorScheme.surface,
+ containerColor = Color.Transparent,
),
content = content,
)
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ConfirmButton.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ConfirmButton.kt
index d8ee750a88d6..c09a692ce9fc 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ConfirmButton.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ConfirmButton.kt
@@ -16,21 +16,27 @@
package com.android.credentialmanager.common.ui
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.FilledTonalButton
import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+/** Primary container color; label-large button text; on-primary button text color. */
@Composable
fun ConfirmButton(text: String, onClick: () -> Unit) {
FilledTonalButton(
+ modifier = Modifier.padding(vertical = 4.dp),
onClick = onClick,
colors = ButtonDefaults.filledTonalButtonColors(
- containerColor = MaterialTheme.colorScheme.primaryContainer,
- contentColor = MaterialTheme.colorScheme.onPrimaryContainer,
- )
+ containerColor = MaterialTheme.colorScheme.primary,
+ contentColor = MaterialTheme.colorScheme.onPrimary,
+ ),
+ contentPadding = PaddingValues(start = 24.dp, top = 10.dp, end = 24.dp, bottom = 10.dp),
) {
- Text(text = text)
+ LargeLabelText(text = text)
}
} \ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt
index aefd534da63c..9550268364a1 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt
@@ -16,55 +16,319 @@
package com.android.credentialmanager.common.ui
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.wrapContentHeight
+import androidx.compose.foundation.layout.wrapContentSize
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.ArrowBack
+import androidx.compose.material.icons.outlined.Lock
import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SuggestionChip
import androidx.compose.material3.SuggestionChipDefaults
+import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.ImageBitmap
+import androidx.compose.ui.graphics.painter.Painter
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.AnnotatedString
+import androidx.compose.ui.text.input.PasswordVisualTransformation
+import androidx.compose.ui.unit.dp
+import com.android.credentialmanager.R
import com.android.credentialmanager.ui.theme.EntryShape
+import com.android.credentialmanager.ui.theme.LocalAndroidColorScheme
+import com.android.credentialmanager.ui.theme.Shapes
-@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun Entry(
- onClick: () -> Unit,
- label: @Composable () -> Unit,
modifier: Modifier = Modifier,
- icon: @Composable (() -> Unit)? = null,
+ onClick: () -> Unit,
+ entryHeadlineText: String,
+ entrySecondLineText: String? = null,
+ entryThirdLineText: String? = null,
+ /** Supply one and only one of the [iconImageBitmap], [iconImageVector], or [iconPainter] for
+ * drawing the leading icon. */
+ iconImageBitmap: ImageBitmap? = null,
+ shouldApplyIconImageBitmapTint: Boolean = false,
+ iconImageVector: ImageVector? = null,
+ iconPainter: Painter? = null,
+ /** This will replace the [entrySecondLineText] value and render the text along with a
+ * mask on / off toggle for hiding / displaying the password value. */
+ passwordValue: String? = null,
+ /** If true, draws a trailing lock icon. */
+ isLockedAuthEntry: Boolean = false,
) {
+ val iconPadding = Modifier.wrapContentSize().padding(
+ // Horizontal padding should be 16dp, but the suggestion chip itself
+ // has 8dp horizontal elements padding
+ start = 8.dp, top = 16.dp, bottom = 16.dp
+ )
+ val iconSize = Modifier.size(24.dp)
SuggestionChip(
- modifier = modifier.fillMaxWidth(),
+ modifier = modifier.fillMaxWidth().wrapContentHeight(),
onClick = onClick,
shape = EntryShape.FullSmallRoundedCorner,
- label = label,
- icon = icon,
+ label = {
+ Row(
+ horizontalArrangement = Arrangement.SpaceBetween,
+ modifier = Modifier.fillMaxWidth().padding(
+ // Total end padding should be 16dp, but the suggestion chip itself
+ // has 8dp horizontal elements padding
+ horizontal = 8.dp, vertical = 16.dp,
+ ),
+ verticalAlignment = Alignment.CenterVertically,
+ ) {
+ Column(modifier = Modifier.wrapContentSize()) {
+ SmallTitleText(entryHeadlineText)
+ if (passwordValue != null) {
+ Row(modifier = Modifier.fillMaxWidth()) {
+ val visualTransformation = remember { PasswordVisualTransformation() }
+ val originalPassword by remember {
+ mutableStateOf(passwordValue)
+ }
+ val displayedPassword = remember {
+ mutableStateOf(
+ visualTransformation.filter(
+ AnnotatedString(originalPassword)
+ ).text.text
+ )
+ }
+ BodySmallText(displayedPassword.value)
+ ToggleVisibilityButton(
+ modifier = Modifier.padding(start = 5.dp).size(24.dp),
+ onToggle = {
+ if (it) {
+ displayedPassword.value = originalPassword
+ } else {
+ displayedPassword.value = visualTransformation.filter(
+ AnnotatedString(originalPassword)
+ ).text.text
+ }
+ },
+ )
+ }
+ } else if (entrySecondLineText != null) {
+ BodySmallText(entrySecondLineText)
+ }
+ if (entryThirdLineText != null) {
+ BodySmallText(entryThirdLineText)
+ }
+ }
+ if (isLockedAuthEntry) {
+ Box(modifier = Modifier.wrapContentSize()) {
+ Icon(
+ imageVector = Icons.Outlined.Lock,
+ // Decorative purpose only.
+ contentDescription = null,
+ modifier = Modifier.size(24.dp),
+ tint = MaterialTheme.colorScheme.onSurfaceVariant,
+ )
+ }
+ }
+ }
+ },
+ icon =
+ if (iconImageBitmap != null) {
+ if (shouldApplyIconImageBitmapTint) {
+ {
+ Box(modifier = iconPadding) {
+ Icon(
+ modifier = iconSize,
+ bitmap = iconImageBitmap,
+ tint = MaterialTheme.colorScheme.onSurfaceVariant,
+ // Decorative purpose only.
+ contentDescription = null,
+ )
+ }
+ }
+ } else {
+ {
+ Box(modifier = iconPadding) {
+ Image(
+ modifier = iconSize,
+ bitmap = iconImageBitmap,
+ // Decorative purpose only.
+ contentDescription = null,
+ )
+ }
+ }
+ }
+ } else if (iconImageVector != null) {
+ {
+ Box(modifier = iconPadding) {
+ Icon(
+ modifier = iconSize,
+ imageVector = iconImageVector,
+ tint = MaterialTheme.colorScheme.onSurfaceVariant,
+ // Decorative purpose only.
+ contentDescription = null,
+ )
+ }
+ }
+ } else if (iconPainter != null) {
+ {
+ Box(modifier = iconPadding) {
+ Icon(
+ modifier = iconSize,
+ painter = iconPainter,
+ tint = MaterialTheme.colorScheme.onSurfaceVariant,
+ // Decorative purpose only.
+ contentDescription = null,
+ )
+ }
+ }
+ } else {
+ null
+ },
border = null,
colors = SuggestionChipDefaults.suggestionChipColors(
- containerColor = MaterialTheme.colorScheme.surfaceVariant,
+ containerColor = LocalAndroidColorScheme.current.colorSurfaceContainerHigh,
+ // TODO: remove?
labelColor = MaterialTheme.colorScheme.onSurfaceVariant,
iconContentColor = MaterialTheme.colorScheme.onSurfaceVariant,
),
)
}
-@OptIn(ExperimentalMaterial3Api::class)
+/**
+ * A variation of the normal entry in that its background is transparent and the paddings are
+ * different (no horizontal padding).
+ */
@Composable
-fun TransparentBackgroundEntry(
+fun ActionEntry(
onClick: () -> Unit,
- label: @Composable () -> Unit,
- modifier: Modifier = Modifier,
- icon: @Composable (() -> Unit)? = null,
+ entryHeadlineText: String,
+ entrySecondLineText: String? = null,
+ iconImageBitmap: ImageBitmap,
) {
SuggestionChip(
- modifier = modifier.fillMaxWidth(),
+ modifier = Modifier.fillMaxWidth().wrapContentHeight(),
onClick = onClick,
- label = label,
- icon = icon,
+ shape = Shapes.large,
+ label = {
+ Column(modifier = Modifier.wrapContentSize()
+ .padding(start = 16.dp, top = 16.dp, bottom = 16.dp)) {
+ SmallTitleText(entryHeadlineText)
+ if (entrySecondLineText != null) {
+ BodySmallText(entrySecondLineText)
+ }
+ }
+ },
+ icon = {
+ Box(modifier = Modifier.wrapContentSize().padding(vertical = 16.dp)) {
+ Image(
+ modifier = Modifier.size(24.dp),
+ bitmap = iconImageBitmap,
+ // Decorative purpose only.
+ contentDescription = null,
+ )
+ }
+ },
border = null,
colors = SuggestionChipDefaults.suggestionChipColors(
containerColor = Color.Transparent,
),
)
+}
+
+/**
+ * A single row of leading icon and text describing a benefit of passkeys, used by the
+ * [com.android.credentialmanager.createflow.PasskeyIntroCard].
+ */
+@Composable
+fun PasskeyBenefitRow(
+ leadingIconPainter: Painter,
+ text: String,
+) {
+ Row(
+ horizontalArrangement = Arrangement.spacedBy(16.dp),
+ verticalAlignment = Alignment.CenterVertically,
+ modifier = Modifier.fillMaxWidth()
+ ) {
+ Icon(
+ modifier = Modifier.size(24.dp),
+ painter = leadingIconPainter,
+ tint = MaterialTheme.colorScheme.onSurfaceVariant,
+ // Decorative purpose only.
+ contentDescription = null,
+ )
+ BodyMediumText(text = text)
+ }
+}
+
+/**
+ * A single row of one or two CTA buttons for continuing or cancelling the current step.
+ */
+@Composable
+fun CtaButtonRow(
+ leftButton: (@Composable () -> Unit)? = null,
+ rightButton: (@Composable () -> Unit)? = null,
+) {
+ Row(
+ horizontalArrangement =
+ if (leftButton == null) Arrangement.End
+ else if (rightButton == null) Arrangement.Start
+ else Arrangement.SpaceBetween,
+ verticalAlignment = Alignment.CenterVertically,
+ modifier = Modifier.fillMaxWidth()
+ ) {
+ if (leftButton != null) {
+ leftButton()
+ }
+ if (rightButton != null) {
+ rightButton()
+ }
+ }
+}
+
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+fun MoreOptionTopAppBar(
+ text: String,
+ onNavigationIconClicked: () -> Unit,
+) {
+ TopAppBar(
+ title = {
+ LargeTitleText(text = text, modifier = Modifier.padding(horizontal = 4.dp))
+ },
+ navigationIcon = {
+ IconButton(
+ modifier = Modifier.padding(top = 8.dp, bottom = 8.dp, start = 4.dp).size(48.dp),
+ onClick = onNavigationIconClicked
+ ) {
+ Box(
+ modifier = Modifier.size(48.dp),
+ contentAlignment = Alignment.Center,
+ ) {
+ Icon(
+ imageVector = Icons.Filled.ArrowBack,
+ contentDescription = stringResource(
+ R.string.accessibility_back_arrow_button
+ ),
+ modifier = Modifier.size(24.dp),
+ tint = MaterialTheme.colorScheme.onSurfaceVariant,
+ )
+ }
+ }
+ },
+ colors = TopAppBarDefaults.topAppBarColors(containerColor = Color.Transparent),
+ modifier = Modifier.padding(top = 12.dp, bottom = 8.dp)
+ )
} \ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/HeadlineIcon.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/HeadlineIcon.kt
new file mode 100644
index 000000000000..ac79844457a8
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/HeadlineIcon.kt
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2023 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.credentialmanager.common.ui
+
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.wrapContentHeight
+import androidx.compose.material3.Icon
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.ImageBitmap
+import androidx.compose.ui.graphics.painter.Painter
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.unit.dp
+
+/** Tinted primary; centered; 32X32. */
+@Composable
+fun HeadlineIcon(bitmap: ImageBitmap, tint: Color? = null) {
+ Row(
+ horizontalArrangement = Arrangement.Center,
+ modifier = Modifier.fillMaxWidth().wrapContentHeight(),
+ ) {
+ Icon(
+ modifier = Modifier.size(32.dp),
+ bitmap = bitmap,
+ tint = tint ?: MaterialTheme.colorScheme.primary,
+ // Decorative purpose only.
+ contentDescription = null,
+ )
+ }
+}
+
+@Composable
+fun HeadlineIcon(imageVector: ImageVector) {
+ Row(
+ horizontalArrangement = Arrangement.Center,
+ modifier = Modifier.fillMaxWidth().wrapContentHeight(),
+ ) {
+ Icon(
+ modifier = Modifier.size(32.dp),
+ imageVector = imageVector,
+ tint = MaterialTheme.colorScheme.primary,
+ // Decorative purpose only.
+ contentDescription = null,
+ )
+ }
+}
+
+@Composable
+fun HeadlineIcon(painter: Painter) {
+ Row(
+ horizontalArrangement = Arrangement.Center,
+ modifier = Modifier.fillMaxWidth().wrapContentHeight(),
+ ) {
+ Icon(
+ modifier = Modifier.size(32.dp),
+ painter = painter,
+ tint = MaterialTheme.colorScheme.primary,
+ // Decorative purpose only.
+ contentDescription = null,
+ )
+ }
+} \ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/SectionHeader.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/SectionHeader.kt
new file mode 100644
index 000000000000..c63771e49516
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/SectionHeader.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2023 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.credentialmanager.common.ui
+
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.wrapContentHeight
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.unit.dp
+
+@Composable
+fun CredentialListSectionHeader(text: String) {
+ InternalSectionHeader(text, MaterialTheme.colorScheme.onSurfaceVariant)
+}
+
+@Composable
+fun MoreAboutPasskeySectionHeader(text: String) {
+ InternalSectionHeader(text, MaterialTheme.colorScheme.onSurface)
+}
+
+@Composable
+private fun InternalSectionHeader(text: String, color: Color) {
+ Row(modifier = Modifier.fillMaxWidth().wrapContentHeight()) {
+ SectionHeaderText(
+ text,
+ modifier = Modifier.padding(top = 20.dp, bottom = 8.dp),
+ color = color
+ )
+ }
+} \ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/SnackBar.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/SnackBar.kt
new file mode 100644
index 000000000000..514ff90be8d7
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/SnackBar.kt
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2023 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.credentialmanager.common.ui
+
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxWithConstraints
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.wrapContentSize
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Close
+import androidx.compose.material3.Card
+import androidx.compose.material3.CardDefaults
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.unit.dp
+import com.android.credentialmanager.R
+import com.android.credentialmanager.common.material.Scrim
+import com.android.credentialmanager.ui.theme.Shapes
+
+@Composable
+fun Snackbar(
+ contentText: String,
+ action: (@Composable () -> Unit)? = null,
+ onDismiss: () -> Unit,
+) {
+ BoxWithConstraints {
+ Box(Modifier.fillMaxSize()) {
+ Scrim(
+ color = Color.Transparent,
+ onDismiss = onDismiss,
+ visible = true
+ )
+ }
+ Box(
+ modifier = Modifier
+ .align(Alignment.BottomCenter).wrapContentSize().padding(bottom = 18.dp)
+ ) {
+ Card(
+ shape = Shapes.medium,
+ modifier = Modifier.wrapContentSize(),
+ colors = CardDefaults.cardColors(
+ containerColor = MaterialTheme.colorScheme.inverseSurface,
+ )
+ ) {
+ Row(
+ modifier = Modifier.wrapContentSize(),
+ verticalAlignment = Alignment.CenterVertically,
+ ) {
+ SnackbarContentText(contentText, modifier = Modifier.padding(
+ top = 18.dp, bottom = 18.dp, start = 24.dp,
+ ))
+ if (action != null) {
+ action()
+ }
+ IconButton(onClick = onDismiss, modifier = Modifier.padding(
+ top = 4.dp, bottom = 4.dp, start = 2.dp, end = 10.dp,
+ )) {
+ Icon(
+ Icons.Filled.Close,
+ contentDescription = stringResource(
+ R.string.accessibility_snackbar_dismiss
+ ),
+ tint = MaterialTheme.colorScheme.inverseOnSurface,
+ )
+ }
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/SystemUiControllerUtils.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/SystemUiControllerUtils.kt
new file mode 100644
index 000000000000..a6195237d139
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/SystemUiControllerUtils.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 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.credentialmanager.common.ui
+
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.graphics.Color
+import com.android.compose.SystemUiController
+import com.android.credentialmanager.common.material.ModalBottomSheetDefaults
+import com.android.credentialmanager.ui.theme.LocalAndroidColorScheme
+
+@Composable
+fun setTransparentSystemBarsColor(sysUiController: SystemUiController) {
+ sysUiController.setSystemBarsColor(color = Color.Transparent, darkIcons = false)
+}
+
+@Composable
+fun setBottomSheetSystemBarsColor(sysUiController: SystemUiController) {
+ sysUiController.setStatusBarColor(
+ color = ModalBottomSheetDefaults.scrimColor,
+ darkIcons = false
+ )
+ sysUiController.setNavigationBarColor(
+ color = LocalAndroidColorScheme.current.colorSurfaceBright,
+ darkIcons = false
+ )
+} \ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Texts.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Texts.kt
index 3a66dda73832..8af729ecdc25 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Texts.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Texts.kt
@@ -16,69 +16,144 @@
package com.android.credentialmanager.common.ui
+import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.style.TextAlign
+/**
+ * The headline for a screen. E.g. "Create a passkey for X", "Choose a saved sign-in for X".
+ *
+ * Centered horizontally; headline-small typography; on-surface color.
+ */
@Composable
-fun TextOnSurface(
- text: String,
- modifier: Modifier = Modifier,
- textAlign: TextAlign? = null,
- style: TextStyle,
-) {
- TextInternal(
+fun HeadlineText(text: String, modifier: Modifier = Modifier) {
+ Text(
+ modifier = modifier.wrapContentSize(),
text = text,
color = MaterialTheme.colorScheme.onSurface,
- modifier = modifier,
- textAlign = textAlign,
- style = style,
+ textAlign = TextAlign.Center,
+ style = MaterialTheme.typography.headlineSmall,
)
}
+/**
+ * Body-medium typography; on-surface-variant color.
+ */
@Composable
-fun TextSecondary(
- text: String,
- modifier: Modifier = Modifier,
- textAlign: TextAlign? = null,
- style: TextStyle,
-) {
- TextInternal(
+fun BodyMediumText(text: String, modifier: Modifier = Modifier) {
+ Text(
+ modifier = modifier.wrapContentSize(),
text = text,
- color = MaterialTheme.colorScheme.secondary,
- modifier = modifier,
- textAlign = textAlign,
- style = style,
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ style = MaterialTheme.typography.bodyMedium,
)
}
+/**
+ * Body-small typography; on-surface-variant color.
+ */
@Composable
-fun TextOnSurfaceVariant(
- text: String,
- modifier: Modifier = Modifier,
- textAlign: TextAlign? = null,
- style: TextStyle,
-) {
- TextInternal(
+fun BodySmallText(text: String, modifier: Modifier = Modifier) {
+ Text(
+ modifier = modifier.wrapContentSize(),
text = text,
color = MaterialTheme.colorScheme.onSurfaceVariant,
- modifier = modifier,
- textAlign = textAlign,
- style = style,
+ style = MaterialTheme.typography.bodySmall,
+ )
+}
+
+/**
+ * Title-large typography; on-surface color.
+ */
+@Composable
+fun LargeTitleText(text: String, modifier: Modifier = Modifier) {
+ Text(
+ modifier = modifier.wrapContentSize(),
+ text = text,
+ color = MaterialTheme.colorScheme.onSurface,
+ style = MaterialTheme.typography.titleLarge,
)
}
+/**
+ * Title-small typography; on-surface color.
+ */
+@Composable
+fun SmallTitleText(text: String, modifier: Modifier = Modifier) {
+ Text(
+ modifier = modifier.wrapContentSize(),
+ text = text,
+ color = MaterialTheme.colorScheme.onSurface,
+ style = MaterialTheme.typography.titleSmall,
+ )
+}
+
+/**
+ * Title-small typography.
+ */
@Composable
-private fun TextInternal(
- text: String,
- color: Color,
- modifier: Modifier,
- textAlign: TextAlign?,
- style: TextStyle,
-) {
- Text(text = text, color = color, modifier = modifier, textAlign = textAlign, style = style)
+fun SectionHeaderText(text: String, modifier: Modifier = Modifier, color: Color) {
+ Text(
+ modifier = modifier.wrapContentSize(),
+ text = text,
+ color = color,
+ style = MaterialTheme.typography.titleSmall,
+ )
+}
+
+/**
+ * Body-medium typography; inverse-on-surface color.
+ */
+@Composable
+fun SnackbarContentText(text: String, modifier: Modifier = Modifier) {
+ Text(
+ modifier = modifier.wrapContentSize(),
+ text = text,
+ color = MaterialTheme.colorScheme.inverseOnSurface,
+ style = MaterialTheme.typography.bodyMedium,
+ )
+}
+
+/**
+ * Label-large typography; inverse-primary color.
+ */
+@Composable
+fun SnackbarActionText(text: String, modifier: Modifier = Modifier) {
+ Text(
+ modifier = modifier.wrapContentSize(),
+ text = text,
+ color = MaterialTheme.colorScheme.inversePrimary,
+ style = MaterialTheme.typography.labelLarge,
+ )
+}
+
+/**
+ * Label-large typography; on-surface-variant color; centered.
+ */
+@Composable
+fun LargeLabelTextOnSurfaceVariant(text: String, modifier: Modifier = Modifier) {
+ Text(
+ modifier = modifier.wrapContentSize(),
+ text = text,
+ textAlign = TextAlign.Center,
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ style = MaterialTheme.typography.labelLarge,
+ )
+}
+
+/**
+ * Label-large typography; color following parent spec; centered.
+ */
+@Composable
+fun LargeLabelText(text: String, modifier: Modifier = Modifier) {
+ Text(
+ modifier = modifier.wrapContentSize(),
+ text = text,
+ textAlign = TextAlign.Center,
+ style = MaterialTheme.typography.labelLarge,
+ )
} \ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
index 942eb490aa20..b83c593fdffc 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
@@ -11,53 +11,49 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.material3.Divider
import androidx.compose.material3.ExperimentalMaterial3Api
-import androidx.compose.material3.Icon
-import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.TopAppBar
-import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.outlined.NewReleases
import androidx.compose.material.icons.filled.Add
+import androidx.compose.material.icons.outlined.QrCodeScanner
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
-import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.text.AnnotatedString
-import androidx.compose.ui.text.input.PasswordVisualTransformation
-import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.core.graphics.drawable.toBitmap
+import com.android.compose.rememberSystemUiController
import com.android.credentialmanager.CredentialSelectorViewModel
import com.android.credentialmanager.R
import com.android.credentialmanager.common.BaseEntry
import com.android.credentialmanager.common.CredentialType
import com.android.credentialmanager.common.ProviderActivityState
import com.android.credentialmanager.common.ui.ActionButton
+import com.android.credentialmanager.common.ui.BodyMediumText
+import com.android.credentialmanager.common.ui.BodySmallText
import com.android.credentialmanager.common.ui.ConfirmButton
+import com.android.credentialmanager.common.ui.CredentialContainerCard
+import com.android.credentialmanager.common.ui.CtaButtonRow
import com.android.credentialmanager.common.ui.Entry
+import com.android.credentialmanager.common.ui.HeadlineIcon
+import com.android.credentialmanager.common.ui.LargeLabelTextOnSurfaceVariant
import com.android.credentialmanager.common.ui.ModalBottomSheet
-import com.android.credentialmanager.common.ui.TextOnSurface
-import com.android.credentialmanager.common.ui.TextSecondary
-import com.android.credentialmanager.common.ui.TextOnSurfaceVariant
-import com.android.credentialmanager.common.ui.ContainerCard
-import com.android.credentialmanager.common.ui.ToggleVisibilityButton
-import com.android.credentialmanager.ui.theme.LocalAndroidColorScheme
+import com.android.credentialmanager.common.ui.MoreAboutPasskeySectionHeader
+import com.android.credentialmanager.common.ui.MoreOptionTopAppBar
+import com.android.credentialmanager.common.ui.SheetContainerCard
+import com.android.credentialmanager.common.ui.PasskeyBenefitRow
+import com.android.credentialmanager.common.ui.HeadlineText
+import com.android.credentialmanager.common.ui.setBottomSheetSystemBarsColor
@Composable
fun CreateCredentialScreen(
@@ -65,6 +61,8 @@ fun CreateCredentialScreen(
createCredentialUiState: CreateCredentialUiState,
providerActivityLauncher: ManagedActivityResultLauncher<IntentSenderRequest, ActivityResult>
) {
+ val sysUiController = rememberSystemUiController()
+ setBottomSheetSystemBarsColor(sysUiController)
ModalBottomSheet(
sheetContent = {
// Hide the sheet content as opposed to the whole bottom sheet to maintain the scrim
@@ -73,7 +71,7 @@ fun CreateCredentialScreen(
when (viewModel.uiState.providerActivityState) {
ProviderActivityState.NOT_APPLICABLE -> {
when (createCredentialUiState.currentScreenState) {
- CreateScreenState.PASSKEY_INTRO -> ConfirmationCard(
+ CreateScreenState.PASSKEY_INTRO -> PasskeyIntroCard(
onConfirm = viewModel::createFlowOnConfirmIntro,
onLearnMore = viewModel::createFlowOnLearnMore,
)
@@ -122,11 +120,20 @@ fun CreateCredentialScreen(
viewModel::createFlowOnDisabledProvidersSelected,
onRemoteEntrySelected = viewModel::createFlowOnEntrySelected,
)
- CreateScreenState.MORE_OPTIONS_ROW_INTRO -> MoreOptionsRowIntroCard(
- providerInfo = createCredentialUiState.activeEntry?.activeProvider!!,
- onChangeDefaultSelected = viewModel::createFlowOnChangeDefaultSelected,
- onUseOnceSelected = viewModel::createFlowOnUseOnceSelected,
- )
+ CreateScreenState.MORE_OPTIONS_ROW_INTRO -> {
+ if (createCredentialUiState.activeEntry == null) {
+ viewModel.onIllegalUiState("Expect active entry to be non-null" +
+ " upon default provider dialog.")
+ } else {
+ MoreOptionsRowIntroCard(
+ selectedEntry = createCredentialUiState.activeEntry,
+ onIllegalScreenState = viewModel::onIllegalUiState,
+ onChangeDefaultSelected =
+ viewModel::createFlowOnChangeDefaultSelected,
+ onUseOnceSelected = viewModel::createFlowOnUseOnceSelected,
+ )
+ }
+ }
CreateScreenState.EXTERNAL_ONLY_SELECTION -> ExternalOnlySelectionCard(
requestDisplayInfo = createCredentialUiState.requestDisplayInfo,
activeRemoteEntry =
@@ -157,14 +164,13 @@ fun CreateCredentialScreen(
)
}
-@OptIn(ExperimentalMaterial3Api::class)
@Composable
-fun ConfirmationCard(
+fun PasskeyIntroCard(
onConfirm: () -> Unit,
onLearnMore: () -> Unit,
) {
- ContainerCard() {
- Column() {
+ SheetContainerCard {
+ item {
val onboardingImageResource = remember {
mutableStateOf(R.drawable.ic_passkeys_onboarding)
}
@@ -173,101 +179,56 @@ fun ConfirmationCard(
} else {
onboardingImageResource.value = R.drawable.ic_passkeys_onboarding
}
- Image(
- painter = painterResource(onboardingImageResource.value),
- contentDescription = null,
- modifier = Modifier.align(alignment = Alignment.CenterHorizontally)
- .padding(top = 24.dp, bottom = 12.dp).size(316.dp, 168.dp)
- )
- TextOnSurface(
- text = stringResource(R.string.passkey_creation_intro_title),
- style = MaterialTheme.typography.titleMedium,
- modifier = Modifier
- .padding(horizontal = 24.dp)
- .align(alignment = Alignment.CenterHorizontally),
- textAlign = TextAlign.Center,
- )
- Divider(
- thickness = 16.dp,
- color = Color.Transparent
- )
Row(
- horizontalArrangement = Arrangement.SpaceBetween,
- verticalAlignment = Alignment.CenterVertically,
- modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
+ modifier = Modifier.wrapContentHeight().fillMaxWidth(),
+ horizontalArrangement = Arrangement.Center,
) {
Image(
- modifier = Modifier.size(24.dp),
- painter = painterResource(R.drawable.ic_passkeys_onboarding_password),
- contentDescription = null
- )
- TextSecondary(
- text = stringResource(R.string.passkey_creation_intro_body_password),
- style = MaterialTheme.typography.bodyMedium,
- modifier = Modifier.padding(start = 16.dp, end = 4.dp),
+ painter = painterResource(onboardingImageResource.value),
+ contentDescription = null,
+ modifier = Modifier.size(316.dp, 168.dp)
)
}
- Divider(
- thickness = 16.dp,
- color = Color.Transparent
+ }
+ item { Divider(thickness = 16.dp, color = Color.Transparent) }
+ item { HeadlineText(text = stringResource(R.string.passkey_creation_intro_title)) }
+ item { Divider(thickness = 16.dp, color = Color.Transparent) }
+ item {
+ PasskeyBenefitRow(
+ leadingIconPainter = painterResource(R.drawable.ic_passkeys_onboarding_password),
+ text = stringResource(R.string.passkey_creation_intro_body_password),
)
- Row(
- horizontalArrangement = Arrangement.SpaceBetween,
- verticalAlignment = Alignment.CenterVertically,
- modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
- ) {
- Image(
- modifier = Modifier.size(24.dp),
- painter = painterResource(R.drawable.ic_passkeys_onboarding_fingerprint),
- contentDescription = null
- )
- TextSecondary(
- text = stringResource(R.string.passkey_creation_intro_body_fingerprint),
- style = MaterialTheme.typography.bodyMedium,
- modifier = Modifier.padding(start = 16.dp, end = 4.dp),
- )
- }
- Divider(
- thickness = 16.dp,
- color = Color.Transparent
+ }
+ item { Divider(thickness = 16.dp, color = Color.Transparent) }
+ item {
+ PasskeyBenefitRow(
+ leadingIconPainter = painterResource(R.drawable.ic_passkeys_onboarding_fingerprint),
+ text = stringResource(R.string.passkey_creation_intro_body_fingerprint),
)
- Row(
- horizontalArrangement = Arrangement.SpaceBetween,
- verticalAlignment = Alignment.CenterVertically,
- modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
- ) {
- Image(
- modifier = Modifier.size(24.dp),
- painter = painterResource(R.drawable.ic_passkeys_onboarding_device),
- contentDescription = null
- )
- TextSecondary(
- text = stringResource(R.string.passkey_creation_intro_body_device),
- style = MaterialTheme.typography.bodyMedium,
- modifier = Modifier.padding(start = 16.dp, end = 4.dp),
- )
- }
- Divider(
- thickness = 32.dp,
- color = Color.Transparent
+ }
+ item { Divider(thickness = 16.dp, color = Color.Transparent) }
+ item {
+ PasskeyBenefitRow(
+ leadingIconPainter = painterResource(R.drawable.ic_passkeys_onboarding_device),
+ text = stringResource(R.string.passkey_creation_intro_body_device),
)
- Row(
- horizontalArrangement = Arrangement.SpaceBetween,
- modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
- ) {
- ActionButton(
- stringResource(R.string.string_learn_more),
- onClick = onLearnMore
- )
- ConfirmButton(
- stringResource(R.string.string_continue),
- onClick = onConfirm
- )
- }
- Divider(
- thickness = 18.dp,
- color = Color.Transparent,
- modifier = Modifier.padding(bottom = 18.dp)
+ }
+ item { Divider(thickness = 24.dp, color = Color.Transparent) }
+
+ item {
+ CtaButtonRow(
+ leftButton = {
+ ActionButton(
+ stringResource(R.string.string_learn_more),
+ onClick = onLearnMore
+ )
+ },
+ rightButton = {
+ ConfirmButton(
+ stringResource(R.string.string_continue),
+ onClick = onConfirm
+ )
+ },
)
}
}
@@ -283,16 +244,11 @@ fun ProviderSelectionCard(
onDisabledProvidersSelected: () -> Unit,
onMoreOptionsSelected: () -> Unit,
) {
- ContainerCard() {
- Column() {
- Icon(
- bitmap = requestDisplayInfo.typeIcon.toBitmap().asImageBitmap(),
- contentDescription = null,
- tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant,
- modifier = Modifier.align(alignment = Alignment.CenterHorizontally)
- .padding(top = 24.dp, bottom = 16.dp).size(32.dp)
- )
- TextOnSurface(
+ SheetContainerCard {
+ item { HeadlineIcon(bitmap = requestDisplayInfo.typeIcon.toBitmap().asImageBitmap()) }
+ item { Divider(thickness = 16.dp, color = Color.Transparent) }
+ item {
+ HeadlineText(
text = stringResource(
R.string.choose_provider_title,
when (requestDisplayInfo.type) {
@@ -302,83 +258,56 @@ fun ProviderSelectionCard(
stringResource(R.string.passwords)
CredentialType.UNKNOWN -> stringResource(R.string.sign_in_info)
}
- ),
- style = MaterialTheme.typography.titleMedium,
- modifier = Modifier.padding(horizontal = 24.dp)
- .align(alignment = Alignment.CenterHorizontally),
- textAlign = TextAlign.Center,
- )
- Divider(
- thickness = 16.dp,
- color = Color.Transparent
- )
- TextSecondary(
- text = stringResource(R.string.choose_provider_body),
- style = MaterialTheme.typography.bodyLarge,
- modifier = Modifier.padding(horizontal = 28.dp),
+ )
)
- ContainerCard(
- shape = MaterialTheme.shapes.medium,
- modifier = Modifier.padding(
- start = 24.dp,
- end = 24.dp,
- top = 24.dp,
- bottom = if (hasRemoteEntry) 24.dp else 16.dp
- ).align(alignment = Alignment.CenterHorizontally),
- ) {
- LazyColumn(
+ }
+ item { Divider(thickness = 24.dp, color = Color.Transparent) }
+
+ item { BodyMediumText(text = stringResource(R.string.choose_provider_body)) }
+ item { Divider(thickness = 16.dp, color = Color.Transparent) }
+ item {
+ CredentialContainerCard {
+ Column(
verticalArrangement = Arrangement.spacedBy(2.dp)
) {
sortedCreateOptionsPairs.forEach { entry ->
- item {
- MoreOptionsInfoRow(
- requestDisplayInfo = requestDisplayInfo,
- providerInfo = entry.second,
- createOptionInfo = entry.first,
- onOptionSelected = {
- onOptionSelected(
- ActiveEntry(
- entry.second,
- entry.first
- )
+ MoreOptionsInfoRow(
+ requestDisplayInfo = requestDisplayInfo,
+ providerInfo = entry.second,
+ createOptionInfo = entry.first,
+ onOptionSelected = {
+ onOptionSelected(
+ ActiveEntry(
+ entry.second,
+ entry.first
)
- }
- )
- }
- }
- item {
- MoreOptionsDisabledProvidersRow(
- disabledProviders = disabledProviderList,
- onDisabledProvidersSelected =
- onDisabledProvidersSelected,
+ )
+ }
)
}
+ MoreOptionsDisabledProvidersRow(
+ disabledProviders = disabledProviderList,
+ onDisabledProvidersSelected = onDisabledProvidersSelected,
+ )
}
}
- if (hasRemoteEntry) {
- Divider(
- thickness = 24.dp,
- color = Color.Transparent
+ }
+ if (hasRemoteEntry) {
+ item { Divider(thickness = 24.dp, color = Color.Transparent) }
+ item {
+ CtaButtonRow(
+ leftButton = {
+ ActionButton(
+ stringResource(R.string.string_more_options),
+ onMoreOptionsSelected
+ )
+ }
)
- Row(
- horizontalArrangement = Arrangement.Start,
- modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
- ) {
- ActionButton(
- stringResource(R.string.string_more_options),
- onMoreOptionsSelected
- )
- }
}
- Divider(
- thickness = 24.dp,
- color = Color.Transparent,
- )
}
}
}
-@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MoreOptionsSelectionCard(
requestDisplayInfo: RequestDisplayInfo,
@@ -393,158 +322,113 @@ fun MoreOptionsSelectionCard(
onDisabledProvidersSelected: () -> Unit,
onRemoteEntrySelected: (BaseEntry) -> Unit,
) {
- ContainerCard() {
- Column() {
- TopAppBar(
- title = {
- TextOnSurface(
- text =
- stringResource(
- R.string.save_credential_to_title,
- when (requestDisplayInfo.type) {
- CredentialType.PASSKEY ->
- stringResource(R.string.passkey)
- CredentialType.PASSWORD ->
- stringResource(R.string.password)
- CredentialType.UNKNOWN -> stringResource(R.string.sign_in_info)
- }
- ),
- style = MaterialTheme.typography.titleMedium,
- )
- },
- navigationIcon = {
- IconButton(
- onClick =
- if (isFromProviderSelection)
- onBackProviderSelectionButtonSelected
- else onBackCreationSelectionButtonSelected
- ) {
- Icon(
- Icons.Filled.ArrowBack,
- stringResource(R.string.accessibility_back_arrow_button)
- )
- }
- },
- colors = TopAppBarDefaults.topAppBarColors(containerColor = Color.Transparent),
- modifier = Modifier.padding(top = 12.dp)
- )
- Divider(
- thickness = 8.dp,
- color = Color.Transparent
- )
- ContainerCard(
- shape = MaterialTheme.shapes.medium,
- modifier = Modifier
- .padding(horizontal = 24.dp)
- .align(alignment = Alignment.CenterHorizontally)
- ) {
- LazyColumn(
- verticalArrangement = Arrangement.spacedBy(2.dp)
- ) {
+ SheetContainerCard(topAppBar = {
+ MoreOptionTopAppBar(
+ text = stringResource(
+ R.string.save_credential_to_title,
+ when (requestDisplayInfo.type) {
+ CredentialType.PASSKEY ->
+ stringResource(R.string.passkey)
+ CredentialType.PASSWORD ->
+ stringResource(R.string.password)
+ CredentialType.UNKNOWN -> stringResource(R.string.sign_in_info)
+ }
+ ),
+ onNavigationIconClicked =
+ if (isFromProviderSelection) onBackProviderSelectionButtonSelected
+ else onBackCreationSelectionButtonSelected,
+ )
+ }) {
+ item { Divider(thickness = 8.dp, color = Color.Transparent) } // Top app bar has a 8dp
+ // bottom padding already
+ item {
+ CredentialContainerCard {
+ Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
// Only in the flows with default provider(not first time use) we can show the
// createOptions here, or they will be shown on ProviderSelectionCard
if (hasDefaultProvider) {
sortedCreateOptionsPairs.forEach { entry ->
- item {
- MoreOptionsInfoRow(
- requestDisplayInfo = requestDisplayInfo,
- providerInfo = entry.second,
- createOptionInfo = entry.first,
- onOptionSelected = {
- onOptionSelected(
- ActiveEntry(
- entry.second,
- entry.first
- )
+ MoreOptionsInfoRow(
+ requestDisplayInfo = requestDisplayInfo,
+ providerInfo = entry.second,
+ createOptionInfo = entry.first,
+ onOptionSelected = {
+ onOptionSelected(
+ ActiveEntry(
+ entry.second,
+ entry.first
)
- })
- }
- }
- item {
- MoreOptionsDisabledProvidersRow(
- disabledProviders = disabledProviderList,
- onDisabledProvidersSelected =
- onDisabledProvidersSelected,
+ )
+ }
)
}
+ MoreOptionsDisabledProvidersRow(
+ disabledProviders = disabledProviderList,
+ onDisabledProvidersSelected =
+ onDisabledProvidersSelected,
+ )
}
enabledProviderList.forEach {
if (it.remoteEntry != null) {
- item {
- RemoteEntryRow(
- remoteInfo = it.remoteEntry!!,
- onRemoteEntrySelected = onRemoteEntrySelected,
- )
- }
+ RemoteEntryRow(
+ remoteInfo = it.remoteEntry!!,
+ onRemoteEntrySelected = onRemoteEntrySelected,
+ )
return@forEach
}
}
}
}
- Divider(
- thickness = 8.dp,
- color = Color.Transparent,
- modifier = Modifier.padding(bottom = 40.dp)
- )
}
}
}
-@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MoreOptionsRowIntroCard(
- providerInfo: EnabledProviderInfo,
+ selectedEntry: ActiveEntry,
+ onIllegalScreenState: (String) -> Unit,
onChangeDefaultSelected: () -> Unit,
onUseOnceSelected: () -> Unit,
) {
- ContainerCard() {
- Column() {
- Icon(
- Icons.Outlined.NewReleases,
- contentDescription = null,
- modifier = Modifier.align(alignment = Alignment.CenterHorizontally)
- .padding(all = 24.dp),
- tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant,
- )
- TextOnSurface(
+ val entryInfo = selectedEntry.activeEntryInfo
+ if (entryInfo !is CreateOptionInfo) {
+ onIllegalScreenState("Encountered unexpected type of entry during the default provider" +
+ " dialog: ${entryInfo::class}")
+ return
+ }
+ SheetContainerCard {
+ item { HeadlineIcon(imageVector = Icons.Outlined.NewReleases) }
+ item { Divider(thickness = 24.dp, color = Color.Transparent) }
+ item {
+ HeadlineText(
text = stringResource(
- R.string.use_provider_for_all_title,
- providerInfo.displayName
- ),
- style = MaterialTheme.typography.titleMedium,
- modifier = Modifier.padding(horizontal = 24.dp)
- .align(alignment = Alignment.CenterHorizontally),
- textAlign = TextAlign.Center,
- )
- TextSecondary(
- text = stringResource(R.string.use_provider_for_all_description),
- style = MaterialTheme.typography.bodyLarge,
- modifier = Modifier.padding(all = 24.dp)
- .align(alignment = Alignment.CenterHorizontally),
+ R.string.use_provider_for_all_title, selectedEntry.activeProvider.displayName)
)
- Row(
- horizontalArrangement = Arrangement.SpaceBetween,
- modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
- ) {
- ActionButton(
- stringResource(R.string.use_once),
- onClick = onUseOnceSelected
- )
- ConfirmButton(
- stringResource(R.string.set_as_default),
- onClick = onChangeDefaultSelected
- )
- }
- Divider(
- thickness = 18.dp,
- color = Color.Transparent,
- modifier = Modifier.padding(bottom = 40.dp)
+ }
+ item { Divider(thickness = 24.dp, color = Color.Transparent) }
+ item {
+ BodyMediumText(text = stringResource(
+ R.string.use_provider_for_all_description, entryInfo.userProviderDisplayName))
+ }
+ item {
+ CtaButtonRow(
+ leftButton = {
+ ActionButton(
+ stringResource(R.string.use_once),
+ onClick = onUseOnceSelected
+ )
+ },
+ rightButton = {
+ ConfirmButton(
+ stringResource(R.string.set_as_default),
+ onClick = onChangeDefaultSelected
+ )
+ },
)
}
}
}
-@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun CreationSelectionCard(
requestDisplayInfo: RequestDisplayInfo,
@@ -556,26 +440,18 @@ fun CreationSelectionCard(
onMoreOptionsSelected: () -> Unit,
hasDefaultProvider: Boolean,
) {
- ContainerCard() {
- Column() {
- Divider(
- thickness = 24.dp,
- color = Color.Transparent
- )
- Icon(
+ SheetContainerCard {
+ item {
+ HeadlineIcon(
bitmap = providerInfo.icon.toBitmap().asImageBitmap(),
- contentDescription = null,
tint = Color.Unspecified,
- modifier = Modifier.align(alignment = Alignment.CenterHorizontally).size(32.dp)
- )
- TextSecondary(
- text = providerInfo.displayName,
- style = MaterialTheme.typography.titleLarge,
- modifier = Modifier.padding(vertical = 10.dp)
- .align(alignment = Alignment.CenterHorizontally),
- textAlign = TextAlign.Center,
)
- TextOnSurface(
+ }
+ item { Divider(thickness = 4.dp, color = Color.Transparent) }
+ item { LargeLabelTextOnSurfaceVariant(text = providerInfo.displayName) }
+ item { Divider(thickness = 16.dp, color = Color.Transparent) }
+ item {
+ HeadlineText(
text = when (requestDisplayInfo.type) {
CredentialType.PASSKEY -> stringResource(
R.string.choose_create_option_passkey_title,
@@ -589,80 +465,67 @@ fun CreationSelectionCard(
R.string.choose_create_option_sign_in_title,
requestDisplayInfo.appName
)
- },
- style = MaterialTheme.typography.titleMedium,
- modifier = Modifier.padding(horizontal = 24.dp)
- .align(alignment = Alignment.CenterHorizontally),
- textAlign = TextAlign.Center,
+ }
)
- ContainerCard(
- shape = MaterialTheme.shapes.medium,
- modifier = Modifier
- .padding(all = 24.dp)
- .align(alignment = Alignment.CenterHorizontally),
- ) {
+ }
+ item { Divider(thickness = 24.dp, color = Color.Transparent) }
+ item {
+ CredentialContainerCard {
PrimaryCreateOptionRow(
requestDisplayInfo = requestDisplayInfo,
entryInfo = createOptionInfo,
onOptionSelected = onOptionSelected
)
}
- var createOptionsSize = 0
- var remoteEntry: RemoteInfo? = null
- enabledProviderList.forEach { enabledProvider ->
- if (enabledProvider.remoteEntry != null) {
- remoteEntry = enabledProvider.remoteEntry
- }
- createOptionsSize += enabledProvider.createOptions.size
- }
- val shouldShowMoreOptionsButton = if (!hasDefaultProvider) {
- // User has already been presented with all options on the default provider
- // selection screen. Don't show them again. Therefore, only show the more option
- // button if remote option is present.
- remoteEntry != null
- } else {
- createOptionsSize > 1 || remoteEntry != null
+ }
+ item { Divider(thickness = 24.dp, color = Color.Transparent) }
+ var createOptionsSize = 0
+ var remoteEntry: RemoteInfo? = null
+ enabledProviderList.forEach { enabledProvider ->
+ if (enabledProvider.remoteEntry != null) {
+ remoteEntry = enabledProvider.remoteEntry
}
- Row(
- horizontalArrangement =
- if (shouldShowMoreOptionsButton) Arrangement.SpaceBetween else Arrangement.End,
- modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
- ) {
- if (shouldShowMoreOptionsButton) {
- ActionButton(
- stringResource(R.string.string_more_options),
- onClick = onMoreOptionsSelected
+ createOptionsSize += enabledProvider.createOptions.size
+ }
+ val shouldShowMoreOptionsButton = if (!hasDefaultProvider) {
+ // User has already been presented with all options on the default provider
+ // selection screen. Don't show them again. Therefore, only show the more option
+ // button if remote option is present.
+ remoteEntry != null
+ } else {
+ createOptionsSize > 1 || remoteEntry != null
+ }
+ item {
+ CtaButtonRow(
+ leftButton = if (shouldShowMoreOptionsButton) {
+ {
+ ActionButton(
+ stringResource(R.string.string_more_options),
+ onMoreOptionsSelected
+ )
+ }
+ } else null,
+ rightButton = {
+ ConfirmButton(
+ stringResource(R.string.string_continue),
+ onClick = onConfirm
)
- }
- ConfirmButton(
- stringResource(R.string.string_continue),
- onClick = onConfirm
- )
- }
- if (createOptionInfo.footerDescription != null) {
+ },
+ )
+ }
+ if (createOptionInfo.footerDescription != null) {
+ item {
Divider(
thickness = 1.dp,
- color = Color.LightGray,
- modifier = Modifier.padding(start = 24.dp, end = 24.dp, top = 18.dp)
- )
- TextSecondary(
- text = createOptionInfo.footerDescription,
- style = MaterialTheme.typography.bodyLarge,
- modifier = Modifier.padding(
- start = 29.dp, top = 8.dp, bottom = 18.dp, end = 28.dp
- )
+ color = MaterialTheme.colorScheme.outlineVariant,
+ modifier = Modifier.padding(vertical = 16.dp)
)
}
- Divider(
- thickness = 18.dp,
- color = Color.Transparent,
- modifier = Modifier.padding(bottom = 16.dp)
- )
+ item { BodySmallText(text = createOptionInfo.footerDescription) }
}
}
}
-@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ExternalOnlySelectionCard(
requestDisplayInfo: RequestDisplayInfo,
@@ -670,148 +533,74 @@ fun ExternalOnlySelectionCard(
onOptionSelected: (BaseEntry) -> Unit,
onConfirm: () -> Unit,
) {
- ContainerCard() {
- Column() {
- Icon(
- painter = painterResource(R.drawable.ic_other_devices),
- contentDescription = null,
- tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant,
- modifier = Modifier.align(alignment = Alignment.CenterHorizontally)
- .padding(all = 24.dp).size(32.dp)
- )
- TextOnSurface(
- text = stringResource(R.string.create_passkey_in_other_device_title),
- style = MaterialTheme.typography.titleMedium,
- modifier = Modifier.padding(horizontal = 24.dp)
- .align(alignment = Alignment.CenterHorizontally),
- textAlign = TextAlign.Center,
- )
- Divider(
- thickness = 24.dp,
- color = Color.Transparent
- )
- ContainerCard(
- shape = MaterialTheme.shapes.medium,
- modifier = Modifier
- .padding(horizontal = 24.dp)
- .align(alignment = Alignment.CenterHorizontally),
- ) {
+ SheetContainerCard {
+ item { HeadlineIcon(imageVector = Icons.Outlined.QrCodeScanner) }
+ item { Divider(thickness = 16.dp, color = Color.Transparent) }
+ item { HeadlineText(text = stringResource(R.string.create_passkey_in_other_device_title)) }
+ item { Divider(thickness = 24.dp, color = Color.Transparent) }
+ item {
+ CredentialContainerCard {
PrimaryCreateOptionRow(
requestDisplayInfo = requestDisplayInfo,
entryInfo = activeRemoteEntry,
onOptionSelected = onOptionSelected
)
}
- Divider(
- thickness = 24.dp,
- color = Color.Transparent
- )
- Row(
- horizontalArrangement = Arrangement.End,
- modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
- ) {
- ConfirmButton(
- stringResource(R.string.string_continue),
- onClick = onConfirm
- )
- }
- Divider(
- thickness = 18.dp,
- color = Color.Transparent,
- modifier = Modifier.padding(bottom = 16.dp)
+ }
+ item { Divider(thickness = 24.dp, color = Color.Transparent) }
+ item {
+ CtaButtonRow(
+ rightButton = {
+ ConfirmButton(
+ stringResource(R.string.string_continue),
+ onClick = onConfirm
+ )
+ },
)
}
}
}
-@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MoreAboutPasskeysIntroCard(
onBackPasskeyIntroButtonSelected: () -> Unit,
) {
- ContainerCard() {
- Column() {
- TopAppBar(
- title = {
- TextOnSurface(
- text =
- stringResource(
- R.string.more_about_passkeys_title
- ),
- style = MaterialTheme.typography.titleMedium,
- )
- },
- navigationIcon = {
- IconButton(
- onClick = onBackPasskeyIntroButtonSelected
- ) {
- Icon(
- Icons.Filled.ArrowBack,
- stringResource(R.string.accessibility_back_arrow_button)
- )
- }
- },
- colors = TopAppBarDefaults.topAppBarColors(containerColor = Color.Transparent),
- modifier = Modifier.padding(top = 12.dp)
+ SheetContainerCard(
+ topAppBar = {
+ MoreOptionTopAppBar(
+ text = stringResource(R.string.more_about_passkeys_title),
+ onNavigationIconClicked = onBackPasskeyIntroButtonSelected,
)
- Column(
- modifier = Modifier.fillMaxWidth().padding(start = 24.dp, end = 68.dp)
- ) {
- TextOnSurfaceVariant(
- text = stringResource(R.string.passwordless_technology_title),
- style = MaterialTheme.typography.titleLarge,
- )
- TextSecondary(
- text = stringResource(R.string.passwordless_technology_detail),
- style = MaterialTheme.typography.bodyMedium,
- )
- Divider(
- thickness = 24.dp,
- color = Color.Transparent
- )
- TextOnSurfaceVariant(
- text = stringResource(R.string.public_key_cryptography_title),
- style = MaterialTheme.typography.titleLarge,
- )
- TextSecondary(
- text = stringResource(R.string.public_key_cryptography_detail),
- style = MaterialTheme.typography.bodyMedium,
- )
- Divider(
- thickness = 24.dp,
- color = Color.Transparent
- )
- TextOnSurfaceVariant(
- text = stringResource(R.string.improved_account_security_title),
- style = MaterialTheme.typography.titleLarge,
- )
- TextSecondary(
- text = stringResource(R.string.improved_account_security_detail),
- style = MaterialTheme.typography.bodyMedium,
- )
- Divider(
- thickness = 24.dp,
- color = Color.Transparent
- )
- TextOnSurfaceVariant(
- text = stringResource(R.string.seamless_transition_title),
- style = MaterialTheme.typography.titleLarge,
- )
- TextSecondary(
- text = stringResource(R.string.seamless_transition_detail),
- style = MaterialTheme.typography.bodyMedium,
- )
- }
- Divider(
- thickness = 18.dp,
- color = Color.Transparent,
- modifier = Modifier.padding(bottom = 24.dp)
+ },
+ contentVerticalArrangement = Arrangement.spacedBy(8.dp)
+ ) {
+ item {
+ MoreAboutPasskeySectionHeader(
+ text = stringResource(R.string.passwordless_technology_title)
)
+ BodyMediumText(text = stringResource(R.string.passwordless_technology_detail))
+ }
+ item {
+ MoreAboutPasskeySectionHeader(
+ text = stringResource(R.string.public_key_cryptography_title)
+ )
+ BodyMediumText(text = stringResource(R.string.public_key_cryptography_detail))
+ }
+ item {
+ MoreAboutPasskeySectionHeader(
+ text = stringResource(R.string.improved_account_security_title)
+ )
+ BodyMediumText(text = stringResource(R.string.improved_account_security_detail))
+ }
+ item {
+ MoreAboutPasskeySectionHeader(
+ text = stringResource(R.string.seamless_transition_title)
+ )
+ BodyMediumText(text = stringResource(R.string.seamless_transition_detail))
}
}
}
-@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PrimaryCreateOptionRow(
requestDisplayInfo: RequestDisplayInfo,
@@ -820,115 +609,37 @@ fun PrimaryCreateOptionRow(
) {
Entry(
onClick = { onOptionSelected(entryInfo) },
- icon = {
- if (entryInfo is CreateOptionInfo && entryInfo.profileIcon != null) {
- Image(
- bitmap = entryInfo.profileIcon.toBitmap().asImageBitmap(),
- contentDescription = null,
- modifier = Modifier.padding(start = 10.dp).size(32.dp),
- )
- } else {
- Icon(
- bitmap = requestDisplayInfo.typeIcon.toBitmap().asImageBitmap(),
- contentDescription = null,
- tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant,
- modifier = Modifier.padding(start = 10.dp).size(32.dp),
- )
- }
+ iconImageBitmap =
+ if (entryInfo is CreateOptionInfo && entryInfo.profileIcon != null) {
+ entryInfo.profileIcon.toBitmap().asImageBitmap()
+ } else {
+ requestDisplayInfo.typeIcon.toBitmap().asImageBitmap()
},
- label = {
- Column() {
- when (requestDisplayInfo.type) {
- CredentialType.PASSKEY -> {
- TextOnSurfaceVariant(
- text = requestDisplayInfo.title,
- style = MaterialTheme.typography.titleLarge,
- modifier = Modifier.padding(top = 16.dp, start = 5.dp),
- )
- TextSecondary(
- text = if (requestDisplayInfo.subtitle != null) {
- requestDisplayInfo.subtitle + " • " + stringResource(
- R.string.passkey_before_subtitle
- )
- } else {
- stringResource(R.string.passkey_before_subtitle)
- },
- style = MaterialTheme.typography.bodyMedium,
- modifier = Modifier.padding(bottom = 16.dp, start = 5.dp),
- )
- }
- CredentialType.PASSWORD -> {
- TextOnSurfaceVariant(
- text = requestDisplayInfo.title,
- style = MaterialTheme.typography.titleLarge,
- modifier = Modifier.padding(top = 16.dp, start = 5.dp),
- )
- Row(
- modifier = Modifier.fillMaxWidth().padding(
- top = 4.dp, bottom = 16.dp,
- start = 5.dp
- ),
- verticalAlignment = Alignment.CenterVertically
- ) {
- val visualTransformation = remember { PasswordVisualTransformation() }
- // This subtitle would never be null for create password
- val originalPassword by remember {
- mutableStateOf(requestDisplayInfo.subtitle ?: "")
- }
- val displayedPassword = remember {
- mutableStateOf(
- visualTransformation.filter(
- AnnotatedString(originalPassword)
- ).text.text
- )
- }
- TextSecondary(
- text = displayedPassword.value,
- style = MaterialTheme.typography.bodyMedium,
- modifier = Modifier.padding(top = 4.dp, bottom = 4.dp),
- )
-
- ToggleVisibilityButton(modifier = Modifier.padding(start = 4.dp)
- .height(24.dp).width(24.dp), onToggle = {
- if (it) {
- displayedPassword.value = originalPassword
- } else {
- displayedPassword.value = visualTransformation.filter(
- AnnotatedString(originalPassword)
- ).text.text
- }
- })
- }
- }
- CredentialType.UNKNOWN -> {
- if (requestDisplayInfo.subtitle != null) {
- TextOnSurfaceVariant(
- text = requestDisplayInfo.title,
- style = MaterialTheme.typography.titleLarge,
- modifier = Modifier.padding(top = 16.dp, start = 5.dp),
- )
- TextOnSurfaceVariant(
- text = requestDisplayInfo.subtitle,
- style = MaterialTheme.typography.bodyMedium,
- modifier = Modifier.padding(bottom = 16.dp, start = 5.dp),
- )
- } else {
- TextOnSurfaceVariant(
- text = requestDisplayInfo.title,
- style = MaterialTheme.typography.titleLarge,
- modifier = Modifier.padding(
- top = 16.dp, bottom = 16.dp, start = 5.dp
- ),
- )
- }
- }
+ shouldApplyIconImageBitmapTint = !(entryInfo is CreateOptionInfo &&
+ entryInfo.profileIcon != null),
+ entryHeadlineText = requestDisplayInfo.title,
+ entrySecondLineText = when (requestDisplayInfo.type) {
+ CredentialType.PASSKEY -> {
+ if (requestDisplayInfo.subtitle != null) {
+ requestDisplayInfo.subtitle + " • " + stringResource(
+ R.string.passkey_before_subtitle
+ )
+ } else {
+ stringResource(R.string.passkey_before_subtitle)
}
}
- }
+ // Set passwordValue instead
+ CredentialType.PASSWORD -> null
+ CredentialType.UNKNOWN -> requestDisplayInfo.subtitle
+ },
+ passwordValue =
+ if (requestDisplayInfo.type == CredentialType.PASSWORD)
+ // This subtitle would never be null for create password
+ requestDisplayInfo.subtitle ?: ""
+ else null,
)
}
-@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MoreOptionsInfoRow(
requestDisplayInfo: RequestDisplayInfo,
@@ -938,93 +649,46 @@ fun MoreOptionsInfoRow(
) {
Entry(
onClick = onOptionSelected,
- icon = {
- Image(
- modifier = Modifier.padding(start = 10.dp).size(32.dp),
- bitmap = providerInfo.icon.toBitmap().asImageBitmap(),
- contentDescription = null
- )
- },
- label = {
- Column() {
- TextOnSurfaceVariant(
- text = providerInfo.displayName,
- style = MaterialTheme.typography.titleLarge,
- modifier = Modifier.padding(top = 16.dp, start = 5.dp),
+ iconImageBitmap = providerInfo.icon.toBitmap().asImageBitmap(),
+ entryHeadlineText = providerInfo.displayName,
+ entrySecondLineText = createOptionInfo.userProviderDisplayName,
+ entryThirdLineText =
+ if (requestDisplayInfo.type == CredentialType.PASSKEY ||
+ requestDisplayInfo.type == CredentialType.PASSWORD) {
+ if (createOptionInfo.passwordCount != null &&
+ createOptionInfo.passkeyCount != null
+ ) {
+ stringResource(
+ R.string.more_options_usage_passwords_passkeys,
+ createOptionInfo.passwordCount,
+ createOptionInfo.passkeyCount
)
- if (createOptionInfo.userProviderDisplayName != null) {
- TextSecondary(
- text = createOptionInfo.userProviderDisplayName,
- style = MaterialTheme.typography.bodyMedium,
- modifier = Modifier.padding(start = 5.dp),
- )
- }
- if (requestDisplayInfo.type == CredentialType.PASSKEY ||
- requestDisplayInfo.type == CredentialType.PASSWORD
- ) {
- if (createOptionInfo.passwordCount != null &&
- createOptionInfo.passkeyCount != null
- ) {
- TextSecondary(
- text =
- stringResource(
- R.string.more_options_usage_passwords_passkeys,
- createOptionInfo.passwordCount,
- createOptionInfo.passkeyCount
- ),
- style = MaterialTheme.typography.bodyMedium,
- modifier = Modifier.padding(bottom = 16.dp, start = 5.dp),
- )
- } else if (createOptionInfo.passwordCount != null) {
- TextSecondary(
- text =
- stringResource(
- R.string.more_options_usage_passwords,
- createOptionInfo.passwordCount
- ),
- style = MaterialTheme.typography.bodyMedium,
- modifier = Modifier.padding(bottom = 16.dp, start = 5.dp),
- )
- } else if (createOptionInfo.passkeyCount != null) {
- TextSecondary(
- text =
- stringResource(
- R.string.more_options_usage_passkeys,
- createOptionInfo.passkeyCount
- ),
- style = MaterialTheme.typography.bodyMedium,
- modifier = Modifier.padding(bottom = 16.dp, start = 5.dp),
- )
- } else {
- Divider(
- thickness = 16.dp,
- color = Color.Transparent,
- )
- }
- } else {
- if (createOptionInfo.totalCredentialCount != null) {
- TextSecondary(
- text =
- stringResource(
- R.string.more_options_usage_credentials,
- createOptionInfo.totalCredentialCount
- ),
- style = MaterialTheme.typography.bodyMedium,
- modifier = Modifier.padding(bottom = 16.dp, start = 5.dp),
- )
- } else {
- Divider(
- thickness = 16.dp,
- color = Color.Transparent,
- )
- }
- }
+ } else if (createOptionInfo.passwordCount != null) {
+ stringResource(
+ R.string.more_options_usage_passwords,
+ createOptionInfo.passwordCount
+ )
+ } else if (createOptionInfo.passkeyCount != null) {
+ stringResource(
+ R.string.more_options_usage_passkeys,
+ createOptionInfo.passkeyCount
+ )
+ } else {
+ null
}
- }
+ } else {
+ if (createOptionInfo.totalCredentialCount != null) {
+ stringResource(
+ R.string.more_options_usage_credentials,
+ createOptionInfo.totalCredentialCount
+ )
+ } else {
+ null
+ }
+ },
)
}
-@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MoreOptionsDisabledProvidersRow(
disabledProviders: List<ProviderInfo>?,
@@ -1033,36 +697,15 @@ fun MoreOptionsDisabledProvidersRow(
if (disabledProviders != null && disabledProviders.isNotEmpty()) {
Entry(
onClick = onDisabledProvidersSelected,
- icon = {
- Icon(
- Icons.Filled.Add,
- contentDescription = null,
- modifier = Modifier.padding(start = 16.dp),
- tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant,
- )
+ iconImageVector = Icons.Filled.Add,
+ entryHeadlineText = stringResource(R.string.other_password_manager),
+ entrySecondLineText = disabledProviders.joinToString(separator = " • ") {
+ it.displayName
},
- label = {
- Column() {
- TextOnSurfaceVariant(
- text = stringResource(R.string.other_password_manager),
- style = MaterialTheme.typography.titleLarge,
- modifier = Modifier.padding(top = 16.dp, start = 5.dp),
- )
- // TODO: Update the subtitle once design is confirmed
- TextSecondary(
- text = disabledProviders.joinToString(separator = " • ") {
- it.displayName
- },
- style = MaterialTheme.typography.bodyMedium,
- modifier = Modifier.padding(bottom = 16.dp, start = 5.dp),
- )
- }
- }
)
}
}
-@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun RemoteEntryRow(
remoteInfo: RemoteInfo,
@@ -1070,23 +713,7 @@ fun RemoteEntryRow(
) {
Entry(
onClick = { onRemoteEntrySelected(remoteInfo) },
- icon = {
- Icon(
- painter = painterResource(R.drawable.ic_other_devices),
- contentDescription = null,
- tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant,
- modifier = Modifier.padding(start = 10.dp)
- )
- },
- label = {
- Column() {
- TextOnSurfaceVariant(
- text = stringResource(R.string.another_device),
- style = MaterialTheme.typography.titleLarge,
- modifier = Modifier.padding(start = 10.dp, top = 18.dp, bottom = 18.dp)
- .align(alignment = Alignment.CenterHorizontally),
- )
- }
- }
+ iconImageVector = Icons.Outlined.QrCodeScanner,
+ entryHeadlineText = stringResource(R.string.another_device),
)
} \ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
index ce4e936446ff..4332fb34ce79 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
@@ -38,7 +38,9 @@ data class CreateCredentialUiState(
)
internal fun hasContentToDisplay(state: CreateCredentialUiState): Boolean {
- return state.sortedCreateOptionsPairs.isNotEmpty()
+ return state.sortedCreateOptionsPairs.isNotEmpty() ||
+ (!state.requestDisplayInfo.preferImmediatelyAvailableCredentials &&
+ state.remoteEntry != null)
}
open class ProviderInfo(
@@ -67,7 +69,7 @@ class CreateOptionInfo(
entrySubkey: String,
pendingIntent: PendingIntent?,
fillInIntent: Intent?,
- val userProviderDisplayName: String?,
+ val userProviderDisplayName: String,
val profileIcon: Drawable?,
val passwordCount: Int?,
val passkeyCount: Int?,
@@ -104,6 +106,7 @@ data class RequestDisplayInfo(
val type: CredentialType,
val appName: String,
val typeIcon: Drawable,
+ val preferImmediatelyAvailableCredentials: Boolean,
)
/**
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
index 5704820444a4..ea56f46716f4 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
@@ -20,58 +20,48 @@ import android.text.TextUtils
import androidx.activity.compose.ManagedActivityResultLauncher
import androidx.activity.result.ActivityResult
import androidx.activity.result.IntentSenderRequest
-
-import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentHeight
-import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.ArrowBack
-import androidx.compose.material.icons.filled.Close
-import androidx.compose.material.icons.outlined.Lock
+import androidx.compose.material.icons.outlined.QrCodeScanner
import androidx.compose.material3.Divider
-import androidx.compose.material3.ExperimentalMaterial3Api
-import androidx.compose.material3.Icon
-import androidx.compose.material3.IconButton
-import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.Snackbar
-import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
-import androidx.compose.material3.TopAppBar
-import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.core.graphics.drawable.toBitmap
+import com.android.compose.rememberSystemUiController
import com.android.credentialmanager.CredentialSelectorViewModel
import com.android.credentialmanager.R
import com.android.credentialmanager.common.BaseEntry
import com.android.credentialmanager.common.CredentialType
import com.android.credentialmanager.common.ProviderActivityState
import com.android.credentialmanager.common.ui.ActionButton
+import com.android.credentialmanager.common.ui.ActionEntry
import com.android.credentialmanager.common.ui.ConfirmButton
+import com.android.credentialmanager.common.ui.CredentialContainerCard
+import com.android.credentialmanager.common.ui.CtaButtonRow
import com.android.credentialmanager.common.ui.Entry
import com.android.credentialmanager.common.ui.ModalBottomSheet
-import com.android.credentialmanager.common.ui.TextOnSurface
-import com.android.credentialmanager.common.ui.TextSecondary
-import com.android.credentialmanager.common.ui.TextOnSurfaceVariant
-import com.android.credentialmanager.common.ui.ContainerCard
-import com.android.credentialmanager.common.ui.TransparentBackgroundEntry
-import com.android.credentialmanager.ui.theme.EntryShape
-import com.android.credentialmanager.ui.theme.LocalAndroidColorScheme
+import com.android.credentialmanager.common.ui.MoreOptionTopAppBar
+import com.android.credentialmanager.common.ui.SheetContainerCard
+import com.android.credentialmanager.common.ui.SnackbarActionText
+import com.android.credentialmanager.common.ui.HeadlineText
+import com.android.credentialmanager.common.ui.CredentialListSectionHeader
+import com.android.credentialmanager.common.ui.Snackbar
+import com.android.credentialmanager.common.ui.setTransparentSystemBarsColor
+import com.android.credentialmanager.common.ui.setBottomSheetSystemBarsColor
@Composable
fun GetCredentialScreen(
@@ -79,13 +69,16 @@ fun GetCredentialScreen(
getCredentialUiState: GetCredentialUiState,
providerActivityLauncher: ManagedActivityResultLauncher<IntentSenderRequest, ActivityResult>
) {
+ val sysUiController = rememberSystemUiController()
if (getCredentialUiState.currentScreenState == GetScreenState.REMOTE_ONLY) {
+ setTransparentSystemBarsColor(sysUiController)
RemoteCredentialSnackBarScreen(
onClick = viewModel::getFlowOnMoreOptionOnSnackBarSelected,
onCancel = viewModel::onUserCancel,
)
} else if (getCredentialUiState.currentScreenState
== GetScreenState.UNLOCKED_AUTH_ENTRIES_ONLY) {
+ setTransparentSystemBarsColor(sysUiController)
EmptyAuthEntrySnackBarScreen(
authenticationEntryList =
getCredentialUiState.providerDisplayInfo.authenticationEntryList,
@@ -93,6 +86,7 @@ fun GetCredentialScreen(
onLastLockedAuthEntryNotFound = viewModel::onLastLockedAuthEntryNotFoundError,
)
} else {
+ setBottomSheetSystemBarsColor(sysUiController)
ModalBottomSheet(
sheetContent = {
// Hide the sheet content as opposed to the whole bottom sheet to maintain the scrim
@@ -154,12 +148,9 @@ fun PrimarySelectionCard(
val sortedUserNameToCredentialEntryList =
providerDisplayInfo.sortedUserNameToCredentialEntryList
val authenticationEntryList = providerDisplayInfo.authenticationEntryList
- ContainerCard() {
- Column() {
- TextOnSurface(
- modifier = Modifier.padding(all = 24.dp),
- textAlign = TextAlign.Center,
- style = MaterialTheme.typography.headlineSmall,
+ SheetContainerCard {
+ item {
+ HeadlineText(
text = stringResource(
if (sortedUserNameToCredentialEntryList
.size == 1 && authenticationEntryList.isEmpty()
@@ -178,48 +169,42 @@ fun PrimarySelectionCard(
requestDisplayInfo.appName
),
)
-
- ContainerCard(
- shape = MaterialTheme.shapes.medium,
- modifier = Modifier
- .padding(horizontal = 24.dp)
- .align(alignment = Alignment.CenterHorizontally)
- ) {
- val usernameForCredentialSize = sortedUserNameToCredentialEntryList
- .size
- val authenticationEntrySize = authenticationEntryList.size
- LazyColumn(
- verticalArrangement = Arrangement.spacedBy(2.dp)
- ) {
+ }
+ item { Divider(thickness = 24.dp, color = Color.Transparent) }
+ item {
+ CredentialContainerCard {
+ Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
+ val usernameForCredentialSize = sortedUserNameToCredentialEntryList.size
+ val authenticationEntrySize = authenticationEntryList.size
// Show max 4 entries in this primary page
if (usernameForCredentialSize + authenticationEntrySize <= 4) {
- items(sortedUserNameToCredentialEntryList) {
+ sortedUserNameToCredentialEntryList.forEach {
CredentialEntryRow(
credentialEntryInfo = it.sortedCredentialEntryList.first(),
onEntrySelected = onEntrySelected,
)
}
- items(authenticationEntryList) {
+ authenticationEntryList.forEach {
AuthenticationEntryRow(
authenticationEntryInfo = it,
onEntrySelected = onEntrySelected,
)
}
} else if (usernameForCredentialSize < 4) {
- items(sortedUserNameToCredentialEntryList) {
+ sortedUserNameToCredentialEntryList.forEach {
CredentialEntryRow(
credentialEntryInfo = it.sortedCredentialEntryList.first(),
onEntrySelected = onEntrySelected,
)
}
- items(authenticationEntryList.take(4 - usernameForCredentialSize)) {
+ authenticationEntryList.take(4 - usernameForCredentialSize).forEach {
AuthenticationEntryRow(
authenticationEntryInfo = it,
onEntrySelected = onEntrySelected,
)
}
} else {
- items(sortedUserNameToCredentialEntryList.take(4)) {
+ sortedUserNameToCredentialEntryList.take(4).forEach {
CredentialEntryRow(
credentialEntryInfo = it.sortedCredentialEntryList.first(),
onEntrySelected = onEntrySelected,
@@ -228,49 +213,39 @@ fun PrimarySelectionCard(
}
}
}
- Divider(
- thickness = 24.dp,
- color = Color.Transparent
- )
- var totalEntriesCount = sortedUserNameToCredentialEntryList
- .flatMap { it.sortedCredentialEntryList }.size + authenticationEntryList
- .size + providerInfoList.flatMap { it.actionEntryList }.size
- if (providerDisplayInfo.remoteEntry != null) totalEntriesCount += 1
- // Row horizontalArrangement differs on only one actionButton(should place on most
- // left)/only one confirmButton(should place on most right)/two buttons exist the same
- // time(should be one on the left, one on the right)
- Row(
- horizontalArrangement =
- if (totalEntriesCount <= 1 && activeEntry != null) Arrangement.End
- else if (totalEntriesCount > 1 && activeEntry == null) Arrangement.Start
- else Arrangement.SpaceBetween,
- modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
- ) {
- if (totalEntriesCount > 1) {
- ActionButton(
- stringResource(R.string.get_dialog_use_saved_passkey_for),
- onMoreOptionSelected
- )
- }
- // Only one sign-in options exist
- if (activeEntry != null) {
- ConfirmButton(
- stringResource(R.string.string_continue),
- onClick = onConfirm
- )
- }
- }
- Divider(
- thickness = 18.dp,
- color = Color.Transparent,
- modifier = Modifier.padding(bottom = 16.dp)
+ }
+ item { Divider(thickness = 24.dp, color = Color.Transparent) }
+ var totalEntriesCount = sortedUserNameToCredentialEntryList
+ .flatMap { it.sortedCredentialEntryList }.size + authenticationEntryList
+ .size + providerInfoList.flatMap { it.actionEntryList }.size
+ if (providerDisplayInfo.remoteEntry != null) totalEntriesCount += 1
+ // Row horizontalArrangement differs on only one actionButton(should place on most
+ // left)/only one confirmButton(should place on most right)/two buttons exist the same
+ // time(should be one on the left, one on the right)
+ item {
+ CtaButtonRow(
+ leftButton = if (totalEntriesCount > 1) {
+ {
+ ActionButton(
+ stringResource(R.string.get_dialog_use_saved_passkey_for),
+ onMoreOptionSelected
+ )
+ }
+ } else null,
+ rightButton = if (activeEntry != null) { // Only one sign-in options exist
+ {
+ ConfirmButton(
+ stringResource(R.string.string_continue),
+ onClick = onConfirm
+ )
+ }
+ } else null,
)
}
}
}
/** Draws the secondary credential selection page, where all sign-in options are listed. */
-@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AllSignInOptionCard(
providerInfoList: List<ProviderInfo>,
@@ -283,88 +258,52 @@ fun AllSignInOptionCard(
val sortedUserNameToCredentialEntryList =
providerDisplayInfo.sortedUserNameToCredentialEntryList
val authenticationEntryList = providerDisplayInfo.authenticationEntryList
- ContainerCard() {
- Column() {
- TopAppBar(
- colors = TopAppBarDefaults.topAppBarColors(
- containerColor = Color.Transparent,
- ),
- title = {
- TextOnSurface(
- text = stringResource(R.string.get_dialog_title_sign_in_options),
- style = MaterialTheme.typography.titleMedium
- )
- },
- navigationIcon = {
- IconButton(onClick = if (isNoAccount) onCancel else onBackButtonClicked) {
- Icon(
- Icons.Filled.ArrowBack,
- contentDescription = stringResource(
- R.string.accessibility_back_arrow_button)
- )
- }
- },
- modifier = Modifier.padding(top = 12.dp)
+ SheetContainerCard(topAppBar = {
+ MoreOptionTopAppBar(
+ text = stringResource(R.string.get_dialog_title_sign_in_options),
+ onNavigationIconClicked = if (isNoAccount) onCancel else onBackButtonClicked,
+ )
+ }) {
+ // For username
+ items(sortedUserNameToCredentialEntryList) { item ->
+ PerUserNameCredentials(
+ perUserNameCredentialEntryList = item,
+ onEntrySelected = onEntrySelected,
)
-
- ContainerCard(
- shape = MaterialTheme.shapes.large,
- modifier = Modifier
- .padding(start = 24.dp, end = 24.dp, bottom = 24.dp)
- .align(alignment = Alignment.CenterHorizontally),
- ) {
- LazyColumn(
- verticalArrangement = Arrangement.spacedBy(8.dp)
- ) {
- // For username
- items(sortedUserNameToCredentialEntryList) { item ->
- PerUserNameCredentials(
- perUserNameCredentialEntryList = item,
- onEntrySelected = onEntrySelected,
- )
- }
- // Locked password manager
- if (authenticationEntryList.isNotEmpty()) {
- item {
- LockedCredentials(
- authenticationEntryList = authenticationEntryList,
- onEntrySelected = onEntrySelected,
- )
- }
- }
- item {
- Divider(
- thickness = 8.dp,
- color = Color.Transparent,
- )
- }
- // From another device
- val remoteEntry = providerDisplayInfo.remoteEntry
- if (remoteEntry != null) {
- item {
- RemoteEntryCard(
- remoteEntry = remoteEntry,
- onEntrySelected = onEntrySelected,
- )
- }
- }
- item {
- Divider(
- thickness = 1.dp,
- color = Color.LightGray,
- modifier = Modifier.padding(top = 16.dp)
- )
- }
- // Manage sign-ins (action chips)
- item {
- ActionChips(
- providerInfoList = providerInfoList,
- onEntrySelected = onEntrySelected
- )
- }
- }
+ }
+ // Locked password manager
+ if (authenticationEntryList.isNotEmpty()) {
+ item {
+ LockedCredentials(
+ authenticationEntryList = authenticationEntryList,
+ onEntrySelected = onEntrySelected,
+ )
+ }
+ }
+ // From another device
+ val remoteEntry = providerDisplayInfo.remoteEntry
+ if (remoteEntry != null) {
+ item {
+ RemoteEntryCard(
+ remoteEntry = remoteEntry,
+ onEntrySelected = onEntrySelected,
+ )
}
}
+ item {
+ Divider(
+ thickness = 1.dp,
+ color = Color.LightGray,
+ modifier = Modifier.padding(top = 16.dp)
+ )
+ }
+ // Manage sign-ins (action chips)
+ item {
+ ActionChips(
+ providerInfoList = providerInfoList,
+ onEntrySelected = onEntrySelected
+ )
+ }
}
}
@@ -381,17 +320,11 @@ fun ActionChips(
return
}
- TextSecondary(
- text = stringResource(R.string.get_dialog_heading_manage_sign_ins),
- style = MaterialTheme.typography.titleLarge,
- modifier = Modifier.padding(vertical = 8.dp)
+ CredentialListSectionHeader(
+ text = stringResource(R.string.get_dialog_heading_manage_sign_ins)
)
- // TODO: tweak padding.
- ContainerCard(
- modifier = Modifier.fillMaxWidth().wrapContentHeight(),
- shape = MaterialTheme.shapes.medium,
- ) {
- Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
+ CredentialContainerCard {
+ Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
actionChips.forEach {
ActionEntryRow(it, onEntrySelected)
}
@@ -404,38 +337,20 @@ fun RemoteEntryCard(
remoteEntry: RemoteEntryInfo,
onEntrySelected: (BaseEntry) -> Unit,
) {
- TextSecondary(
- text = stringResource(R.string.get_dialog_heading_from_another_device),
- style = MaterialTheme.typography.titleLarge,
- modifier = Modifier.padding(vertical = 8.dp)
+ CredentialListSectionHeader(
+ text = stringResource(R.string.get_dialog_heading_from_another_device)
)
- ContainerCard(
- modifier = Modifier.fillMaxWidth().wrapContentHeight(),
- shape = MaterialTheme.shapes.medium,
- ) {
+ CredentialContainerCard {
Column(
modifier = Modifier.fillMaxWidth().wrapContentHeight(),
verticalArrangement = Arrangement.spacedBy(2.dp),
) {
Entry(
onClick = { onEntrySelected(remoteEntry) },
- icon = {
- Icon(
- painter = painterResource(R.drawable.ic_other_devices),
- contentDescription = null,
- tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant,
- modifier = Modifier.padding(start = 10.dp)
- )
- },
- label = {
- TextOnSurfaceVariant(
- text = stringResource(
- R.string.get_dialog_option_headline_use_a_different_device),
- style = MaterialTheme.typography.titleLarge,
- modifier = Modifier.padding(start = 10.dp, top = 18.dp, bottom = 18.dp)
- .align(alignment = Alignment.CenterHorizontally)
- )
- }
+ iconImageVector = Icons.Outlined.QrCodeScanner,
+ entryHeadlineText = stringResource(
+ R.string.get_dialog_option_headline_use_a_different_device
+ ),
)
}
}
@@ -446,15 +361,10 @@ fun LockedCredentials(
authenticationEntryList: List<AuthenticationEntryInfo>,
onEntrySelected: (BaseEntry) -> Unit,
) {
- TextSecondary(
- text = stringResource(R.string.get_dialog_heading_locked_password_managers),
- style = MaterialTheme.typography.labelLarge,
- modifier = Modifier.padding(vertical = 8.dp)
+ CredentialListSectionHeader(
+ text = stringResource(R.string.get_dialog_heading_locked_password_managers)
)
- ContainerCard(
- modifier = Modifier.fillMaxWidth().wrapContentHeight(),
- shape = MaterialTheme.shapes.medium,
- ) {
+ CredentialContainerCard {
Column(
modifier = Modifier.fillMaxWidth().wrapContentHeight(),
verticalArrangement = Arrangement.spacedBy(2.dp),
@@ -471,17 +381,12 @@ fun PerUserNameCredentials(
perUserNameCredentialEntryList: PerUserNameCredentialEntryList,
onEntrySelected: (BaseEntry) -> Unit,
) {
- TextSecondary(
+ CredentialListSectionHeader(
text = stringResource(
R.string.get_dialog_heading_for_username, perUserNameCredentialEntryList.userName
- ),
- style = MaterialTheme.typography.titleLarge,
- modifier = Modifier.padding(vertical = 8.dp)
+ )
)
- ContainerCard(
- modifier = Modifier.fillMaxWidth().wrapContentHeight(),
- shape = MaterialTheme.shapes.medium,
- ) {
+ CredentialContainerCard {
Column(
modifier = Modifier.fillMaxWidth().wrapContentHeight(),
verticalArrangement = Arrangement.spacedBy(2.dp),
@@ -500,53 +405,29 @@ fun CredentialEntryRow(
) {
Entry(
onClick = { onEntrySelected(credentialEntryInfo) },
- icon = {
- if (credentialEntryInfo.icon != null) {
- Image(
- modifier = Modifier.padding(start = 10.dp).size(32.dp),
- bitmap = credentialEntryInfo.icon.toBitmap().asImageBitmap(),
- contentDescription = null,
- )
- } else {
- Icon(
- modifier = Modifier.padding(start = 10.dp).size(32.dp),
- painter = painterResource(R.drawable.ic_other_sign_in),
- contentDescription = null,
- tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant
- )
- }
+ iconImageBitmap = credentialEntryInfo.icon?.toBitmap()?.asImageBitmap(),
+ // Fall back to iconPainter if iconImageBitmap isn't available
+ iconPainter =
+ if (credentialEntryInfo.icon == null) painterResource(R.drawable.ic_other_sign_in_24)
+ else null,
+ entryHeadlineText = credentialEntryInfo.userName,
+ entrySecondLineText = if (
+ credentialEntryInfo.credentialType == CredentialType.PASSWORD) {
+ "••••••••••••"
+ } else {
+ val itemsToDisplay = listOf(
+ credentialEntryInfo.displayName,
+ credentialEntryInfo.credentialTypeDisplayName,
+ credentialEntryInfo.providerDisplayName
+ ).filterNot(TextUtils::isEmpty)
+ if (itemsToDisplay.isEmpty()) null
+ else itemsToDisplay.joinToString(
+ separator = stringResource(R.string.get_dialog_sign_in_type_username_separator)
+ )
},
- label = {
- Column() {
- // TODO: fix the text values.
- TextOnSurfaceVariant(
- text = credentialEntryInfo.userName,
- style = MaterialTheme.typography.titleLarge,
- modifier = Modifier.padding(top = 16.dp, start = 5.dp)
- )
- TextSecondary(
- text = if (
- credentialEntryInfo.credentialType == CredentialType.PASSWORD) {
- "••••••••••••"
- } else {
- if (TextUtils.isEmpty(credentialEntryInfo.displayName))
- credentialEntryInfo.credentialTypeDisplayName
- else
- credentialEntryInfo.credentialTypeDisplayName +
- stringResource(
- R.string.get_dialog_sign_in_type_username_separator
- ) +
- credentialEntryInfo.displayName
- },
- style = MaterialTheme.typography.bodyMedium,
- modifier = Modifier.padding(bottom = 16.dp, start = 5.dp)
- )
- }
- }
)
}
-@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AuthenticationEntryRow(
authenticationEntryInfo: AuthenticationEntryInfo,
@@ -554,144 +435,66 @@ fun AuthenticationEntryRow(
) {
Entry(
onClick = { onEntrySelected(authenticationEntryInfo) },
- icon = {
- Image(
- modifier = Modifier.padding(start = 10.dp).size(32.dp),
- bitmap = authenticationEntryInfo.icon.toBitmap().asImageBitmap(),
- contentDescription = null
- )
- },
- label = {
- Row(
- horizontalArrangement = Arrangement.SpaceBetween,
- modifier = Modifier.fillMaxWidth().padding(horizontal = 5.dp),
- ) {
- Column() {
- TextOnSurfaceVariant(
- text = authenticationEntryInfo.title,
- style = MaterialTheme.typography.titleLarge,
- modifier = Modifier.padding(top = 16.dp)
- )
- TextSecondary(
- text = stringResource(
- if (authenticationEntryInfo.isUnlockedAndEmpty)
- R.string.locked_credential_entry_label_subtext_no_sign_in
- else R.string.locked_credential_entry_label_subtext_tap_to_unlock
- ),
- style = MaterialTheme.typography.bodyMedium,
- modifier = Modifier.padding(bottom = 16.dp)
- )
- }
- if (!authenticationEntryInfo.isUnlockedAndEmpty) {
- Icon(
- Icons.Outlined.Lock,
- null,
- Modifier.align(alignment = Alignment.CenterVertically).padding(end = 10.dp),
- )
- }
- }
- }
+ iconImageBitmap = authenticationEntryInfo.icon.toBitmap().asImageBitmap(),
+ entryHeadlineText = authenticationEntryInfo.title,
+ entrySecondLineText = stringResource(
+ if (authenticationEntryInfo.isUnlockedAndEmpty)
+ R.string.locked_credential_entry_label_subtext_no_sign_in
+ else R.string.locked_credential_entry_label_subtext_tap_to_unlock
+ ),
+ isLockedAuthEntry = !authenticationEntryInfo.isUnlockedAndEmpty,
)
}
-@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ActionEntryRow(
actionEntryInfo: ActionEntryInfo,
onEntrySelected: (BaseEntry) -> Unit,
) {
- TransparentBackgroundEntry(
- icon = {
- Image(
- modifier = Modifier.padding(start = 10.dp).size(24.dp),
- bitmap = actionEntryInfo.icon.toBitmap().asImageBitmap(),
- contentDescription = null,
- )
- },
- label = {
- Column() {
- TextOnSurfaceVariant(
- text = actionEntryInfo.title,
- style = MaterialTheme.typography.titleLarge,
- modifier = Modifier.padding(start = 8.dp),
- )
- if (actionEntryInfo.subTitle != null) {
- TextSecondary(
- text = actionEntryInfo.subTitle,
- style = MaterialTheme.typography.bodyMedium,
- modifier = Modifier.padding(start = 8.dp),
- )
- }
- }
- },
+ ActionEntry(
+ iconImageBitmap = actionEntryInfo.icon.toBitmap().asImageBitmap(),
+ entryHeadlineText = actionEntryInfo.title,
+ entrySecondLineText = actionEntryInfo.subTitle,
onClick = { onEntrySelected(actionEntryInfo) },
)
}
-@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun RemoteCredentialSnackBarScreen(
onClick: (Boolean) -> Unit,
onCancel: () -> Unit,
) {
- // TODO: Change the height, width and position according to the design
Snackbar(
- modifier = Modifier.padding(horizontal = 40.dp).padding(top = 700.dp),
- shape = EntryShape.FullMediumRoundedCorner,
- containerColor = LocalAndroidColorScheme.current.colorBackground,
- contentColor = LocalAndroidColorScheme.current.colorAccentPrimaryVariant,
action = {
TextButton(
+ modifier = Modifier.padding(top = 4.dp, bottom = 4.dp, start = 16.dp)
+ .heightIn(min = 32.dp),
onClick = { onClick(true) },
+ contentPadding =
+ PaddingValues(start = 0.dp, top = 6.dp, end = 0.dp, bottom = 6.dp),
) {
- Text(text = stringResource(R.string.snackbar_action))
+ SnackbarActionText(text = stringResource(R.string.snackbar_action))
}
},
- dismissAction = {
- IconButton(onClick = onCancel) {
- Icon(
- Icons.Filled.Close,
- contentDescription = stringResource(
- R.string.accessibility_close_button
- ),
- tint = LocalAndroidColorScheme.current.colorAccentTertiary
- )
- }
- },
- ) {
- Text(text = stringResource(R.string.get_dialog_use_saved_passkey_for))
- }
+ onDismiss = onCancel,
+ contentText = stringResource(R.string.get_dialog_use_saved_passkey_for),
+ )
}
-@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun EmptyAuthEntrySnackBarScreen(
authenticationEntryList: List<AuthenticationEntryInfo>,
onCancel: () -> Unit,
onLastLockedAuthEntryNotFound: () -> Unit,
) {
- val lastLocked = authenticationEntryList.firstOrNull({it.isLastUnlocked})
+ val lastLocked = authenticationEntryList.firstOrNull({ it.isLastUnlocked })
if (lastLocked == null) {
onLastLockedAuthEntryNotFound()
return
}
- // TODO: Change the height, width and position according to the design
Snackbar(
- modifier = Modifier.padding(horizontal = 40.dp).padding(top = 700.dp),
- shape = EntryShape.FullMediumRoundedCorner,
- containerColor = LocalAndroidColorScheme.current.colorBackground,
- contentColor = LocalAndroidColorScheme.current.colorAccentPrimaryVariant,
- dismissAction = {
- IconButton(onClick = onCancel) {
- Icon(
- Icons.Filled.Close,
- contentDescription = stringResource(R.string.accessibility_close_button),
- tint = LocalAndroidColorScheme.current.colorAccentTertiary
- )
- }
- },
- ) {
- Text(text = stringResource(R.string.no_sign_in_info_in, lastLocked.title))
- }
+ onDismiss = onCancel,
+ contentText = stringResource(R.string.no_sign_in_info_in, lastLocked.providerDisplayName),
+ )
} \ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt
index 49415c01033d..56bc19ae7041 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt
@@ -37,7 +37,8 @@ data class GetCredentialUiState(
internal fun hasContentToDisplay(state: GetCredentialUiState): Boolean {
return state.providerDisplayInfo.sortedUserNameToCredentialEntryList.isNotEmpty() ||
state.providerDisplayInfo.authenticationEntryList.isNotEmpty() ||
- state.providerDisplayInfo.remoteEntry != null
+ (state.providerDisplayInfo.remoteEntry != null &&
+ !state.requestDisplayInfo.preferImmediatelyAvailableCredentials)
}
data class ProviderInfo(
@@ -76,6 +77,7 @@ class CredentialEntryInfo(
val credentialType: CredentialType,
/** Localized type value of this credential used for display purpose. */
val credentialTypeDisplayName: String,
+ val providerDisplayName: String,
val userName: String,
val displayName: String?,
val icon: Drawable?,
@@ -96,6 +98,7 @@ class AuthenticationEntryInfo(
pendingIntent: PendingIntent?,
fillInIntent: Intent?,
val title: String,
+ val providerDisplayName: String,
val icon: Drawable,
// The entry had been unlocked and turned out to be empty. Used to determine whether to
// show "Tap to unlock" or "No sign-in info" for this entry.
@@ -140,11 +143,12 @@ class ActionEntryInfo(
entrySubkey,
pendingIntent,
fillInIntent,
- shouldTerminateUiUponSuccessfulProviderResult = false,
+ shouldTerminateUiUponSuccessfulProviderResult = true,
)
data class RequestDisplayInfo(
val appName: String,
+ val preferImmediatelyAvailableCredentials: Boolean,
)
/**
@@ -245,7 +249,6 @@ private fun toActiveEntry(
private fun toGetScreenState(
providerDisplayInfo: ProviderDisplayInfo
): GetScreenState {
-
return if (providerDisplayInfo.sortedUserNameToCredentialEntryList.isEmpty() &&
providerDisplayInfo.remoteEntry == null &&
providerDisplayInfo.authenticationEntryList.all { it.isUnlockedAndEmpty })
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/AndroidColorScheme.kt b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/AndroidColorScheme.kt
index 15ae3295416b..8928e1869838 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/AndroidColorScheme.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/AndroidColorScheme.kt
@@ -22,12 +22,14 @@ import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.graphics.Color
import com.android.internal.R
+/** File copied from PlatformComposeCore. */
+
/** CompositionLocal used to pass [AndroidColorScheme] down the tree. */
val LocalAndroidColorScheme =
staticCompositionLocalOf<AndroidColorScheme> {
throw IllegalStateException(
"No AndroidColorScheme configured. Make sure to use LocalAndroidColorScheme in a " +
- "Composable surrounded by a CredentialSelectorTheme {}."
+ "Composable surrounded by a PlatformTheme {}."
)
}
@@ -38,38 +40,15 @@ val LocalAndroidColorScheme =
* most of the colors in this class will be removed in favor of their M3 counterpart.
*/
class AndroidColorScheme internal constructor(context: Context) {
+ val colorSurfaceBright = getColor(context, R.attr.materialColorSurfaceBright)
+ val colorSurfaceContainerHigh = getColor(context, R.attr.materialColorSurfaceContainerHigh)
- val colorPrimary = getColor(context, R.attr.colorPrimary)
- val colorPrimaryDark = getColor(context, R.attr.colorPrimaryDark)
- val colorAccent = getColor(context, R.attr.colorAccent)
- val colorAccentPrimary = getColor(context, R.attr.colorAccentPrimary)
- val colorAccentSecondary = getColor(context, R.attr.colorAccentSecondary)
- val colorAccentTertiary = getColor(context, R.attr.colorAccentTertiary)
- val colorAccentPrimaryVariant = getColor(context, R.attr.colorAccentPrimaryVariant)
- val colorAccentSecondaryVariant = getColor(context, R.attr.colorAccentSecondaryVariant)
- val colorAccentTertiaryVariant = getColor(context, R.attr.colorAccentTertiaryVariant)
- val colorSurface = getColor(context, R.attr.colorSurface)
- val colorSurfaceHighlight = getColor(context, R.attr.colorSurfaceHighlight)
- val colorSurfaceVariant = getColor(context, R.attr.colorSurfaceVariant)
- val colorSurfaceHeader = getColor(context, R.attr.colorSurfaceHeader)
- val colorError = getColor(context, R.attr.colorError)
- val colorBackground = getColor(context, R.attr.colorBackground)
- val colorBackgroundFloating = getColor(context, R.attr.colorBackgroundFloating)
- val panelColorBackground = getColor(context, R.attr.panelColorBackground)
- val textColorPrimary = getColor(context, R.attr.textColorPrimary)
- val textColorSecondary = getColor(context, R.attr.textColorSecondary)
- val textColorTertiary = getColor(context, R.attr.textColorTertiary)
- val textColorPrimaryInverse = getColor(context, R.attr.textColorPrimaryInverse)
- val textColorSecondaryInverse = getColor(context, R.attr.textColorSecondaryInverse)
- val textColorTertiaryInverse = getColor(context, R.attr.textColorTertiaryInverse)
- val textColorOnAccent = getColor(context, R.attr.textColorOnAccent)
- val colorForeground = getColor(context, R.attr.colorForeground)
- val colorForegroundInverse = getColor(context, R.attr.colorForegroundInverse)
-
- private fun getColor(context: Context, attr: Int): Color {
- val ta = context.obtainStyledAttributes(intArrayOf(attr))
- @ColorInt val color = ta.getColor(0, 0)
- ta.recycle()
- return Color(color)
+ companion object {
+ fun getColor(context: Context, attr: Int): Color {
+ val ta = context.obtainStyledAttributes(intArrayOf(attr))
+ @ColorInt val color = ta.getColor(0, 0)
+ ta.recycle()
+ return Color(color)
+ }
}
}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/Color.kt b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/Color.kt
index abb4bfbf915e..c9238459633c 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/Color.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/Color.kt
@@ -1,14 +1,30 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package com.android.credentialmanager.ui.theme
+import android.annotation.AttrRes
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.LocalContext
-val Grey100 = Color(0xFFF1F3F4)
-val Purple200 = Color(0xFFBB86FC)
-val Purple500 = Color(0xFF6200EE)
-val Purple700 = Color(0xFF3700B3)
-val Teal200 = Color(0xFF03DAC5)
-val lightColorAccentSecondary = Color(0xFFC2E7FF)
-val lightBackgroundColor = Color(0xFFF0F0F0)
-val lightSurface1 = Color(0xFF6991D6)
-val textColorSecondary = Color(0xFF40484B)
-val textColorPrimary = Color(0xFF191C1D)
+/** Read the [Color] from the given [attribute]. */
+@Composable
+@ReadOnlyComposable
+fun colorAttr(@AttrRes attribute: Int): Color {
+ return AndroidColorScheme.getColor(LocalContext.current, attribute)
+}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/PlatformTheme.kt b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/PlatformTheme.kt
new file mode 100644
index 000000000000..662199a4bba5
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/PlatformTheme.kt
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.credentialmanager.ui.theme
+
+import androidx.compose.foundation.isSystemInDarkTheme
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.dynamicDarkColorScheme
+import androidx.compose.material3.dynamicLightColorScheme
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.remember
+import androidx.compose.ui.platform.LocalContext
+import com.android.credentialmanager.ui.theme.typography.TypeScaleTokens
+import com.android.credentialmanager.ui.theme.typography.TypefaceNames
+import com.android.credentialmanager.ui.theme.typography.TypefaceTokens
+import com.android.credentialmanager.ui.theme.typography.TypographyTokens
+import com.android.credentialmanager.ui.theme.typography.platformTypography
+
+/** File copied from PlatformComposeCore. */
+
+/** The Material 3 theme that should wrap all Platform Composables. */
+@Composable
+fun PlatformTheme(
+ isDarkTheme: Boolean = isSystemInDarkTheme(),
+ content: @Composable () -> Unit,
+) {
+ val context = LocalContext.current
+
+ // TODO(b/230605885): Define our color scheme.
+ val colorScheme =
+ if (isDarkTheme) {
+ dynamicDarkColorScheme(context)
+ } else {
+ dynamicLightColorScheme(context)
+ }
+ val androidColorScheme = AndroidColorScheme(context)
+ val typefaceNames = remember(context) { TypefaceNames.get(context) }
+ val typography =
+ remember(typefaceNames) {
+ platformTypography(TypographyTokens(TypeScaleTokens(TypefaceTokens(typefaceNames))))
+ }
+
+ MaterialTheme(colorScheme, typography = typography) {
+ CompositionLocalProvider(
+ LocalAndroidColorScheme provides androidColorScheme,
+ ) {
+ content()
+ }
+ }
+}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/Theme.kt b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/Theme.kt
deleted file mode 100644
index 3ca0e4494ab6..000000000000
--- a/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/Theme.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.android.credentialmanager.ui.theme
-
-import androidx.compose.foundation.isSystemInDarkTheme
-import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.dynamicDarkColorScheme
-import androidx.compose.material3.dynamicLightColorScheme
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.ui.platform.LocalContext
-
-@Composable
-fun CredentialSelectorTheme(
- darkTheme: Boolean = isSystemInDarkTheme(),
- content: @Composable () -> Unit
-) {
- val context = LocalContext.current
-
- val colorScheme =
- if (darkTheme) {
- dynamicDarkColorScheme(context)
- } else {
- dynamicLightColorScheme(context)
- }
- val androidColorScheme = AndroidColorScheme(context)
- val typography = Typography
-
- MaterialTheme(
- colorScheme,
- typography = typography,
- shapes = Shapes
- ) {
- CompositionLocalProvider(
- LocalAndroidColorScheme provides androidColorScheme,
- ) {
- content()
- }
- }
-}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/Type.kt b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/Type.kt
deleted file mode 100644
index e09abbb3ffff..000000000000
--- a/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/Type.kt
+++ /dev/null
@@ -1,56 +0,0 @@
-package com.android.credentialmanager.ui.theme
-
-import androidx.compose.material3.Typography
-import androidx.compose.ui.text.TextStyle
-import androidx.compose.ui.text.font.FontFamily
-import androidx.compose.ui.text.font.FontWeight
-import androidx.compose.ui.unit.sp
-
-// Set of Material typography styles to start with
-val Typography = Typography(
- titleMedium = TextStyle(
- fontFamily = FontFamily.Default,
- fontWeight = FontWeight.Normal,
- fontSize = 24.sp,
- lineHeight = 32.sp,
- ),
- bodyLarge = TextStyle(
- fontFamily = FontFamily.Default,
- fontWeight = FontWeight.Normal,
- fontSize = 14.sp,
- lineHeight = 20.sp,
- ),
- bodyMedium = TextStyle(
- fontFamily = FontFamily.Default,
- fontWeight = FontWeight.Normal,
- fontSize = 14.sp,
- lineHeight = 20.sp,
- color = textColorSecondary
- ),
- labelLarge = TextStyle(
- fontFamily = FontFamily.Default,
- fontWeight = FontWeight.Medium,
- fontSize = 14.sp,
- lineHeight = 20.sp,
- ),
- titleLarge = TextStyle(
- fontFamily = FontFamily.Default,
- fontWeight = FontWeight.Medium,
- fontSize = 16.sp,
- lineHeight = 24.sp,
- color = textColorPrimary
- ),
-
- /* Other default text styles to override
- button = TextStyle(
- fontFamily = FontFamily.Default,
- fontWeight = FontWeight.W500,
- fontSize = 14.sp
- ),
- caption = TextStyle(
- fontFamily = FontFamily.Default,
- fontWeight = FontWeight.Normal,
- fontSize = 12.sp
- )
- */
-)
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/typography/PlatformTypography.kt b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/typography/PlatformTypography.kt
new file mode 100644
index 000000000000..984e4f19e4d4
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/typography/PlatformTypography.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.credentialmanager.ui.theme.typography
+
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Typography
+
+/** File copied from PlatformComposeCore. */
+
+/**
+ * The typography for Platform Compose code.
+ *
+ * Do not use directly and call [MaterialTheme.typography] instead to access the different text
+ * styles.
+ */
+internal fun platformTypography(typographyTokens: TypographyTokens): Typography {
+ return Typography(
+ displayLarge = typographyTokens.displayLarge,
+ displayMedium = typographyTokens.displayMedium,
+ displaySmall = typographyTokens.displaySmall,
+ headlineLarge = typographyTokens.headlineLarge,
+ headlineMedium = typographyTokens.headlineMedium,
+ headlineSmall = typographyTokens.headlineSmall,
+ titleLarge = typographyTokens.titleLarge,
+ titleMedium = typographyTokens.titleMedium,
+ titleSmall = typographyTokens.titleSmall,
+ bodyLarge = typographyTokens.bodyLarge,
+ bodyMedium = typographyTokens.bodyMedium,
+ bodySmall = typographyTokens.bodySmall,
+ labelLarge = typographyTokens.labelLarge,
+ labelMedium = typographyTokens.labelMedium,
+ labelSmall = typographyTokens.labelSmall,
+ )
+}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/typography/TypeScaleTokens.kt b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/typography/TypeScaleTokens.kt
new file mode 100644
index 000000000000..b2dd20720f6a
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/typography/TypeScaleTokens.kt
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.credentialmanager.ui.theme.typography
+
+import androidx.compose.ui.unit.sp
+
+/** File copied from PlatformComposeCore. */
+internal class TypeScaleTokens(typefaceTokens: TypefaceTokens) {
+ val bodyLargeFont = typefaceTokens.plain
+ val bodyLargeLineHeight = 24.0.sp
+ val bodyLargeSize = 16.sp
+ val bodyLargeTracking = 0.0.sp
+ val bodyLargeWeight = TypefaceTokens.WeightRegular
+ val bodyMediumFont = typefaceTokens.plain
+ val bodyMediumLineHeight = 20.0.sp
+ val bodyMediumSize = 14.sp
+ val bodyMediumTracking = 0.0.sp
+ val bodyMediumWeight = TypefaceTokens.WeightRegular
+ val bodySmallFont = typefaceTokens.plain
+ val bodySmallLineHeight = 16.0.sp
+ val bodySmallSize = 12.sp
+ val bodySmallTracking = 0.1.sp
+ val bodySmallWeight = TypefaceTokens.WeightRegular
+ val displayLargeFont = typefaceTokens.brand
+ val displayLargeLineHeight = 64.0.sp
+ val displayLargeSize = 57.sp
+ val displayLargeTracking = 0.0.sp
+ val displayLargeWeight = TypefaceTokens.WeightRegular
+ val displayMediumFont = typefaceTokens.brand
+ val displayMediumLineHeight = 52.0.sp
+ val displayMediumSize = 45.sp
+ val displayMediumTracking = 0.0.sp
+ val displayMediumWeight = TypefaceTokens.WeightRegular
+ val displaySmallFont = typefaceTokens.brand
+ val displaySmallLineHeight = 44.0.sp
+ val displaySmallSize = 36.sp
+ val displaySmallTracking = 0.0.sp
+ val displaySmallWeight = TypefaceTokens.WeightRegular
+ val headlineLargeFont = typefaceTokens.brand
+ val headlineLargeLineHeight = 40.0.sp
+ val headlineLargeSize = 32.sp
+ val headlineLargeTracking = 0.0.sp
+ val headlineLargeWeight = TypefaceTokens.WeightRegular
+ val headlineMediumFont = typefaceTokens.brand
+ val headlineMediumLineHeight = 36.0.sp
+ val headlineMediumSize = 28.sp
+ val headlineMediumTracking = 0.0.sp
+ val headlineMediumWeight = TypefaceTokens.WeightRegular
+ val headlineSmallFont = typefaceTokens.brand
+ val headlineSmallLineHeight = 32.0.sp
+ val headlineSmallSize = 24.sp
+ val headlineSmallTracking = 0.0.sp
+ val headlineSmallWeight = TypefaceTokens.WeightRegular
+ val labelLargeFont = typefaceTokens.plain
+ val labelLargeLineHeight = 20.0.sp
+ val labelLargeSize = 14.sp
+ val labelLargeTracking = 0.0.sp
+ val labelLargeWeight = TypefaceTokens.WeightMedium
+ val labelMediumFont = typefaceTokens.plain
+ val labelMediumLineHeight = 16.0.sp
+ val labelMediumSize = 12.sp
+ val labelMediumTracking = 0.1.sp
+ val labelMediumWeight = TypefaceTokens.WeightMedium
+ val labelSmallFont = typefaceTokens.plain
+ val labelSmallLineHeight = 16.0.sp
+ val labelSmallSize = 11.sp
+ val labelSmallTracking = 0.1.sp
+ val labelSmallWeight = TypefaceTokens.WeightMedium
+ val titleLargeFont = typefaceTokens.brand
+ val titleLargeLineHeight = 28.0.sp
+ val titleLargeSize = 22.sp
+ val titleLargeTracking = 0.0.sp
+ val titleLargeWeight = TypefaceTokens.WeightRegular
+ val titleMediumFont = typefaceTokens.plain
+ val titleMediumLineHeight = 24.0.sp
+ val titleMediumSize = 16.sp
+ val titleMediumTracking = 0.0.sp
+ val titleMediumWeight = TypefaceTokens.WeightMedium
+ val titleSmallFont = typefaceTokens.plain
+ val titleSmallLineHeight = 20.0.sp
+ val titleSmallSize = 14.sp
+ val titleSmallTracking = 0.0.sp
+ val titleSmallWeight = TypefaceTokens.WeightMedium
+}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/typography/TypefaceTokens.kt b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/typography/TypefaceTokens.kt
new file mode 100644
index 000000000000..3cc761f1cc60
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/typography/TypefaceTokens.kt
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:OptIn(ExperimentalTextApi::class)
+
+package com.android.credentialmanager.ui.theme.typography
+
+import android.content.Context
+import androidx.compose.ui.text.ExperimentalTextApi
+import androidx.compose.ui.text.font.DeviceFontFamilyName
+import androidx.compose.ui.text.font.Font
+import androidx.compose.ui.text.font.FontFamily
+import androidx.compose.ui.text.font.FontWeight
+
+/** File copied from PlatformComposeCore. */
+internal class TypefaceTokens(typefaceNames: TypefaceNames) {
+ companion object {
+ val WeightMedium = FontWeight.Medium
+ val WeightRegular = FontWeight.Normal
+ }
+
+ private val brandFont = DeviceFontFamilyName(typefaceNames.brand)
+ private val plainFont = DeviceFontFamilyName(typefaceNames.plain)
+
+ val brand =
+ FontFamily(
+ Font(brandFont, weight = WeightMedium),
+ Font(brandFont, weight = WeightRegular),
+ )
+ val plain =
+ FontFamily(
+ Font(plainFont, weight = WeightMedium),
+ Font(plainFont, weight = WeightRegular),
+ )
+}
+
+internal data class TypefaceNames
+private constructor(
+ val brand: String,
+ val plain: String,
+) {
+ private enum class Config(val configName: String, val default: String) {
+ Brand("config_headlineFontFamily", "sans-serif"),
+ Plain("config_bodyFontFamily", "sans-serif"),
+ }
+
+ companion object {
+ fun get(context: Context): TypefaceNames {
+ return TypefaceNames(
+ brand = getTypefaceName(context, Config.Brand),
+ plain = getTypefaceName(context, Config.Plain),
+ )
+ }
+
+ private fun getTypefaceName(context: Context, config: Config): String {
+ return context
+ .getString(context.resources.getIdentifier(config.configName, "string", "android"))
+ .takeIf { it.isNotEmpty() }
+ ?: config.default
+ }
+ }
+}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/typography/TypographyTokens.kt b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/typography/TypographyTokens.kt
new file mode 100644
index 000000000000..aadab92f40cc
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/typography/TypographyTokens.kt
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.credentialmanager.ui.theme.typography
+
+import androidx.compose.ui.text.TextStyle
+
+/** File copied from PlatformComposeCore. */
+internal class TypographyTokens(typeScaleTokens: TypeScaleTokens) {
+ val bodyLarge =
+ TextStyle(
+ fontFamily = typeScaleTokens.bodyLargeFont,
+ fontWeight = typeScaleTokens.bodyLargeWeight,
+ fontSize = typeScaleTokens.bodyLargeSize,
+ lineHeight = typeScaleTokens.bodyLargeLineHeight,
+ letterSpacing = typeScaleTokens.bodyLargeTracking,
+ )
+ val bodyMedium =
+ TextStyle(
+ fontFamily = typeScaleTokens.bodyMediumFont,
+ fontWeight = typeScaleTokens.bodyMediumWeight,
+ fontSize = typeScaleTokens.bodyMediumSize,
+ lineHeight = typeScaleTokens.bodyMediumLineHeight,
+ letterSpacing = typeScaleTokens.bodyMediumTracking,
+ )
+ val bodySmall =
+ TextStyle(
+ fontFamily = typeScaleTokens.bodySmallFont,
+ fontWeight = typeScaleTokens.bodySmallWeight,
+ fontSize = typeScaleTokens.bodySmallSize,
+ lineHeight = typeScaleTokens.bodySmallLineHeight,
+ letterSpacing = typeScaleTokens.bodySmallTracking,
+ )
+ val displayLarge =
+ TextStyle(
+ fontFamily = typeScaleTokens.displayLargeFont,
+ fontWeight = typeScaleTokens.displayLargeWeight,
+ fontSize = typeScaleTokens.displayLargeSize,
+ lineHeight = typeScaleTokens.displayLargeLineHeight,
+ letterSpacing = typeScaleTokens.displayLargeTracking,
+ )
+ val displayMedium =
+ TextStyle(
+ fontFamily = typeScaleTokens.displayMediumFont,
+ fontWeight = typeScaleTokens.displayMediumWeight,
+ fontSize = typeScaleTokens.displayMediumSize,
+ lineHeight = typeScaleTokens.displayMediumLineHeight,
+ letterSpacing = typeScaleTokens.displayMediumTracking,
+ )
+ val displaySmall =
+ TextStyle(
+ fontFamily = typeScaleTokens.displaySmallFont,
+ fontWeight = typeScaleTokens.displaySmallWeight,
+ fontSize = typeScaleTokens.displaySmallSize,
+ lineHeight = typeScaleTokens.displaySmallLineHeight,
+ letterSpacing = typeScaleTokens.displaySmallTracking,
+ )
+ val headlineLarge =
+ TextStyle(
+ fontFamily = typeScaleTokens.headlineLargeFont,
+ fontWeight = typeScaleTokens.headlineLargeWeight,
+ fontSize = typeScaleTokens.headlineLargeSize,
+ lineHeight = typeScaleTokens.headlineLargeLineHeight,
+ letterSpacing = typeScaleTokens.headlineLargeTracking,
+ )
+ val headlineMedium =
+ TextStyle(
+ fontFamily = typeScaleTokens.headlineMediumFont,
+ fontWeight = typeScaleTokens.headlineMediumWeight,
+ fontSize = typeScaleTokens.headlineMediumSize,
+ lineHeight = typeScaleTokens.headlineMediumLineHeight,
+ letterSpacing = typeScaleTokens.headlineMediumTracking,
+ )
+ val headlineSmall =
+ TextStyle(
+ fontFamily = typeScaleTokens.headlineSmallFont,
+ fontWeight = typeScaleTokens.headlineSmallWeight,
+ fontSize = typeScaleTokens.headlineSmallSize,
+ lineHeight = typeScaleTokens.headlineSmallLineHeight,
+ letterSpacing = typeScaleTokens.headlineSmallTracking,
+ )
+ val labelLarge =
+ TextStyle(
+ fontFamily = typeScaleTokens.labelLargeFont,
+ fontWeight = typeScaleTokens.labelLargeWeight,
+ fontSize = typeScaleTokens.labelLargeSize,
+ lineHeight = typeScaleTokens.labelLargeLineHeight,
+ letterSpacing = typeScaleTokens.labelLargeTracking,
+ )
+ val labelMedium =
+ TextStyle(
+ fontFamily = typeScaleTokens.labelMediumFont,
+ fontWeight = typeScaleTokens.labelMediumWeight,
+ fontSize = typeScaleTokens.labelMediumSize,
+ lineHeight = typeScaleTokens.labelMediumLineHeight,
+ letterSpacing = typeScaleTokens.labelMediumTracking,
+ )
+ val labelSmall =
+ TextStyle(
+ fontFamily = typeScaleTokens.labelSmallFont,
+ fontWeight = typeScaleTokens.labelSmallWeight,
+ fontSize = typeScaleTokens.labelSmallSize,
+ lineHeight = typeScaleTokens.labelSmallLineHeight,
+ letterSpacing = typeScaleTokens.labelSmallTracking,
+ )
+ val titleLarge =
+ TextStyle(
+ fontFamily = typeScaleTokens.titleLargeFont,
+ fontWeight = typeScaleTokens.titleLargeWeight,
+ fontSize = typeScaleTokens.titleLargeSize,
+ lineHeight = typeScaleTokens.titleLargeLineHeight,
+ letterSpacing = typeScaleTokens.titleLargeTracking,
+ )
+ val titleMedium =
+ TextStyle(
+ fontFamily = typeScaleTokens.titleMediumFont,
+ fontWeight = typeScaleTokens.titleMediumWeight,
+ fontSize = typeScaleTokens.titleMediumSize,
+ lineHeight = typeScaleTokens.titleMediumLineHeight,
+ letterSpacing = typeScaleTokens.titleMediumTracking,
+ )
+ val titleSmall =
+ TextStyle(
+ fontFamily = typeScaleTokens.titleSmallFont,
+ fontWeight = typeScaleTokens.titleSmallWeight,
+ fontSize = typeScaleTokens.titleSmallSize,
+ lineHeight = typeScaleTokens.titleSmallLineHeight,
+ letterSpacing = typeScaleTokens.titleSmallTracking,
+ )
+}
diff --git a/packages/DynamicSystemInstallationService/AndroidManifest.xml b/packages/DynamicSystemInstallationService/AndroidManifest.xml
index b194738c67b6..c2aaeace1af6 100644
--- a/packages/DynamicSystemInstallationService/AndroidManifest.xml
+++ b/packages/DynamicSystemInstallationService/AndroidManifest.xml
@@ -21,12 +21,7 @@
android:exported="true"
android:permission="android.permission.INSTALL_DYNAMIC_SYSTEM"
android:foregroundServiceType="systemExempted"
- android:process=":dynsystem">
- <intent-filter>
- <action android:name="android.os.image.action.NOTIFY_IF_IN_USE" />
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- </service>
+ android:process=":dynsystem" />
<activity android:name=".VerificationActivity"
android:exported="true"
diff --git a/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java b/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
index 95b49a8ef335..73f87302dd05 100644
--- a/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
+++ b/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
@@ -21,7 +21,6 @@ import android.app.backup.BackupAgent;
import android.app.backup.BackupDataInput;
import android.app.backup.BackupDataOutput;
import android.app.backup.BackupManagerMonitor;
-import android.app.backup.BackupRestoreEventLogger;
import android.app.backup.BackupRestoreEventLogger.DataTypeResult;
import android.app.backup.BackupTransport;
import android.app.backup.RestoreDescription;
@@ -48,6 +47,7 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
/**
@@ -915,6 +915,7 @@ public class LocalTransport extends BackupTransport {
Log.i(TAG, "\tdataType: " + result.getDataType());
Log.i(TAG, "\tsuccessCount: " + result.getSuccessCount());
Log.i(TAG, "\tfailCount: " + result.getFailCount());
+ Log.i(TAG, "\tmetadataHash: " + Arrays.toString(result.getMetadataHash()));
if (!result.getErrors().isEmpty()) {
Log.i(TAG, "\terrors {");
diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp
index af20a4bd5707..750c156f95bd 100644
--- a/packages/SettingsLib/Android.bp
+++ b/packages/SettingsLib/Android.bp
@@ -70,7 +70,7 @@ android_library {
"src/**/*.kt",
],
- min_sdk_version: "29",
+ min_sdk_version: "30",
}
diff --git a/packages/SettingsLib/DeviceStateRotationLock/OWNERS b/packages/SettingsLib/DeviceStateRotationLock/OWNERS
new file mode 100644
index 000000000000..091df2610866
--- /dev/null
+++ b/packages/SettingsLib/DeviceStateRotationLock/OWNERS
@@ -0,0 +1 @@
+include platform/frameworks/base:/packages/SettingsLib/src/com/android/settingslib/devicestate/OWNERS \ No newline at end of file
diff --git a/packages/SettingsLib/Spa/.idea/codeStyles/Project.xml b/packages/SettingsLib/Spa/.idea/codeStyles/Project.xml
index 940f5c936e5b..78a740892f13 100644
--- a/packages/SettingsLib/Spa/.idea/codeStyles/Project.xml
+++ b/packages/SettingsLib/Spa/.idea/codeStyles/Project.xml
@@ -1,17 +1,12 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<JetCodeStyleSettings>
- <option name="PACKAGES_TO_USE_STAR_IMPORTS">
- <value />
- </option>
<option name="PACKAGES_IMPORT_LAYOUT">
<value>
<package name="" alias="false" withSubpackages="true" />
<package name="" alias="true" withSubpackages="true" />
</value>
</option>
- <option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" />
- <option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="2147483647" />
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>
<XML>
diff --git a/packages/SettingsLib/Spa/build.gradle b/packages/SettingsLib/Spa/build.gradle
index 42af9992f774..643af759347d 100644
--- a/packages/SettingsLib/Spa/build.gradle
+++ b/packages/SettingsLib/Spa/build.gradle
@@ -24,7 +24,7 @@ buildscript {
}
}
plugins {
- id 'com.android.application' version '7.3.1' apply false
- id 'com.android.library' version '7.3.1' apply false
+ id 'com.android.application' version '8.0.0-beta01' apply false
+ id 'com.android.library' version '8.0.0-beta01' apply false
id 'org.jetbrains.kotlin.android' version '1.8.0' apply false
}
diff --git a/packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties b/packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties
index bd7e7ff38205..53b24b0e5d75 100644
--- a/packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties
+++ b/packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties
@@ -16,7 +16,7 @@
#Thu Jul 14 10:36:06 CST 2022
distributionBase=GRADLE_USER_HOME
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-rc-1-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
diff --git a/packages/SettingsLib/Spa/spa/build.gradle b/packages/SettingsLib/Spa/spa/build.gradle
index 640aa01f307f..4563b7d75b22 100644
--- a/packages/SettingsLib/Spa/spa/build.gradle
+++ b/packages/SettingsLib/Spa/spa/build.gradle
@@ -48,11 +48,11 @@ android {
}
}
compileOptions {
- sourceCompatibility JavaVersion.VERSION_11
- targetCompatibility JavaVersion.VERSION_11
+ sourceCompatibility JavaVersion.VERSION_17
+ targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
- jvmTarget = '11'
+ jvmTarget = '17'
freeCompilerArgs = ["-Xjvm-default=all"]
}
buildFeatures {
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPage.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPage.kt
index 724588f794b4..3fdb1d14e667 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPage.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SettingsPage.kt
@@ -77,9 +77,8 @@ data class SettingsPage(
return true
}
- fun isEnabled(): Boolean {
- return getPageProvider(sppName)?.isEnabled(arguments) ?: false
- }
+ fun isEnabled(): Boolean =
+ SpaEnvironment.IS_DEBUG || getPageProvider(sppName)?.isEnabled(arguments) ?: false
fun getTitle(): String {
return getPageProvider(sppName)?.getTitle(arguments) ?: ""
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SpaEnvironment.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SpaEnvironment.kt
index 02962a5815a2..2d956d5eddb2 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SpaEnvironment.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/common/SpaEnvironment.kt
@@ -88,4 +88,13 @@ abstract class SpaEnvironment(context: Context) {
open val sliceProviderAuthorities: String? = null
// TODO: add other environment setup here.
+ companion object {
+ /**
+ * Whether debug mode is on or off.
+ *
+ * If set to true, this will also enable all the pages under development (allows browsing
+ * and searching).
+ */
+ const val IS_DEBUG = false
+ }
}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/button/ActionButtons.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/button/ActionButtons.kt
index 5e6c61423c24..0552c408a8eb 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/button/ActionButtons.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/button/ActionButtons.kt
@@ -24,7 +24,6 @@ import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
-import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
@@ -46,6 +45,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.android.settingslib.spa.framework.theme.SettingsDimension
@@ -100,11 +100,16 @@ private fun RowScope.ActionButton(actionButton: ActionButton) {
contentDescription = null,
modifier = Modifier.size(SettingsDimension.itemIconSize),
)
- Spacer(Modifier.height(4.dp))
- Text(
- text = actionButton.text,
- style = MaterialTheme.typography.labelMedium,
- )
+ Box(
+ modifier = Modifier.padding(top = 4.dp).fillMaxHeight(),
+ contentAlignment = Alignment.Center,
+ ) {
+ Text(
+ text = actionButton.text,
+ textAlign = TextAlign.Center,
+ style = MaterialTheme.typography.labelMedium,
+ )
+ }
}
}
}
diff --git a/packages/SettingsLib/Spa/testutils/build.gradle b/packages/SettingsLib/Spa/testutils/build.gradle
index 536829e00b65..e7f7db2f1ec0 100644
--- a/packages/SettingsLib/Spa/testutils/build.gradle
+++ b/packages/SettingsLib/Spa/testutils/build.gradle
@@ -38,11 +38,11 @@ android {
}
}
compileOptions {
- sourceCompatibility JavaVersion.VERSION_11
- targetCompatibility JavaVersion.VERSION_11
+ sourceCompatibility JavaVersion.VERSION_17
+ targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
- jvmTarget = '11'
+ jvmTarget = '17'
freeCompilerArgs = ["-Xjvm-default=all"]
}
buildFeatures {
diff --git a/packages/SettingsLib/SpaPrivileged/AndroidManifest.xml b/packages/SettingsLib/SpaPrivileged/AndroidManifest.xml
index d1dceb309b99..5396de0ed70b 100644
--- a/packages/SettingsLib/SpaPrivileged/AndroidManifest.xml
+++ b/packages/SettingsLib/SpaPrivileged/AndroidManifest.xml
@@ -17,6 +17,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.settingslib.spaprivileged">
-<uses-permission android:name="android.permission.MANAGE_USERS" />
+ <uses-permission android:name="android.permission.MANAGE_USERS" />
+ <uses-permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS" />
</manifest>
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppOpsController.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppOpsController.kt
index 171903f5c648..c6090042895e 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppOpsController.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppOpsController.kt
@@ -16,11 +16,14 @@
package com.android.settingslib.spaprivileged.model.app
+import android.app.AppOpsManager;
import android.app.AppOpsManager.MODE_ALLOWED
import android.app.AppOpsManager.MODE_ERRORED
import android.app.AppOpsManager.Mode
import android.content.Context
import android.content.pm.ApplicationInfo
+import android.content.pm.PackageManager
+import android.os.UserHandle
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.map
@@ -44,17 +47,25 @@ class AppOpsController(
private val setModeByUid: Boolean = false,
) : IAppOpsController {
private val appOpsManager = context.appOpsManager
+ private val packageManager = context.packageManager
override val mode: LiveData<Int>
get() = _mode
override fun setAllowed(allowed: Boolean) {
val mode = if (allowed) MODE_ALLOWED else modeForNotAllowed
+
if (setModeByUid) {
appOpsManager.setUidMode(op, app.uid, mode)
} else {
appOpsManager.setMode(op, app.uid, app.packageName, mode)
}
+
+ val permission = AppOpsManager.opToPermission(op)
+ packageManager.updatePermissionFlags(permission, app.packageName,
+ PackageManager.FLAG_PERMISSION_USER_SET, PackageManager.FLAG_PERMISSION_USER_SET,
+ UserHandle.getUserHandleForUid(app.uid))
+
_mode.postValue(mode)
}
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppRepository.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppRepository.kt
index 18b207337ad4..1a7d8968f232 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppRepository.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppRepository.kt
@@ -19,7 +19,6 @@ package com.android.settingslib.spaprivileged.model.app
import android.content.Context
import android.content.pm.ApplicationInfo
import android.graphics.drawable.Drawable
-import android.os.UserManager
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.produceState
@@ -28,6 +27,7 @@ import androidx.compose.ui.res.stringResource
import com.android.settingslib.Utils
import com.android.settingslib.spa.framework.compose.rememberContext
import com.android.settingslib.spaprivileged.R
+import com.android.settingslib.spaprivileged.framework.common.userManager
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@@ -42,23 +42,25 @@ interface AppRepository {
val context = LocalContext.current
return produceState(initialValue = stringResource(R.string.summary_placeholder), app) {
withContext(Dispatchers.IO) {
- if (isClonedAppPage || isCloneApp(context, app)) {
- value = context.getString(R.string.cloned_app_info_label, loadLabel(app))
+ value = if (isClonedAppPage || isCloneApp(context, app)) {
+ context.getString(R.string.cloned_app_info_label, loadLabel(app))
} else {
- value = loadLabel(app)
+ loadLabel(app)
}
}
}
}
private fun isCloneApp(context: Context, app: ApplicationInfo): Boolean {
- val userManager = context.getSystemService(UserManager::class.java)!!
- val userInfo = userManager.getUserInfo(app.userId)
+ val userInfo = context.userManager.getUserInfo(app.userId)
return userInfo != null && userInfo.isCloneProfile
}
@Composable
fun produceIcon(app: ApplicationInfo): State<Drawable?>
+
+ @Composable
+ fun produceIconContentDescription(app: ApplicationInfo): State<String?>
}
internal class AppRepositoryImpl(private val context: Context) : AppRepository {
@@ -69,8 +71,22 @@ internal class AppRepositoryImpl(private val context: Context) : AppRepository {
@Composable
override fun produceIcon(app: ApplicationInfo) =
produceState<Drawable?>(initialValue = null, app) {
- withContext(Dispatchers.Default) {
+ withContext(Dispatchers.IO) {
value = Utils.getBadgedIcon(context, app)
}
}
+
+ @Composable
+ override fun produceIconContentDescription(app: ApplicationInfo) =
+ produceState<String?>(initialValue = null, app) {
+ withContext(Dispatchers.IO) {
+ value = when {
+ context.userManager.isManagedProfile(app.userId) -> {
+ context.getString(R.string.category_work)
+ }
+
+ else -> null
+ }
+ }
+ }
}
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt
index 602df54ed3fb..e3ea2e78756f 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt
@@ -32,6 +32,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.android.settingslib.spa.framework.compose.rememberDrawablePainter
@@ -50,7 +51,8 @@ class AppInfoProvider(private val packageInfo: PackageInfo) {
.padding(
horizontal = SettingsDimension.itemPaddingStart,
vertical = SettingsDimension.itemPaddingVertical,
- ),
+ )
+ .semantics(mergeDescendants = true) {},
horizontalAlignment = Alignment.CenterHorizontally,
) {
val app = packageInfo.applicationInfo
@@ -93,8 +95,8 @@ internal fun AppIcon(app: ApplicationInfo, size: Dp) {
val appRepository = rememberAppRepository()
Image(
painter = rememberDrawablePainter(appRepository.produceIcon(app).value),
- contentDescription = null,
- modifier = Modifier.size(size)
+ contentDescription = appRepository.produceIconContentDescription(app).value,
+ modifier = Modifier.size(size),
)
}
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListViewModelTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListViewModelTest.kt
index fc40aed43c92..4f0cddef078b 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListViewModelTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListViewModelTest.kt
@@ -103,6 +103,9 @@ class AppListViewModelTest {
@Composable
override fun produceIcon(app: ApplicationInfo) = stateOf(null)
+
+ @Composable
+ override fun produceIconContentDescription(app: ApplicationInfo) = stateOf(null)
}
private companion object {
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppOpsControllerTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppOpsControllerTest.kt
index fd2ceb7e34f2..23270c147d85 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppOpsControllerTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppOpsControllerTest.kt
@@ -22,6 +22,7 @@ import android.app.AppOpsManager.MODE_ERRORED
import android.app.AppOpsManager.MODE_IGNORED
import android.content.Context
import android.content.pm.ApplicationInfo
+import android.content.pm.PackageManager
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settingslib.spaprivileged.framework.common.appOpsManager
@@ -31,6 +32,10 @@ import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
+import org.mockito.Mockito.any
+import org.mockito.Mockito.anyInt
+import org.mockito.Mockito.anyString
+import org.mockito.Mockito.doNothing
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when` as whenever
import org.mockito.Spy
@@ -45,9 +50,13 @@ class AppOpsControllerTest {
@Mock private lateinit var appOpsManager: AppOpsManager
+ @Mock private lateinit var packageManager: PackageManager
+
@Before
fun setUp() {
whenever(context.appOpsManager).thenReturn(appOpsManager)
+ doNothing().`when`(packageManager)
+ .updatePermissionFlags(anyString(), anyString(), anyInt(), anyInt(), any())
}
@Test
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppRepositoryTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppRepositoryTest.kt
new file mode 100644
index 000000000000..26caa01192c5
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppRepositoryTest.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2023 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.settingslib.spaprivileged.model.app
+
+import android.content.Context
+import android.content.pm.ApplicationInfo
+import android.os.UserManager
+import androidx.compose.runtime.State
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settingslib.spa.framework.compose.stateOf
+import com.android.settingslib.spa.testutils.delay
+import com.android.settingslib.spaprivileged.R
+import com.android.settingslib.spaprivileged.framework.common.userManager
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Spy
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+import org.mockito.Mockito.`when` as whenever
+
+@RunWith(AndroidJUnit4::class)
+class AppRepositoryTest {
+ @get:Rule
+ val composeTestRule = createComposeRule()
+
+ @get:Rule
+ val mockito: MockitoRule = MockitoJUnit.rule()
+
+ @Spy
+ private val context: Context = ApplicationProvider.getApplicationContext()
+
+ @Mock
+ private lateinit var userManager: UserManager
+
+ private lateinit var appRepository: AppRepositoryImpl
+
+ @Before
+ fun setUp() {
+ whenever(context.userManager).thenReturn(userManager)
+ appRepository = AppRepositoryImpl(context)
+ }
+
+ @Test
+ fun produceIconContentDescription_workProfile() {
+ whenever(userManager.isManagedProfile(APP.userId)).thenReturn(true)
+
+ val contentDescription = produceIconContentDescription()
+
+ assertThat(contentDescription.value).isEqualTo(context.getString(R.string.category_work))
+ }
+
+ @Test
+ fun produceIconContentDescription_personalProfile() {
+ whenever(userManager.isManagedProfile(APP.userId)).thenReturn(false)
+
+ val contentDescription = produceIconContentDescription()
+
+ assertThat(contentDescription.value).isNull()
+ }
+
+ private fun produceIconContentDescription(): State<String?> {
+ var contentDescription: State<String?> = stateOf(null)
+ composeTestRule.setContent {
+ contentDescription = appRepository.produceIconContentDescription(APP)
+ }
+ composeTestRule.delay()
+ return contentDescription
+ }
+
+ private companion object {
+ const val UID = 123
+ val APP = ApplicationInfo().apply {
+ uid = UID
+ }
+ }
+} \ No newline at end of file
diff --git a/packages/SettingsLib/res/drawable-mcc310-mnc012/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc310-mnc012/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc310-mnc012/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc310-mnc590/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc310-mnc590/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc310-mnc590/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc310-mnc591/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc310-mnc591/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc310-mnc591/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc310-mnc592/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc310-mnc592/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc310-mnc592/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc310-mnc593/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc310-mnc593/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc310-mnc593/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc310-mnc594/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc310-mnc594/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc310-mnc594/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc310-mnc595/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc310-mnc595/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc310-mnc595/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc310-mnc596/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc310-mnc596/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc310-mnc596/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc310-mnc597/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc310-mnc597/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc310-mnc597/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc310-mnc598/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc310-mnc598/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc310-mnc598/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc310-mnc599/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc310-mnc599/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc310-mnc599/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc310-mnc890/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc310-mnc890/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc310-mnc890/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc270/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc270/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc311-mnc270/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc280/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc280/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc311-mnc280/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc281/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc281/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc311-mnc281/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc282/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc282/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc311-mnc282/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc283/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc283/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc311-mnc283/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc284/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc284/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc311-mnc284/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc285/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc285/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc311-mnc285/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc286/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc286/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc311-mnc286/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc287/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc287/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc311-mnc287/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc288/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc288/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc311-mnc288/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc289/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc289/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc311-mnc289/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc480/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc480/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc311-mnc480/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc481/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc481/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc311-mnc481/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc482/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc482/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc311-mnc482/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc483/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc483/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc311-mnc483/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc484/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc484/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc311-mnc484/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc485/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc485/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc311-mnc485/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc486/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc486/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc311-mnc486/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc487/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc487/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc311-mnc487/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc488/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc488/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc311-mnc488/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable-mcc311-mnc489/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable-mcc311-mnc489/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..c1103fe4cf2e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mcc311-mnc489/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,35 @@
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/values-af/arrays.xml b/packages/SettingsLib/res/values-af/arrays.xml
index 006c9c1baacf..28f7c50a732a 100644
--- a/packages/SettingsLib/res/values-af/arrays.xml
+++ b/packages/SettingsLib/res/values-af/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Het gefiltreer geaktiveer"</item>
<item msgid="2779123106632690576">"Geaktiveer"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (verstek)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 31f50e8fac58..3de581ea3940 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -522,7 +522,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Wekkers en onthounotas"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Laat toe dat wekkers en onthounotas gestel word"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Wekkers en onthounotas"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Laat hierdie program toe om wekkers te stel en tydsensitiewe handelinge te skeduleer. Dit laat die program op die agtergrond werk, wat meer batterykrag kan gebruik.\n\nAs hierdie toestemming af is, sal bestaande wekkers en tydgegronde geleenthede wat deur hierdie program geskeduleer is, nie werk nie."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Laat hierdie app toe om wekkers te stel en tydsensitiewe handelinge te skeduleer. Dit laat die app op die agtergrond werk, wat meer batterykrag kan gebruik.\n\nAs hierdie toestemming af is, sal bestaande wekkers en tydgegronde geleenthede wat deur hierdie app geskeduleer is, nie werk nie."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"skedule, wekker, onthounota, horlosie"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Skakel aan"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Skakel Moenie steur nie aan"</string>
diff --git a/packages/SettingsLib/res/values-am/arrays.xml b/packages/SettingsLib/res/values-am/arrays.xml
index 43c89b13e0e6..c423d3c86ed1 100644
--- a/packages/SettingsLib/res/values-am/arrays.xml
+++ b/packages/SettingsLib/res/values-am/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"ማጣሪያን አንቃ"</item>
<item msgid="2779123106632690576">"ነቅቷል"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (ነባሪ)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ar/arrays.xml b/packages/SettingsLib/res/values-ar/arrays.xml
index 1a16f5ad8393..cf46a8fdcc7d 100644
--- a/packages/SettingsLib/res/values-ar/arrays.xml
+++ b/packages/SettingsLib/res/values-ar/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"تمّ تفعيل التصفية"</item>
<item msgid="2779123106632690576">"مفعّل"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"‏AVRCP 1.5 (تلقائي)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-as/arrays.xml b/packages/SettingsLib/res/values-as/arrays.xml
index 456fa3d60934..284ca122edef 100644
--- a/packages/SettingsLib/res/values-as/arrays.xml
+++ b/packages/SettingsLib/res/values-as/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"সক্ষম কৰাবিলাক ফিল্টাৰ কৰা হৈছে"</item>
<item msgid="2779123106632690576">"সক্ষম কৰা আছে"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (ডিফ’ল্ট)"</item>
<item msgid="1637054408779685086">"AVRCP ১.৩"</item>
diff --git a/packages/SettingsLib/res/values-az/arrays.xml b/packages/SettingsLib/res/values-az/arrays.xml
index dacaacaf5521..ff0054bfe810 100644
--- a/packages/SettingsLib/res/values-az/arrays.xml
+++ b/packages/SettingsLib/res/values-az/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Filtrləmə aktivdir"</item>
<item msgid="2779123106632690576">"Aktivdir"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Defolt)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
index 8e6fae67afac..32071e541bc7 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Omogućeno filtrirano"</item>
<item msgid="2779123106632690576">"Omogućeno"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (podrazumevano)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-be/arrays.xml b/packages/SettingsLib/res/values-be/arrays.xml
index ced9acfd018f..a60d35419cf6 100644
--- a/packages/SettingsLib/res/values-be/arrays.xml
+++ b/packages/SettingsLib/res/values-be/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Уключана з фільтрацыяй"</item>
<item msgid="2779123106632690576">"Уключана"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (стандартная)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-bg/arrays.xml b/packages/SettingsLib/res/values-bg/arrays.xml
index c129304743a9..d778ca275d81 100644
--- a/packages/SettingsLib/res/values-bg/arrays.xml
+++ b/packages/SettingsLib/res/values-bg/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Филтрирането е активирано"</item>
<item msgid="2779123106632690576">"Активирано"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (основно)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-bn/arrays.xml b/packages/SettingsLib/res/values-bn/arrays.xml
index d5837387c12c..dbb738c3d47e 100644
--- a/packages/SettingsLib/res/values-bn/arrays.xml
+++ b/packages/SettingsLib/res/values-bn/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"ফিল্টার করা চালু আছে"</item>
<item msgid="2779123106632690576">"চালু করা আছে"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (ডিফল্ট)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 423309f7ddea..1faee6a03b60 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -540,17 +540,13 @@
<string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"এই ফোন"</string>
<string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"এই ট্যাবলেট"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"এই ফোনটি"</string>
- <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
- <skip />
+ <string name="media_output_status_unknown_error" msgid="5098565887497902222">"এই ডিভাইসে চালানো যাবে না"</string>
<string name="media_output_status_require_premium" msgid="8411255800047014822">"পরিবর্তন করতে অ্যাকাউন্ট আপগ্রেড করুন"</string>
<string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"এখানে ডাউনলোড করা যাবে না"</string>
<string name="media_output_status_try_after_ad" msgid="8312579066856015441">"বিজ্ঞাপনের পরে আবার চেষ্টা করুন"</string>
- <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
- <skip />
- <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
- <skip />
- <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
- <skip />
+ <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"এখানে চালানোর জন্য ডিভাইসকে জাগান"</string>
+ <string name="media_output_status_unauthorized" msgid="5880222828273853838">"চালানোর জন্য ডিভাইসের অনুমতি নেই"</string>
+ <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"এখানে এই মিডিয়া চালানো যাচ্ছে না"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"কানেক্ট করতে সমস্যা হচ্ছে। ডিভাইস বন্ধ করে আবার চালু করুন"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ওয়্যার অডিও ডিভাইস"</string>
<string name="help_label" msgid="3528360748637781274">"সহায়তা ও মতামত"</string>
diff --git a/packages/SettingsLib/res/values-bs/arrays.xml b/packages/SettingsLib/res/values-bs/arrays.xml
index c2e80b675c8c..740e70478fc3 100644
--- a/packages/SettingsLib/res/values-bs/arrays.xml
+++ b/packages/SettingsLib/res/values-bs/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Omogućeno filtrirano"</item>
<item msgid="2779123106632690576">"Omogućeno"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Filtrirana zaglavlja"</item>
- <item msgid="4818549483446395865">"Filtrirani A2DP medijski paketi"</item>
- <item msgid="8207123990453243311">"Filtrirani RFCOMM kanal"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Onemogućeno"</item>
- <item msgid="5884245882825346396">"Čarolija"</item>
- <item msgid="6569400572915342949">"Zaglavlje"</item>
- <item msgid="1239386221416967664">"Potpuni filtar"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (zadano)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index e8cabfaf7ae5..1aa8ff38b2fa 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -522,7 +522,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmi i podsjetnici"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Dozvoli postavljanje alarma i podsjetnika"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmi i podsjetnici"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Dozvolite ovoj aplikaciji da postavlja alarme i zakazuje vremenski osjetljive radnje. Ovim će se omogućiti aplikaciji da radi u pozadini, čime se može povećati potrošnja baterije.\n\nAko je ovo odobrenje isključeno, postojeći alarmi i događaji zasnovani na vremenu koje je ova aplikacija zakazala neće funkcionirati."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Dozvolite ovoj aplikaciji da postavlja alarme i zakazuje vremenski osjetljive radnje. Ovim će se omogućiti aplikaciji da radi u pozadini, čime se može povećati potrošnja baterije.\n\nAko je ovo odobrenje isključeno, postojeći alarmi i događaji zasnovani na vremenu, a koje je ova aplikacija zakazala, neće funkcionirati."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"raspored, alarm, podsjetnik, sat"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Uključi"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Uključi način rada Ne ometaj"</string>
diff --git a/packages/SettingsLib/res/values-ca/arrays.xml b/packages/SettingsLib/res/values-ca/arrays.xml
index 20a3d03eeeea..4e437ba2d4fe 100644
--- a/packages/SettingsLib/res/values-ca/arrays.xml
+++ b/packages/SettingsLib/res/values-ca/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Activat amb filtres"</item>
<item msgid="2779123106632690576">"Activat"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (predeterminada)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 83b32d4d492e..f14befdcd123 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -522,7 +522,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmes i recordatoris"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permet la configuració d\'alarmes i recordatoris"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes i recordatoris"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permet que aquesta aplicació configuri alarmes i programi accions. Això permet a l\'aplicació executar-se en segon pla i, per tant, és possible que consumeixi més bateria.\n\nSi aquest permís està desactivat, les alarmes i els esdeveniments que ja hagi programat l\'aplicació no funcionaran."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permet que aquesta aplicació configuri alarmes i programi accions a una hora determinada. Això permet a l\'aplicació executar-se en segon pla i, per tant, és possible que consumeixi més bateria.\n\nSi aquest permís està desactivat, les alarmes i els esdeveniments que ja hagi programat l\'aplicació no funcionaran."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programació, alarma, recordatori, rellotge"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activa"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activa el mode No molestis"</string>
diff --git a/packages/SettingsLib/res/values-cs/arrays.xml b/packages/SettingsLib/res/values-cs/arrays.xml
index ad6062c4d1c0..e1a5aefc34b5 100644
--- a/packages/SettingsLib/res/values-cs/arrays.xml
+++ b/packages/SettingsLib/res/values-cs/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Povolit filtrované"</item>
<item msgid="2779123106632690576">"Zapnuto"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (výchozí)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-da/arrays.xml b/packages/SettingsLib/res/values-da/arrays.xml
index 6fc471404a13..03cab2062bd5 100644
--- a/packages/SettingsLib/res/values-da/arrays.xml
+++ b/packages/SettingsLib/res/values-da/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Filtreret er aktiveret"</item>
<item msgid="2779123106632690576">"Aktiveret"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (standard)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-de/arrays.xml b/packages/SettingsLib/res/values-de/arrays.xml
index 636a7a4587d3..c5dcc10b0ccb 100644
--- a/packages/SettingsLib/res/values-de/arrays.xml
+++ b/packages/SettingsLib/res/values-de/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Filter aktiviert"</item>
<item msgid="2779123106632690576">"Aktiviert"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Standard)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-el/arrays.xml b/packages/SettingsLib/res/values-el/arrays.xml
index 986adf58d59a..6486b3d113c2 100644
--- a/packages/SettingsLib/res/values-el/arrays.xml
+++ b/packages/SettingsLib/res/values-el/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Ενεργοποιήθηκε το φιλτράρισμα"</item>
<item msgid="2779123106632690576">"Ενεργοποιήθηκε"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Προεπιλογή)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-en-rAU/arrays.xml b/packages/SettingsLib/res/values-en-rAU/arrays.xml
index de633860626c..9a7390e5882e 100644
--- a/packages/SettingsLib/res/values-en-rAU/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rAU/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Enabled Filtered"</item>
<item msgid="2779123106632690576">"Enabled"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Headers filtered"</item>
- <item msgid="4818549483446395865">"A2DP media packets filtered"</item>
- <item msgid="8207123990453243311">"RFCOMM channel filtered"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Disabled"</item>
- <item msgid="5884245882825346396">"Magic"</item>
- <item msgid="6569400572915342949">"Header"</item>
- <item msgid="1239386221416967664">"Full filter"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-en-rCA/arrays.xml b/packages/SettingsLib/res/values-en-rCA/arrays.xml
index 0af8b4efc216..184d21005cc1 100644
--- a/packages/SettingsLib/res/values-en-rCA/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rCA/arrays.xml
@@ -64,15 +64,15 @@
<item msgid="2779123106632690576">"Enabled"</item>
</string-array>
<string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Headers Filtered"</item>
- <item msgid="4818549483446395865">"A2DP Media Packets Filtered"</item>
- <item msgid="8207123990453243311">"RFCOMM Channel Filtered"</item>
+ <item msgid="195768089203590086">"Leave only ACL headers"</item>
+ <item msgid="2776218217644557831">"Filter A2DP media packets"</item>
+ <item msgid="8163235976612675092">"Filter RFCOMM channel"</item>
</string-array>
<string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Disabled"</item>
- <item msgid="5884245882825346396">"Magic"</item>
- <item msgid="6569400572915342949">"Header"</item>
- <item msgid="1239386221416967664">"Full Filter"</item>
+ <item msgid="3961868665260627524">"Disable"</item>
+ <item msgid="2505973306504851132">"Fill with string of characters"</item>
+ <item msgid="5883011000629613855">"Leave only header"</item>
+ <item msgid="1051534112762023603">"Fully remove"</item>
</string-array>
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item>
diff --git a/packages/SettingsLib/res/values-en-rGB/arrays.xml b/packages/SettingsLib/res/values-en-rGB/arrays.xml
index de633860626c..9a7390e5882e 100644
--- a/packages/SettingsLib/res/values-en-rGB/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rGB/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Enabled Filtered"</item>
<item msgid="2779123106632690576">"Enabled"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Headers filtered"</item>
- <item msgid="4818549483446395865">"A2DP media packets filtered"</item>
- <item msgid="8207123990453243311">"RFCOMM channel filtered"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Disabled"</item>
- <item msgid="5884245882825346396">"Magic"</item>
- <item msgid="6569400572915342949">"Header"</item>
- <item msgid="1239386221416967664">"Full filter"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-en-rIN/arrays.xml b/packages/SettingsLib/res/values-en-rIN/arrays.xml
index de633860626c..9a7390e5882e 100644
--- a/packages/SettingsLib/res/values-en-rIN/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rIN/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Enabled Filtered"</item>
<item msgid="2779123106632690576">"Enabled"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Headers filtered"</item>
- <item msgid="4818549483446395865">"A2DP media packets filtered"</item>
- <item msgid="8207123990453243311">"RFCOMM channel filtered"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Disabled"</item>
- <item msgid="5884245882825346396">"Magic"</item>
- <item msgid="6569400572915342949">"Header"</item>
- <item msgid="1239386221416967664">"Full filter"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-en-rXC/arrays.xml b/packages/SettingsLib/res/values-en-rXC/arrays.xml
index 30c9a4968997..dec70f456d1e 100644
--- a/packages/SettingsLib/res/values-en-rXC/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rXC/arrays.xml
@@ -64,15 +64,15 @@
<item msgid="2779123106632690576">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‏‎‏‎‎‏‎‎‎‏‎‏‏‎‏‏‎‏‏‎‏‏‏‏‎‏‏‎‏‏‎‏‎‏‏‏‏‎‏‎‏‏‏‏‏‎‏‎‏‏‏‎‎‏‎‎‎‎‎Enabled‎‏‎‎‏‎"</item>
</string-array>
<string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‏‏‏‎‎‎‎‎‏‏‏‎‏‏‎‏‏‎‏‎‏‎‏‎‎‎‏‎‏‏‏‎‏‏‎‎‎‏‏‎‏‎‏‎‎‏‏‎‎‏‎‏‎‏‎‏‎‎‏‎Headers Filtered‎‏‎‎‏‎"</item>
- <item msgid="4818549483446395865">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‎‏‎‏‏‎‏‏‏‏‎‏‏‏‎‏‏‎‏‎‎‏‏‏‎‎‏‏‎‏‏‎‏‎‏‎‏‏‏‎‏‏‎‏‏‏‎‎‎‏‏‏‏‎‏‏‎‎‏‎A2DP Media Packets Filtered‎‏‎‎‏‎"</item>
- <item msgid="8207123990453243311">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‎‎‏‎‏‏‎‎‎‏‏‏‏‏‏‎‎‏‎‎‏‎‎‏‏‏‏‏‎‏‎‎‎‏‏‎‏‎‏‎‎‏‏‎‏‏‎‏‎‏‏‏‏‎RFCOMM Channel Filtered‎‏‎‎‏‎"</item>
+ <item msgid="195768089203590086">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‎‏‎‏‏‎‏‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‎‏‎‎‎‏‏‎‏‏‏‎‏‎‏‎‏‏‎‎‏‎‎‎‎‏‏‏‏‎‎‎‏‏‎‎Leave only ACL headers‎‏‎‎‏‎"</item>
+ <item msgid="2776218217644557831">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‏‎‏‎‎‎‎‏‏‏‎‎‎‏‏‎‏‏‏‏‎‎‎‎‏‎‏‎‎‎‏‎‎‏‏‎‏‎‏‏‎‎‎‎‎‎‎‏‏‎‎‎‎‎‎‏‏‏‎Filter A2DP media packets‎‏‎‎‏‎"</item>
+ <item msgid="8163235976612675092">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‏‎‎‏‏‎‏‎‎‎‏‏‏‏‎‏‏‏‏‎‏‎‏‏‏‎‏‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‎‎Filter RFCOMM channel‎‏‎‎‏‎"</item>
</string-array>
<string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‏‎‎‏‎‎‎‎‏‎‎‎‎‏‎‏‎‏‏‎‎‏‎‎‏‏‎‏‎‎‏‏‎‎‎‎‏‏‎‎‏‎‏‏‏‎‏‏‎‎‏‏‎Disabled‎‏‎‎‏‎"</item>
- <item msgid="5884245882825346396">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‏‎‏‎‎‏‎‎‎‎‏‎‏‎‎‏‏‏‎‏‎‎‎‏‎‏‎‎‎‎‏‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‎‏‏‏‎‎‎Magic‎‏‎‎‏‎"</item>
- <item msgid="6569400572915342949">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‏‎‏‎‏‏‎‎‏‏‎‎‏‏‎‎‎‎‎‎‏‏‏‏‎‎‏‏‏‏‏‏‎‏‏‏‎‏‏‏‎‏‏‏‏‎‎‏‏‎‎‏‎‏‎Header‎‏‎‎‏‎"</item>
- <item msgid="1239386221416967664">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‎‏‎‎‏‏‎‎‏‏‎‎‏‎‏‏‏‏‎‎‏‏‎‎‏‏‏‎‏‎‏‎‏‏‎‎‎‏‎‎‏‎‎‏‏‎‏‏‎‏‏‏‏‏‎‎‎‎‎Full Filter‎‏‎‎‏‎"</item>
+ <item msgid="3961868665260627524">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‏‎‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‎‏‎‎‎‏‏‏‏‎‏‏‎‎‏‏‏‏‎‎‏‏‏‎‎‎‏‎‏‎‏‏‎‎‏‎‎‎‏‎‎‎Disable‎‏‎‎‏‎"</item>
+ <item msgid="2505973306504851132">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‏‎‏‏‎‎‎‏‏‏‎‎‎‎‎‎‎‏‎‏‏‏‎‎‎‏‏‏‏‎‏‏‏‎‏‏‎‏‎‏‎‏‎‎‏‎‏‏‏‎‏‎‏‏‏‏‎‎‎Fill with string of characters‎‏‎‎‏‎"</item>
+ <item msgid="5883011000629613855">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‏‎‎‏‎‎‏‎‏‎‎‏‏‏‎‏‎‏‎‏‎‏‏‏‏‎‎‏‏‎‎‎‏‏‏‏‏‎‎‏‎‏‎‏‎‏‎‎‎‏‏‏‏‏‎Leave only header‎‏‎‎‏‎"</item>
+ <item msgid="1051534112762023603">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‏‏‎‏‎‎‏‎‏‏‏‏‏‎‎‏‏‎‎‏‎‏‏‎‏‎‎‎‏‎‎‏‏‎‎‎‏‏‎‎‎‏‎‏‏‎‎‏‏‏‎‏‎‏‏‎‎‏‏‎Fully remove‎‏‎‎‏‎"</item>
</string-array>
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‏‎‎‏‎‏‏‎‏‏‎‎‏‎‏‎‎‎‎‏‏‏‎‏‏‎‏‏‎‎‎‏‎‎‎‎‎‏‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎AVRCP 1.5 (Default)‎‏‎‎‏‎"</item>
diff --git a/packages/SettingsLib/res/values-es-rUS/arrays.xml b/packages/SettingsLib/res/values-es-rUS/arrays.xml
index e272cd5fb42d..771690dc8309 100644
--- a/packages/SettingsLib/res/values-es-rUS/arrays.xml
+++ b/packages/SettingsLib/res/values-es-rUS/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Filtrado habilitado"</item>
<item msgid="2779123106632690576">"Habilitado"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (predeterminado)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-es/arrays.xml b/packages/SettingsLib/res/values-es/arrays.xml
index fc28d4ae76e9..e07f9dc372f7 100644
--- a/packages/SettingsLib/res/values-es/arrays.xml
+++ b/packages/SettingsLib/res/values-es/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Habilitado con filtros"</item>
<item msgid="2779123106632690576">"Habilitado"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (predeterminado)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 7c8421f2103b..a7109feee086 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -172,7 +172,7 @@
<string name="unknown" msgid="3544487229740637809">"Desconocido"</string>
<string name="running_process_item_user_label" msgid="3988506293099805796">"Usuario: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="3631650616557252926">"Se han establecido algunos valores predeterminados"</string>
- <string name="launch_defaults_none" msgid="8049374306261262709">"No se han establecido valores predeterminados"</string>
+ <string name="launch_defaults_none" msgid="8049374306261262709">"No hay valores predeterminados"</string>
<string name="tts_settings" msgid="8130616705989351312">"Ajustes de conversión de texto a voz"</string>
<string name="tts_settings_title" msgid="7602210956640483039">"Salida de conversión de texto a voz"</string>
<string name="tts_default_rate_title" msgid="3964187817364304022">"Velocidad de la voz"</string>
diff --git a/packages/SettingsLib/res/values-et/arrays.xml b/packages/SettingsLib/res/values-et/arrays.xml
index 282bfb15027b..34448a72525e 100644
--- a/packages/SettingsLib/res/values-et/arrays.xml
+++ b/packages/SettingsLib/res/values-et/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Luba filtreeritud"</item>
<item msgid="2779123106632690576">"Lubatud"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (vaikeseade)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-eu/arrays.xml b/packages/SettingsLib/res/values-eu/arrays.xml
index 8cd3da8d0731..eb678ffc03e3 100644
--- a/packages/SettingsLib/res/values-eu/arrays.xml
+++ b/packages/SettingsLib/res/values-eu/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Gaituta baina iragazita"</item>
<item msgid="2779123106632690576">"Gaituta"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (lehenetsia)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 82e0eea0167f..02ab1920731d 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -522,7 +522,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmak eta abisuak"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Eman alarmak eta abisuak ezartzeko baimena"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmak eta abisuak"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Eman alarmak ezartzeko eta denbora-muga duten ekintzak programatzeko baimena aplikazioari. Hala, aplikazioak atzeko planoan funtzionatuko du, eta litekeena da bateria gehiago kontsumitzea.\n\nEz baduzu ematen baimen hori, ez dute funtzionatuko aplikazio honen bidez programatutako alarmek eta denbora-muga duten ekintzek."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Eman alarmak ezartzeko eta denbora-muga duten ekintzak programatzeko baimena aplikazioari. Hala, aplikazioak atzeko planoan funtzionatuko du, eta litekeena da bateria gehiago kontsumitzea.\n\nBaimen hori ematen ez baduzu, ez dute funtzionatuko aplikazio honen bidez programatutako alarmek eta denbora-muga duten ekintzek."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programazioa, alarma, abisua, erlojua"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aktibatu"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Aktibatu ez molestatzeko modua"</string>
diff --git a/packages/SettingsLib/res/values-fa/arrays.xml b/packages/SettingsLib/res/values-fa/arrays.xml
index 3a7badacb307..2d9be3177a16 100644
--- a/packages/SettingsLib/res/values-fa/arrays.xml
+++ b/packages/SettingsLib/res/values-fa/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"فیلترشده فعال شده است"</item>
<item msgid="2779123106632690576">"فعال"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"‏AVRCP نسخه ۱.۵ (پیش‌فرض)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-fi/arrays.xml b/packages/SettingsLib/res/values-fi/arrays.xml
index 541ae380b453..d6f002f5b539 100644
--- a/packages/SettingsLib/res/values-fi/arrays.xml
+++ b/packages/SettingsLib/res/values-fi/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Suodatus käytössä"</item>
<item msgid="2779123106632690576">"Päällä"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (oletus)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-fr-rCA/arrays.xml b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
index 4bcf9d2bde5b..6657aa121159 100644
--- a/packages/SettingsLib/res/values-fr-rCA/arrays.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Filtres activés"</item>
<item msgid="2779123106632690576">"Activé"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (par défaut)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-fr/arrays.xml b/packages/SettingsLib/res/values-fr/arrays.xml
index b15435435467..869d88ad5599 100644
--- a/packages/SettingsLib/res/values-fr/arrays.xml
+++ b/packages/SettingsLib/res/values-fr/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Activé et filtré"</item>
<item msgid="2779123106632690576">"Activé"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (par défaut)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-gl/arrays.xml b/packages/SettingsLib/res/values-gl/arrays.xml
index 07c4b29e5882..3cd7b4b4c4a0 100644
--- a/packages/SettingsLib/res/values-gl/arrays.xml
+++ b/packages/SettingsLib/res/values-gl/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Está activado o filtrado"</item>
<item msgid="2779123106632690576">"Activada"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (predeterminado)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-gu/arrays.xml b/packages/SettingsLib/res/values-gu/arrays.xml
index 69fe7bb4160f..f559b805af4c 100644
--- a/packages/SettingsLib/res/values-gu/arrays.xml
+++ b/packages/SettingsLib/res/values-gu/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"ફિલ્ટર કરેલ ચાલુ છે"</item>
<item msgid="2779123106632690576">"ચાલુ છે"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (ડિફૉલ્ટ)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-hi/arrays.xml b/packages/SettingsLib/res/values-hi/arrays.xml
index 5ed88a9974d9..be8862096de8 100644
--- a/packages/SettingsLib/res/values-hi/arrays.xml
+++ b/packages/SettingsLib/res/values-hi/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"चालू और फ़िल्टर किया गया"</item>
<item msgid="2779123106632690576">"चालू है"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (डिफ़ॉल्ट)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-hr/arrays.xml b/packages/SettingsLib/res/values-hr/arrays.xml
index 812f8d270d33..5c73ebba1402 100644
--- a/packages/SettingsLib/res/values-hr/arrays.xml
+++ b/packages/SettingsLib/res/values-hr/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Omogućeno filtrirano"</item>
<item msgid="2779123106632690576">"Omogućeno"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Filtrirana zaglavlja"</item>
- <item msgid="4818549483446395865">"Filtrirani A2DP medijski paketi"</item>
- <item msgid="8207123990453243311">"Filtrirani RFCOMM kanal"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Onemogućeno"</item>
- <item msgid="5884245882825346396">"Čarolija"</item>
- <item msgid="6569400572915342949">"Zaglavlje"</item>
- <item msgid="1239386221416967664">"Potpuni filtar"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (zadano)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-hu/arrays.xml b/packages/SettingsLib/res/values-hu/arrays.xml
index 55a2d28a8d5a..500b9fd228f3 100644
--- a/packages/SettingsLib/res/values-hu/arrays.xml
+++ b/packages/SettingsLib/res/values-hu/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Szűrtek engedélyezve"</item>
<item msgid="2779123106632690576">"Engedélyezve"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (alapértelmezett)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-hy/arrays.xml b/packages/SettingsLib/res/values-hy/arrays.xml
index d2c46ac41748..6fd6893b83e6 100644
--- a/packages/SettingsLib/res/values-hy/arrays.xml
+++ b/packages/SettingsLib/res/values-hy/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Միացված է զտիչներով"</item>
<item msgid="2779123106632690576">"Միացված է"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (կանխադրված)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-in/arrays.xml b/packages/SettingsLib/res/values-in/arrays.xml
index 87cede73df9c..8257d0ee983a 100644
--- a/packages/SettingsLib/res/values-in/arrays.xml
+++ b/packages/SettingsLib/res/values-in/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Diaktifkan Difilter"</item>
<item msgid="2779123106632690576">"Diaktifkan"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-is/arrays.xml b/packages/SettingsLib/res/values-is/arrays.xml
index 5c5841cefae6..1b114eeaff93 100644
--- a/packages/SettingsLib/res/values-is/arrays.xml
+++ b/packages/SettingsLib/res/values-is/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Kveikt á síuðu"</item>
<item msgid="2779123106632690576">"Kveikt"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (sjálfgefið)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-it/arrays.xml b/packages/SettingsLib/res/values-it/arrays.xml
index 4cd775a9855e..50eca9304321 100644
--- a/packages/SettingsLib/res/values-it/arrays.xml
+++ b/packages/SettingsLib/res/values-it/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Filtro attivo"</item>
<item msgid="2779123106632690576">"Attiva"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (versione predefinita)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-iw/arrays.xml b/packages/SettingsLib/res/values-iw/arrays.xml
index a09bccb55e0f..02b77516ed3b 100644
--- a/packages/SettingsLib/res/values-iw/arrays.xml
+++ b/packages/SettingsLib/res/values-iw/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"המסננים המופעלים"</item>
<item msgid="2779123106632690576">"מופעל"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"‏AVRCP 1.5 (ברירת המחדל)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ja/arrays.xml b/packages/SettingsLib/res/values-ja/arrays.xml
index 2090266cd46f..869fd9970065 100644
--- a/packages/SettingsLib/res/values-ja/arrays.xml
+++ b/packages/SettingsLib/res/values-ja/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"有効(フィルタ済み)"</item>
<item msgid="2779123106632690576">"有効"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5(デフォルト)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ka/arrays.xml b/packages/SettingsLib/res/values-ka/arrays.xml
index 616633fb5df4..71a283c9a848 100644
--- a/packages/SettingsLib/res/values-ka/arrays.xml
+++ b/packages/SettingsLib/res/values-ka/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"გაფილტრულის ჩართვა"</item>
<item msgid="2779123106632690576">"ჩართულია"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (ნაგულისხმევი)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-kk/arrays.xml b/packages/SettingsLib/res/values-kk/arrays.xml
index 9aa8d85e426a..ab5e10763b7b 100644
--- a/packages/SettingsLib/res/values-kk/arrays.xml
+++ b/packages/SettingsLib/res/values-kk/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Сүзгіленгендері қосулы"</item>
<item msgid="2779123106632690576">"Қосулы"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (әдепкі)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-km/arrays.xml b/packages/SettingsLib/res/values-km/arrays.xml
index c2c1290bc223..bfc983457f5a 100644
--- a/packages/SettingsLib/res/values-km/arrays.xml
+++ b/packages/SettingsLib/res/values-km/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"បានបើក​ការត្រង"</item>
<item msgid="2779123106632690576">"បាន​បើក"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (លំនាំដើម)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-kn/arrays.xml b/packages/SettingsLib/res/values-kn/arrays.xml
index 22bfe22f263c..61e27912dda8 100644
--- a/packages/SettingsLib/res/values-kn/arrays.xml
+++ b/packages/SettingsLib/res/values-kn/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"ಫಿಲ್ಟರ್ ಮಾಡುವುದನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</item>
<item msgid="2779123106632690576">"ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (ಡೀಫಾಲ್ಟ್)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ko/arrays.xml b/packages/SettingsLib/res/values-ko/arrays.xml
index 547eabf488ba..b4a035ae2751 100644
--- a/packages/SettingsLib/res/values-ko/arrays.xml
+++ b/packages/SettingsLib/res/values-ko/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"필터링 사용 설정됨"</item>
<item msgid="2779123106632690576">"사용 설정됨"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5(기본값)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ky/arrays.xml b/packages/SettingsLib/res/values-ky/arrays.xml
index 6e3cd745d487..657e63ea33b5 100644
--- a/packages/SettingsLib/res/values-ky/arrays.xml
+++ b/packages/SettingsLib/res/values-ky/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Чыпкалар иштетилди"</item>
<item msgid="2779123106632690576">"Иштетилди"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Демейки)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-lo/arrays.xml b/packages/SettingsLib/res/values-lo/arrays.xml
index b74aab747e0a..11688d4dfb04 100644
--- a/packages/SettingsLib/res/values-lo/arrays.xml
+++ b/packages/SettingsLib/res/values-lo/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"ເປີດການກັ່ນຕອງແລ້ວ"</item>
<item msgid="2779123106632690576">"ເປີດໃຊ້ແລ້ວ"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (ຄ່າເລີ່ມຕົ້ນ)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-lt/arrays.xml b/packages/SettingsLib/res/values-lt/arrays.xml
index a25078cbb500..6718660be334 100644
--- a/packages/SettingsLib/res/values-lt/arrays.xml
+++ b/packages/SettingsLib/res/values-lt/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Įgalinta filtruota"</item>
<item msgid="2779123106632690576">"Įgalinta"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (numatytoji)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-lv/arrays.xml b/packages/SettingsLib/res/values-lv/arrays.xml
index 908ebf81969d..3e1869abd3de 100644
--- a/packages/SettingsLib/res/values-lv/arrays.xml
+++ b/packages/SettingsLib/res/values-lv/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Iespējot filtrētos"</item>
<item msgid="2779123106632690576">"Iespējots"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (noklusējums)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-mcc310-mnc012/strings.xml b/packages/SettingsLib/res/values-mcc310-mnc012/strings.xml
new file mode 100644
index 000000000000..aa504ef7fd92
--- /dev/null
+++ b/packages/SettingsLib/res/values-mcc310-mnc012/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
+
diff --git a/packages/SettingsLib/res/values-mcc310-mnc590/strings.xml b/packages/SettingsLib/res/values-mcc310-mnc590/strings.xml
new file mode 100644
index 000000000000..4cd04d0ca10b
--- /dev/null
+++ b/packages/SettingsLib/res/values-mcc310-mnc590/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-mcc310-mnc591/strings.xml b/packages/SettingsLib/res/values-mcc310-mnc591/strings.xml
new file mode 100644
index 000000000000..4cd04d0ca10b
--- /dev/null
+++ b/packages/SettingsLib/res/values-mcc310-mnc591/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-mcc310-mnc592/strings.xml b/packages/SettingsLib/res/values-mcc310-mnc592/strings.xml
new file mode 100644
index 000000000000..4cd04d0ca10b
--- /dev/null
+++ b/packages/SettingsLib/res/values-mcc310-mnc592/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-mcc310-mnc593/strings.xml b/packages/SettingsLib/res/values-mcc310-mnc593/strings.xml
new file mode 100644
index 000000000000..4cd04d0ca10b
--- /dev/null
+++ b/packages/SettingsLib/res/values-mcc310-mnc593/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-mcc310-mnc594/strings.xml b/packages/SettingsLib/res/values-mcc310-mnc594/strings.xml
new file mode 100644
index 000000000000..4cd04d0ca10b
--- /dev/null
+++ b/packages/SettingsLib/res/values-mcc310-mnc594/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-mcc310-mnc595/strings.xml b/packages/SettingsLib/res/values-mcc310-mnc595/strings.xml
new file mode 100644
index 000000000000..4cd04d0ca10b
--- /dev/null
+++ b/packages/SettingsLib/res/values-mcc310-mnc595/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-mcc310-mnc596/strings.xml b/packages/SettingsLib/res/values-mcc310-mnc596/strings.xml
new file mode 100644
index 000000000000..4cd04d0ca10b
--- /dev/null
+++ b/packages/SettingsLib/res/values-mcc310-mnc596/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-mcc310-mnc597/strings.xml b/packages/SettingsLib/res/values-mcc310-mnc597/strings.xml
new file mode 100644
index 000000000000..4cd04d0ca10b
--- /dev/null
+++ b/packages/SettingsLib/res/values-mcc310-mnc597/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-mcc310-mnc598/strings.xml b/packages/SettingsLib/res/values-mcc310-mnc598/strings.xml
new file mode 100644
index 000000000000..4cd04d0ca10b
--- /dev/null
+++ b/packages/SettingsLib/res/values-mcc310-mnc598/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-mcc310-mnc599/strings.xml b/packages/SettingsLib/res/values-mcc310-mnc599/strings.xml
new file mode 100644
index 000000000000..4cd04d0ca10b
--- /dev/null
+++ b/packages/SettingsLib/res/values-mcc310-mnc599/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-mcc310-mnc890/strings.xml b/packages/SettingsLib/res/values-mcc310-mnc890/strings.xml
new file mode 100644
index 000000000000..4cd04d0ca10b
--- /dev/null
+++ b/packages/SettingsLib/res/values-mcc310-mnc890/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc270/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc270/strings.xml
new file mode 100644
index 000000000000..4cd04d0ca10b
--- /dev/null
+++ b/packages/SettingsLib/res/values-mcc311-mnc270/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc280/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc280/strings.xml
new file mode 100644
index 000000000000..4cd04d0ca10b
--- /dev/null
+++ b/packages/SettingsLib/res/values-mcc311-mnc280/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc281/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc281/strings.xml
new file mode 100644
index 000000000000..4cd04d0ca10b
--- /dev/null
+++ b/packages/SettingsLib/res/values-mcc311-mnc281/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc282/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc282/strings.xml
new file mode 100644
index 000000000000..4cd04d0ca10b
--- /dev/null
+++ b/packages/SettingsLib/res/values-mcc311-mnc282/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc283/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc283/strings.xml
new file mode 100644
index 000000000000..4cd04d0ca10b
--- /dev/null
+++ b/packages/SettingsLib/res/values-mcc311-mnc283/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc284/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc284/strings.xml
new file mode 100644
index 000000000000..4cd04d0ca10b
--- /dev/null
+++ b/packages/SettingsLib/res/values-mcc311-mnc284/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc285/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc285/strings.xml
new file mode 100644
index 000000000000..4cd04d0ca10b
--- /dev/null
+++ b/packages/SettingsLib/res/values-mcc311-mnc285/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc286/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc286/strings.xml
new file mode 100644
index 000000000000..4cd04d0ca10b
--- /dev/null
+++ b/packages/SettingsLib/res/values-mcc311-mnc286/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc287/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc287/strings.xml
new file mode 100644
index 000000000000..4cd04d0ca10b
--- /dev/null
+++ b/packages/SettingsLib/res/values-mcc311-mnc287/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc288/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc288/strings.xml
new file mode 100644
index 000000000000..4cd04d0ca10b
--- /dev/null
+++ b/packages/SettingsLib/res/values-mcc311-mnc288/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc289/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc289/strings.xml
new file mode 100644
index 000000000000..4cd04d0ca10b
--- /dev/null
+++ b/packages/SettingsLib/res/values-mcc311-mnc289/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc481/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc481/strings.xml
new file mode 100644
index 000000000000..4cd04d0ca10b
--- /dev/null
+++ b/packages/SettingsLib/res/values-mcc311-mnc481/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc482/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc482/strings.xml
new file mode 100644
index 000000000000..4cd04d0ca10b
--- /dev/null
+++ b/packages/SettingsLib/res/values-mcc311-mnc482/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc483/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc483/strings.xml
new file mode 100644
index 000000000000..4cd04d0ca10b
--- /dev/null
+++ b/packages/SettingsLib/res/values-mcc311-mnc483/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc484/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc484/strings.xml
new file mode 100644
index 000000000000..4cd04d0ca10b
--- /dev/null
+++ b/packages/SettingsLib/res/values-mcc311-mnc484/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc485/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc485/strings.xml
new file mode 100644
index 000000000000..4cd04d0ca10b
--- /dev/null
+++ b/packages/SettingsLib/res/values-mcc311-mnc485/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc486/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc486/strings.xml
new file mode 100644
index 000000000000..4cd04d0ca10b
--- /dev/null
+++ b/packages/SettingsLib/res/values-mcc311-mnc486/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc487/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc487/strings.xml
new file mode 100644
index 000000000000..4cd04d0ca10b
--- /dev/null
+++ b/packages/SettingsLib/res/values-mcc311-mnc487/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc488/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc488/strings.xml
new file mode 100644
index 000000000000..4cd04d0ca10b
--- /dev/null
+++ b/packages/SettingsLib/res/values-mcc311-mnc488/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-mcc311-mnc489/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc489/strings.xml
new file mode 100644
index 000000000000..4cd04d0ca10b
--- /dev/null
+++ b/packages/SettingsLib/res/values-mcc311-mnc489/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-mk/arrays.xml b/packages/SettingsLib/res/values-mk/arrays.xml
index 98b3de2c691c..ebf387badec7 100644
--- a/packages/SettingsLib/res/values-mk/arrays.xml
+++ b/packages/SettingsLib/res/values-mk/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Овозможено е филтрирано"</item>
<item msgid="2779123106632690576">"Овозможено"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Стандардна)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ml/arrays.xml b/packages/SettingsLib/res/values-ml/arrays.xml
index 75a5921f514f..30adb57365aa 100644
--- a/packages/SettingsLib/res/values-ml/arrays.xml
+++ b/packages/SettingsLib/res/values-ml/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"ഫിൽട്ടറിംഗ് പ്രവർത്തനക്ഷമമാക്കി"</item>
<item msgid="2779123106632690576">"പ്രവർത്തനക്ഷമമാക്കി"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (ഡിഫോൾട്ട്)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-mn/arrays.xml b/packages/SettingsLib/res/values-mn/arrays.xml
index 2ca88a547219..d03fcd651586 100644
--- a/packages/SettingsLib/res/values-mn/arrays.xml
+++ b/packages/SettingsLib/res/values-mn/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Идэвхжүүлсэн Шүүсэн"</item>
<item msgid="2779123106632690576">"Идэвхжүүлсэн"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Өгөгдмөл)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-mr/arrays.xml b/packages/SettingsLib/res/values-mr/arrays.xml
index eaf4c66a3bdf..68eff756451f 100644
--- a/packages/SettingsLib/res/values-mr/arrays.xml
+++ b/packages/SettingsLib/res/values-mr/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"फिल्टर केलेले सुरू केले"</item>
<item msgid="2779123106632690576">"सुरू केले"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (डीफॉल्ट)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ms/arrays.xml b/packages/SettingsLib/res/values-ms/arrays.xml
index 727f4753df41..efdd879638cb 100644
--- a/packages/SettingsLib/res/values-ms/arrays.xml
+++ b/packages/SettingsLib/res/values-ms/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Didayakan Ditapis"</item>
<item msgid="2779123106632690576">"Didayakan"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Lalai)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-my/arrays.xml b/packages/SettingsLib/res/values-my/arrays.xml
index 768b74988c8d..4d0b792a8532 100644
--- a/packages/SettingsLib/res/values-my/arrays.xml
+++ b/packages/SettingsLib/res/values-my/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"စစ်ထုတ်ထားသည်များကို ဖွင့်ထားသည်"</item>
<item msgid="2779123106632690576">"ဖွင့်ထားသည်"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (မူလ)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-nb/arrays.xml b/packages/SettingsLib/res/values-nb/arrays.xml
index 6f2370d9f72e..9293bdadb02d 100644
--- a/packages/SettingsLib/res/values-nb/arrays.xml
+++ b/packages/SettingsLib/res/values-nb/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Filtrering er slått på"</item>
<item msgid="2779123106632690576">"Slått på"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (standard)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ne/arrays.xml b/packages/SettingsLib/res/values-ne/arrays.xml
index 46edebe3fa8d..29a7c6017510 100644
--- a/packages/SettingsLib/res/values-ne/arrays.xml
+++ b/packages/SettingsLib/res/values-ne/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"फिल्टर सक्षम पारियो"</item>
<item msgid="2779123106632690576">"सक्षम पारिएको छ"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP १.५ (डिफल्ट)"</item>
<item msgid="1637054408779685086">"AVRCP १.३"</item>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index ae7e8b3ec4d3..831ed2f24082 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -520,7 +520,7 @@
<string name="okay" msgid="949938843324579502">"ठिक छ"</string>
<string name="done" msgid="381184316122520313">"सम्पन्न भयो"</string>
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"अलार्म र रिमाइन्डरहरू"</string>
- <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"अलार्म तथा रिमाइन्डर सेट गर्न दिइयोस्"</string>
+ <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"अलार्म तथा रिमाइन्डर सेट गर्ने अनुमति दिनुहोस्"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"अलार्म तथा रिमाइन्डर"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"यो एपलाई अलार्म सेट गर्ने र समयमै पूरा गर्नु पर्ने कारबाहीहरूको रुटिन बनाउने अनुमति दिनुहोस्। यो अनुमति दिइएको छ भने यो एप ब्याकग्राउन्डमा चल्छ र धेरै ब्याट्री खपत हुन्छ।\n\nयो अनुमति दिइएको छैन भने सेट गरिएका अलार्म बज्दैनन् र यो एपले तय गरेका गतिविधि चल्दैनन्।"</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"समयतालिका, अलार्म, रिमाइन्डर, घडी"</string>
diff --git a/packages/SettingsLib/res/values-nl/arrays.xml b/packages/SettingsLib/res/values-nl/arrays.xml
index b839ffe738ac..460302cfb29d 100644
--- a/packages/SettingsLib/res/values-nl/arrays.xml
+++ b/packages/SettingsLib/res/values-nl/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Gefilterd staat aan"</item>
<item msgid="2779123106632690576">"Aangezet"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (standaard)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-or/arrays.xml b/packages/SettingsLib/res/values-or/arrays.xml
index 57da2685fff9..439bd725004b 100644
--- a/packages/SettingsLib/res/values-or/arrays.xml
+++ b/packages/SettingsLib/res/values-or/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"ଫିଲ୍ଟର୍‌କୁ ସକ୍ଷମ କରାଯାଇଛି"</item>
<item msgid="2779123106632690576">"ସକ୍ଷମ କରାଯାଇଛି"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (ଡିଫଲ୍ଟ)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-pa/arrays.xml b/packages/SettingsLib/res/values-pa/arrays.xml
index 083f5aa0fad5..f4bfcd1f1861 100644
--- a/packages/SettingsLib/res/values-pa/arrays.xml
+++ b/packages/SettingsLib/res/values-pa/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"ਫਿਲਟਰ ਕੀਤਿਆਂ ਨੂੰ ਚਾਲੂ ਕੀਤਾ ਗਿਆ"</item>
<item msgid="2779123106632690576">"ਚਾਲੂ"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (ਪੂਰਵ-ਨਿਰਧਾਰਿਤ)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-pl/arrays.xml b/packages/SettingsLib/res/values-pl/arrays.xml
index 87aeb5092ad1..a305a65c16cd 100644
--- a/packages/SettingsLib/res/values-pl/arrays.xml
+++ b/packages/SettingsLib/res/values-pl/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Filtrowanie włączone"</item>
<item msgid="2779123106632690576">"Włączono"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (domyślnie)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 84aa66aa3963..ddff92c78b26 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -522,7 +522,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmy i przypomnienia"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Zezwalaj na ustawianie alarmów i przypomnień"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmy i przypomnienia"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Zezwól na ustawianie alarmów i planowanie innych działań, w przypadku których czas jest istotny. Dzięki temu aplikacja będzie mogła działać w tle, co może zwiększyć wykorzystanie baterii.\n\nJeśli nie włączysz tych uprawnień, istniejące alarmy i zaplanowane wydarzenia z tej aplikacji nie będą działać."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Zezwalaj tej aplikacji na ustawianie alarmów i planowanie działań, w przypadku których czas jest istotny. Aplikacja będzie mogła działać w tle, co może zwiększyć wykorzystanie baterii.\n\nJeśli nie włączysz tego uprawnienia, istniejące alarmy i zaplanowane wydarzenia z tej aplikacji nie będą działać."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"harmonogram, alarm, przypomnienie, zegar"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Włącz"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Włącz tryb Nie przeszkadzać"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/arrays.xml b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
index b64383f6a1c2..eff092216c0a 100644
--- a/packages/SettingsLib/res/values-pt-rBR/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Filtro ativado"</item>
<item msgid="2779123106632690576">"Ativado"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (padrão)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 168207d518df..3a48c3d2b6a5 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -522,7 +522,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmes e lembretes"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Autorizar a definição de alarmes e lembretes"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes e lembretes"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permitir que o app defina alarmes e programe ações mais imediatas. Essa opção autoriza o app a ser executado em segundo plano, o que pode consumir mais bateria.\n\nSe a permissão for desativada, os alarmes e eventos programados pelo app não funcionarão."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permitir que o app defina alarmes e programe ações com hora marcada. Essa opção autoriza o app a ser executado em segundo plano, o que pode consumir mais bateria.\n\nSe a permissão for desativada, os alarmes e eventos programados pelo app não funcionarão."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programar, alarme, lembrete, relógio"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Ativar"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Ativar o Não perturbe"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/arrays.xml b/packages/SettingsLib/res/values-pt-rPT/arrays.xml
index b134be6d9ead..0553aac032e8 100644
--- a/packages/SettingsLib/res/values-pt-rPT/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/arrays.xml
@@ -63,17 +63,13 @@
<item msgid="6336372935919715515">"Filtrado ativado"</item>
<item msgid="2779123106632690576">"Ativado"</item>
</string-array>
- <string-array name="bt_hci_snoop_log_filters_entries">
- <item msgid="5118179698172834473">"Cabeçalhos filtrados"</item>
- <item msgid="4818549483446395865">"Pacotes de multimédia A2DP filtrados"</item>
- <item msgid="8207123990453243311">"Canal RFCOMM filtrado"</item>
- </string-array>
- <string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item msgid="6348114316510677939">"Desativado"</item>
- <item msgid="5884245882825346396">"Magia"</item>
- <item msgid="6569400572915342949">"Cabeçalho"</item>
- <item msgid="1239386221416967664">"Filtro completo"</item>
- </string-array>
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (predefinição)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 91d120409eea..499477e4fbfd 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -141,7 +141,7 @@
<string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Cancelar"</string>
<string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"A sincronização concede acesso aos seus contactos e ao histórico de chamadas quando tem uma ligação estabelecida."</string>
<string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"Não foi possível sincronizar com <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
- <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Não foi possível sincronizar com <xliff:g id="DEVICE_NAME">%1$s</xliff:g> devido a PIN ou chave de acesso incorreto."</string>
+ <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Não foi possível sincronizar com <xliff:g id="DEVICE_NAME">%1$s</xliff:g> devido a PIN ou token de acesso incorreto."</string>
<string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Não é possível comunicar com <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
<string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"Emparelhamento rejeitado por <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
<string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Computador"</string>
@@ -339,7 +339,7 @@
<string name="debug_app" msgid="8903350241392391766">"Selecionar a aplicação a depurar"</string>
<string name="debug_app_not_set" msgid="1934083001283807188">"Nenhuma aplicação a depurar definida"</string>
<string name="debug_app_set" msgid="6599535090477753651">"A depurar aplicação: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="select_application" msgid="2543228890535466325">"Selecionar aplicação"</string>
+ <string name="select_application" msgid="2543228890535466325">"Selecionar app"</string>
<string name="no_application" msgid="9038334538870247690">"Nenhuma"</string>
<string name="wait_for_debugger" msgid="7461199843335409809">"Aguarde pelo depurador"</string>
<string name="wait_for_debugger_summary" msgid="6846330006113363286">"A aplicação depurada aguarda a anexação do depurador antes da execução"</string>
@@ -520,7 +520,7 @@
<string name="okay" msgid="949938843324579502">"OK"</string>
<string name="done" msgid="381184316122520313">"Concluir"</string>
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmes e lembretes"</string>
- <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permitir a definição de alarmes e lembretes"</string>
+ <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permitir alarmes e lembretes"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes e lembretes"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permita que esta app defina alarmes e agende outras ações com base no tempo. Esta ação permite que a app seja executada em segundo plano, o que pode utilizar mais bateria.\n\nSe esta autorização estiver desativada, os alarmes existentes e os eventos com base no tempo agendados por esta app não funcionam."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"agendar, alarme, lembrete, relógio"</string>
diff --git a/packages/SettingsLib/res/values-pt/arrays.xml b/packages/SettingsLib/res/values-pt/arrays.xml
index b64383f6a1c2..eff092216c0a 100644
--- a/packages/SettingsLib/res/values-pt/arrays.xml
+++ b/packages/SettingsLib/res/values-pt/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Filtro ativado"</item>
<item msgid="2779123106632690576">"Ativado"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (padrão)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 168207d518df..3a48c3d2b6a5 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -522,7 +522,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmes e lembretes"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Autorizar a definição de alarmes e lembretes"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes e lembretes"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permitir que o app defina alarmes e programe ações mais imediatas. Essa opção autoriza o app a ser executado em segundo plano, o que pode consumir mais bateria.\n\nSe a permissão for desativada, os alarmes e eventos programados pelo app não funcionarão."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permitir que o app defina alarmes e programe ações com hora marcada. Essa opção autoriza o app a ser executado em segundo plano, o que pode consumir mais bateria.\n\nSe a permissão for desativada, os alarmes e eventos programados pelo app não funcionarão."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programar, alarme, lembrete, relógio"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Ativar"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Ativar o Não perturbe"</string>
diff --git a/packages/SettingsLib/res/values-ro/arrays.xml b/packages/SettingsLib/res/values-ro/arrays.xml
index 8062339cba66..303d669c4eae 100644
--- a/packages/SettingsLib/res/values-ro/arrays.xml
+++ b/packages/SettingsLib/res/values-ro/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Este activat Filtrat"</item>
<item msgid="2779123106632690576">"Activat"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (prestabilit)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index dba7507b090d..e9afb3da12b4 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -522,7 +522,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarme și mementouri"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permite setarea pentru alarme și mementouri"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarme și mementouri"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permite acestei aplicații să stabilească alarme și să planifice acțiuni dependente de timp. Astfel, aplicația poate să ruleze în fundal, fapt care ar putea consuma mai multă baterie.\n\nDacă permisiunea este dezactivată, alarmele și evenimentele dependente de timp planificate de aplicație nu vor funcționa."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permite acestei aplicații să seteze alarme și să planifice acțiuni care trebuie realizate în timp scurt. Astfel, aplicația poate să ruleze în fundal, ceea ce ar putea crește consumul de baterie.\n\nDacă permisiunea este dezactivată, alarmele și evenimentele dependente de timp planificate de aplicație nu vor funcționa."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programare, alarmă, memento, ceas"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activează"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activează Nu deranja"</string>
diff --git a/packages/SettingsLib/res/values-ru/arrays.xml b/packages/SettingsLib/res/values-ru/arrays.xml
index 5f7597d92cf3..4772df984ff5 100644
--- a/packages/SettingsLib/res/values-ru/arrays.xml
+++ b/packages/SettingsLib/res/values-ru/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Включены фильтры"</item>
<item msgid="2779123106632690576">"Включено"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (по умолчанию)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 76d163cea817..16788c3c828c 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -522,7 +522,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Будильники и напоминания"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Разрешить установку будильников и напоминаний"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Будильники и напоминания"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Если вы разрешите этому приложению устанавливать будильники и планировать на определенное время действия, оно будет работать в фоновом режиме. В таком случае заряд батареи может расходоваться быстрее.\n\nЕсли отключить эту настройку, текущие будильники и созданные приложением мероприятия перестанут запускаться."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Вы можете разрешить этому приложению устанавливать будильники и планировать запуск действий в определенное время. В этом случае оно будет работать в фоновом режиме и быстрее расходовать заряд батареи.\n\nЕсли отключить это разрешение, текущие будильники и созданные приложением события перестанут запускаться."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"установить, будильник, напоминание, часы"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Включить"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Включите режим \"Не беспокоить\""</string>
diff --git a/packages/SettingsLib/res/values-si/arrays.xml b/packages/SettingsLib/res/values-si/arrays.xml
index b03b8117de4d..8de6a71d1dd4 100644
--- a/packages/SettingsLib/res/values-si/arrays.xml
+++ b/packages/SettingsLib/res/values-si/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"සබල පෙරහන් කළ"</item>
<item msgid="2779123106632690576">"සබලයි"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (පෙරනිමි)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-sk/arrays.xml b/packages/SettingsLib/res/values-sk/arrays.xml
index 902531c960f9..f15dfb7629d3 100644
--- a/packages/SettingsLib/res/values-sk/arrays.xml
+++ b/packages/SettingsLib/res/values-sk/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Aktivované filtrované"</item>
<item msgid="2779123106632690576">"Aktivované"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (predvolené)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 5e56aba6c0c0..89ef9465b96f 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -522,7 +522,7 @@
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Budíky a pripomenutia"</string>
<string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Povoliť nastavovanie budíkov a pripomenutí"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Budíky a pripomenutia"</string>
- <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Povoľte tejto aplikácii nastavovať budíky a plánovať akcie s časovým obmedzením. Aplikácii to umožní pracovať na pozadí, čo môže zvýšiť spotrebu batérie.\n\nAk je toto povolenie vypnuté, súčasné budíky a udalosti s časovým obmedzením naplánované touto aplikáciu nebudú fungovať."</string>
+ <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Povoľte tejto aplikácii nastavovať budíky a plánovať akcie s časovým obmedzením. Aplikácii to umožní pracovať na pozadí, čo môže zvýšiť spotrebu batérie.\n\nAk je toto povolenie vypnuté, existujúce budíky a udalosti s časovým obmedzením naplánované touto aplikáciu nebudú fungovať."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"plán, budík, pripomenutie, hodiny"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Zapnúť"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Zapnite režim bez vyrušení"</string>
diff --git a/packages/SettingsLib/res/values-sl/arrays.xml b/packages/SettingsLib/res/values-sl/arrays.xml
index ef5bf5338340..9ef852c062c2 100644
--- a/packages/SettingsLib/res/values-sl/arrays.xml
+++ b/packages/SettingsLib/res/values-sl/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Omogočeno filtrirano"</item>
<item msgid="2779123106632690576">"Omogočeno"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (privzeto)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-sq/arrays.xml b/packages/SettingsLib/res/values-sq/arrays.xml
index c31d4fb0ebb0..89a316dcd6e7 100644
--- a/packages/SettingsLib/res/values-sq/arrays.xml
+++ b/packages/SettingsLib/res/values-sq/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Të aktivizuara të filtruara"</item>
<item msgid="2779123106632690576">"Aktiv"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (I parazgjedhur)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-sr/arrays.xml b/packages/SettingsLib/res/values-sr/arrays.xml
index e5a9f501f5e5..e76820e3368e 100644
--- a/packages/SettingsLib/res/values-sr/arrays.xml
+++ b/packages/SettingsLib/res/values-sr/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Омогућено филтрирано"</item>
<item msgid="2779123106632690576">"Омогућено"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (подразумевано)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-sv/arrays.xml b/packages/SettingsLib/res/values-sv/arrays.xml
index 4f4ded1581f2..391f603721c2 100644
--- a/packages/SettingsLib/res/values-sv/arrays.xml
+++ b/packages/SettingsLib/res/values-sv/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Filtrering har aktiverats"</item>
<item msgid="2779123106632690576">"Aktiverad"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (standard)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-sw/arrays.xml b/packages/SettingsLib/res/values-sw/arrays.xml
index aee1cde43fb3..1a33b6e4ce7c 100644
--- a/packages/SettingsLib/res/values-sw/arrays.xml
+++ b/packages/SettingsLib/res/values-sw/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Vichujio Vilivyowekwa"</item>
<item msgid="2779123106632690576">"Imewashwa"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Chaguomsingi)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ta/arrays.xml b/packages/SettingsLib/res/values-ta/arrays.xml
index 9fd1b6e3eab2..23eb2426b49f 100644
--- a/packages/SettingsLib/res/values-ta/arrays.xml
+++ b/packages/SettingsLib/res/values-ta/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"இயக்கப்பட்டு வடிகட்டப்பட்டது"</item>
<item msgid="2779123106632690576">"இயக்கப்பட்டது"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (இயல்பு)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-te/arrays.xml b/packages/SettingsLib/res/values-te/arrays.xml
index c4494f967355..0f62c1d8d842 100644
--- a/packages/SettingsLib/res/values-te/arrays.xml
+++ b/packages/SettingsLib/res/values-te/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"ప్రారంభించబడింది ఫిల్టర్ చేయబడింది"</item>
<item msgid="2779123106632690576">"ప్రారంభించబడింది"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.4 (ఆటోమేటిక్ సెట్టింగ్)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-th/arrays.xml b/packages/SettingsLib/res/values-th/arrays.xml
index 1fb18a0aea31..8d98cdb54fd3 100644
--- a/packages/SettingsLib/res/values-th/arrays.xml
+++ b/packages/SettingsLib/res/values-th/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"เปิดใช้รายการที่กรอง"</item>
<item msgid="2779123106632690576">"เปิดใช้"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (ค่าเริ่มต้น)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-tl/arrays.xml b/packages/SettingsLib/res/values-tl/arrays.xml
index 7b554366fcd0..ed47d3294280 100644
--- a/packages/SettingsLib/res/values-tl/arrays.xml
+++ b/packages/SettingsLib/res/values-tl/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Na-enable Na-filter"</item>
<item msgid="2779123106632690576">"Naka-enable"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-tr/arrays.xml b/packages/SettingsLib/res/values-tr/arrays.xml
index 016b5a908ac4..45580f5b4f2c 100644
--- a/packages/SettingsLib/res/values-tr/arrays.xml
+++ b/packages/SettingsLib/res/values-tr/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Etkin Filtrelenmiş"</item>
<item msgid="2779123106632690576">"Etkin"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Varsayılan)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 86d53e7d586d..1f56170f6294 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -520,7 +520,7 @@
<string name="okay" msgid="949938843324579502">"Tamam"</string>
<string name="done" msgid="381184316122520313">"Bitti"</string>
<string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmlar ve hatırlatıcılar"</string>
- <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Alarm ve hatırlatıcı ayarlanmasına izin ver"</string>
+ <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Alarm ve hatırlatıcı ayarlamasına izin ver"</string>
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmlar ve hatırlatıcılar"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Bu uygulamanın alarm kurmasına ve zamana bağlı işlemler programlamasına izin verin. Bu izin, uygulamanın arka planda çalışmasına olanak sağlayarak daha fazla pil harcanmasına neden olabilir.\n\nBu izin verilmezse bu uygulama tarafından programlanmış mevcut alarmlar ve zamana bağlı etkinlikler çalışmaz."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"program, alarm, hatırlatıcı, saat"</string>
diff --git a/packages/SettingsLib/res/values-uk/arrays.xml b/packages/SettingsLib/res/values-uk/arrays.xml
index ff19fa3861e4..f97452c159c8 100644
--- a/packages/SettingsLib/res/values-uk/arrays.xml
+++ b/packages/SettingsLib/res/values-uk/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Увімкнено з фільтром"</item>
<item msgid="2779123106632690576">"Увімкнено"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (за умовчанням)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ur/arrays.xml b/packages/SettingsLib/res/values-ur/arrays.xml
index 09cd76542af5..74af32215d1b 100644
--- a/packages/SettingsLib/res/values-ur/arrays.xml
+++ b/packages/SettingsLib/res/values-ur/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"فعال کردہ فلٹر کردہ"</item>
<item msgid="2779123106632690576">"فعال"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"‏AVRCP 1.5 (ڈیفالٹ)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-uz/arrays.xml b/packages/SettingsLib/res/values-uz/arrays.xml
index 0893e062624f..3e53ae6abaf0 100644
--- a/packages/SettingsLib/res/values-uz/arrays.xml
+++ b/packages/SettingsLib/res/values-uz/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Filtrlar yoniq"</item>
<item msgid="2779123106632690576">"Yoniq"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (asosiy)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-vi/arrays.xml b/packages/SettingsLib/res/values-vi/arrays.xml
index fd9ac04deb75..649cb5cd7693 100644
--- a/packages/SettingsLib/res/values-vi/arrays.xml
+++ b/packages/SettingsLib/res/values-vi/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Đã bật và lọc"</item>
<item msgid="2779123106632690576">"Đã bật"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (Mặc định)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-zh-rCN/arrays.xml b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
index 1b856c78268b..13941af90c8d 100644
--- a/packages/SettingsLib/res/values-zh-rCN/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"已启用“已过滤”"</item>
<item msgid="2779123106632690576">"已启用"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5(默认)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-zh-rHK/arrays.xml b/packages/SettingsLib/res/values-zh-rHK/arrays.xml
index 6170f4a596a3..9b359ed4ea22 100644
--- a/packages/SettingsLib/res/values-zh-rHK/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"已啟用篩選"</item>
<item msgid="2779123106632690576">"已啟用"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (預設)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-zh-rTW/arrays.xml b/packages/SettingsLib/res/values-zh-rTW/arrays.xml
index 9241798fde04..00362d828b91 100644
--- a/packages/SettingsLib/res/values-zh-rTW/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"已啟用篩選結果"</item>
<item msgid="2779123106632690576">"已啟用"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"AVRCP 1.5 (預設)"</item>
<item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 8bfbd7a5cd00..588c4f4b698e 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -230,7 +230,7 @@
<string name="adb_wireless_error" msgid="721958772149779856">"錯誤"</string>
<string name="adb_wireless_settings" msgid="2295017847215680229">"無線偵錯"</string>
<string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"如要查看並使用可用的裝置,請開啟無線偵錯功能"</string>
- <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"使用 QR 圖碼配對裝置"</string>
+ <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"使用 QR code 配對裝置"</string>
<string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"使用 QR code 掃描器配對新裝置"</string>
<string name="adb_pair_method_code_title" msgid="1122590300445142904">"使用配對碼配對裝置"</string>
<string name="adb_pair_method_code_summary" msgid="6370414511333685185">"使用六位數的配對碼配對新裝置"</string>
diff --git a/packages/SettingsLib/res/values-zu/arrays.xml b/packages/SettingsLib/res/values-zu/arrays.xml
index f36d99cbab57..ac3cb024fef8 100644
--- a/packages/SettingsLib/res/values-zu/arrays.xml
+++ b/packages/SettingsLib/res/values-zu/arrays.xml
@@ -63,13 +63,13 @@
<item msgid="6336372935919715515">"Okuhlungiwe okunikwe amandla"</item>
<item msgid="2779123106632690576">"Kunikwe amandla"</item>
</string-array>
- <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
- <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
- <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+ <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+ <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
<string-array name="bluetooth_avrcp_versions">
<item msgid="6603880723315236832">"I-AVRCP 1.5 (Okuzenzakalelayo)"</item>
<item msgid="1637054408779685086">"I-AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml
index 337c251705e4..502296029e23 100644
--- a/packages/SettingsLib/res/values/arrays.xml
+++ b/packages/SettingsLib/res/values/arrays.xml
@@ -118,9 +118,9 @@
<!-- Titles for Bluetooth HCI Snoop Filtered Logging -->
<string-array name="bt_hci_snoop_log_filters_entries">
- <item>Headers Filtered</item>
- <item>A2DP Media Packets Filtered</item>
- <item>RFCOMM Channel Filtered</item>
+ <item>Leave only ACL headers</item>
+ <item>Filter A2DP media packets</item>
+ <item>Filter RFCOMM channel</item>
</string-array>
<!-- Values for Bluetooth HCI Snoop Filtered Logging -->
@@ -132,10 +132,10 @@
<!-- Titles for Bluetooth HCI Snoop Filtered Logging -->
<string-array name="bt_hci_snoop_log_profile_filter_entries">
- <item>Disabled</item>
- <item>Magic</item>
- <item>Header</item>
- <item>Full Filter</item>
+ <item>Disable</item>
+ <item>Fill with string of characters</item>
+ <item>Leave only header</item>
+ <item>Fully remove</item>
</string-array>
<!-- Values for Bluetooth HCI Snoop Filtered Logging -->
diff --git a/packages/SettingsLib/res/values/styles.xml b/packages/SettingsLib/res/values/styles.xml
index 5a9e780df8e9..cc60382b48f9 100644
--- a/packages/SettingsLib/res/values/styles.xml
+++ b/packages/SettingsLib/res/values/styles.xml
@@ -14,7 +14,7 @@
~ limitations under the License
-->
-<resources>
+<resources xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
<style name="TextAppearanceSmall">
<item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
</style>
@@ -73,7 +73,7 @@
</style>
<style name="TextAppearanceBroadcastDialogButton" parent="@android:TextAppearance.DeviceDefault.Headline">
- <item name="android:textColor">?android:attr/textColorPrimary</item>
+ <item name="android:textColor">?androidprv:attr/textColorOnAccent</item>
<item name="android:textSize">@dimen/broadcast_dialog_btn_text_size</item>
</style>
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index 888b09fafd3b..e846480f68d9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -575,9 +575,15 @@ public class Utils {
/** Get the corresponding adaptive icon drawable. */
public static Drawable getBadgedIcon(Context context, Drawable icon, UserHandle user) {
+ UserManager um = context.getSystemService(UserManager.class);
+ boolean isClone = um.getProfiles(user.getIdentifier()).stream()
+ .anyMatch(profile ->
+ profile.isCloneProfile() && profile.id == user.getIdentifier());
try (IconFactory iconFactory = IconFactory.obtain(context)) {
return iconFactory
- .createBadgedIconBitmap(icon, new IconOptions().setUser(user))
+ .createBadgedIconBitmap(
+ icon,
+ new IconOptions().setUser(user).setIsCloneProfile(isClone))
.newIcon(context);
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java b/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java
index 85e8aad38808..59735f413f9d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java
@@ -183,7 +183,7 @@ public class AccessibilityUtils {
final String currentShortcutServiceId = Settings.Secure.getStringForUser(
context.getContentResolver(), Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE,
userId);
- if (!TextUtils.isEmpty(currentShortcutServiceId)) {
+ if (currentShortcutServiceId != null) {
return currentShortcutServiceId;
}
return context.getString(R.string.config_defaultAccessibilityService);
diff --git a/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java b/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
index 2614644feb20..688fc720d058 100644
--- a/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
+++ b/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
@@ -55,6 +55,7 @@ public class DreamBackend {
public ComponentName settingsComponentName;
public CharSequence description;
public Drawable previewImage;
+ public boolean supportsComplications = false;
@Override
public String toString() {
@@ -175,6 +176,7 @@ public class DreamBackend {
if (dreamMetadata != null) {
dreamInfo.settingsComponentName = dreamMetadata.settingsActivity;
dreamInfo.previewImage = dreamMetadata.previewImage;
+ dreamInfo.supportsComplications = dreamMetadata.showComplications;
}
dreamInfos.add(dreamInfo);
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
index 28353ab7dff4..52f3111d967c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
@@ -169,8 +169,11 @@ public class BatterySaverUtils {
*/
public static boolean maybeShowBatterySaverConfirmation(Context context, Bundle extras) {
if (Secure.getInt(context.getContentResolver(),
- Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 0) != 0) {
- return false; // Already shown.
+ Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 0) != 0
+ && Secure.getInt(context.getContentResolver(),
+ Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, 0) != 0) {
+ // Already shown.
+ return false;
}
context.sendBroadcast(
getSystemUiBroadcast(ACTION_SHOW_START_SAVER_CONFIRMATION, extras));
@@ -190,8 +193,10 @@ public class BatterySaverUtils {
}
private static void setBatterySaverConfirmationAcknowledged(Context context) {
- Secure.putIntForUser(context.getContentResolver(), Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 1,
- UserHandle.USER_CURRENT);
+ Secure.putIntForUser(context.getContentResolver(),
+ Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 1, UserHandle.USER_CURRENT);
+ Secure.putIntForUser(context.getContentResolver(),
+ Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, 1, UserHandle.USER_CURRENT);
}
/**
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java b/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
index 6a1cee3146a2..562d20d05429 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
@@ -224,6 +224,9 @@ public class EnableZenModeDialog {
mMetricsLogger.logOnConditionSelected();
updateAlarmWarningText(tag.condition);
}
+ tag.line1.setStateDescription(
+ isChecked ? buttonView.getContext().getString(
+ com.android.internal.R.string.selected) : null);
}
});
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java b/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java
index 87e97b17b914..abbdaa73c18e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java
@@ -196,6 +196,9 @@ public class ZenDurationDialog {
if (isChecked) {
tag.rb.setChecked(true);
}
+ tag.line1.setStateDescription(
+ isChecked ? buttonView.getContext().getString(
+ com.android.internal.R.string.selected) : null);
}
});
diff --git a/packages/SettingsLib/src/com/android/settingslib/udfps/UdfpsUtils.java b/packages/SettingsLib/src/com/android/settingslib/udfps/UdfpsUtils.java
index dc8a862d72c7..31f014c27a13 100644
--- a/packages/SettingsLib/src/com/android/settingslib/udfps/UdfpsUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/udfps/UdfpsUtils.java
@@ -62,16 +62,7 @@ public class UdfpsUtils {
*/
public Point getTouchInNativeCoordinates(int idx, MotionEvent event,
UdfpsOverlayParams udfpsOverlayParams) {
- Point portraitTouch = new Point((int) event.getRawX(idx), (int) event.getRawY(idx));
- int rot = udfpsOverlayParams.getRotation();
- if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
- RotationUtils.rotatePoint(
- portraitTouch,
- RotationUtils.deltaRotation(rot, Surface.ROTATION_0),
- udfpsOverlayParams.getLogicalDisplayWidth(),
- udfpsOverlayParams.getLogicalDisplayHeight()
- );
- }
+ Point portraitTouch = getPortraitTouch(idx, event, udfpsOverlayParams);
// Scale the coordinates to native resolution.
float scale = udfpsOverlayParams.getScaleFactor();
@@ -81,13 +72,25 @@ public class UdfpsUtils {
}
/**
+ * @param idx The pointer identifier.
+ * @param event The MotionEvent object containing full information about the event.
+ * @param udfpsOverlayParams The [UdfpsOverlayParams] used.
+ * @return Whether the touch event is within sensor area.
+ */
+ public boolean isWithinSensorArea(int idx, MotionEvent event,
+ UdfpsOverlayParams udfpsOverlayParams) {
+ Point portraitTouch = getPortraitTouch(idx, event, udfpsOverlayParams);
+ return udfpsOverlayParams.getSensorBounds().contains(portraitTouch.x, portraitTouch.y);
+ }
+
+ /**
* This function computes the angle of touch relative to the sensor and maps the angle to a list
* of help messages which are announced if accessibility is enabled.
*
* @return Whether the announcing string is null
*/
- public String onTouchOutsideOfSensorArea(boolean touchExplorationEnabled,
- Context context, int touchX, int touchY, UdfpsOverlayParams udfpsOverlayParams) {
+ public String onTouchOutsideOfSensorArea(boolean touchExplorationEnabled, Context context,
+ int scaledTouchX, int scaledTouchY, UdfpsOverlayParams udfpsOverlayParams) {
if (!touchExplorationEnabled) {
return null;
}
@@ -106,8 +109,8 @@ public class UdfpsUtils {
String theStr =
onTouchOutsideOfSensorAreaImpl(
touchHints,
- touchX,
- touchY,
+ scaledTouchX,
+ scaledTouchY,
scaledSensorX,
scaledSensorY,
udfpsOverlayParams.getRotation()
@@ -156,4 +159,22 @@ public class UdfpsUtils {
}
return touchHints[index];
}
+
+ /**
+ * Map the touch to portrait mode if the device is in landscape mode.
+ */
+ private Point getPortraitTouch(int idx, MotionEvent event,
+ UdfpsOverlayParams udfpsOverlayParams) {
+ Point portraitTouch = new Point((int) event.getRawX(idx), (int) event.getRawY(idx));
+ int rot = udfpsOverlayParams.getRotation();
+ if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
+ RotationUtils.rotatePoint(
+ portraitTouch,
+ RotationUtils.deltaRotation(rot, Surface.ROTATION_0),
+ udfpsOverlayParams.getLogicalDisplayWidth(),
+ udfpsOverlayParams.getLogicalDisplayHeight()
+ );
+ }
+ return portraitTouch;
+ }
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java
index a15fe9f90206..ad022a63eaf6 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java
@@ -69,6 +69,7 @@ public class BatterySaverUtilsTest {
@Test
public void testSetPowerSaveMode_enable_firstCall_needWarning() {
Secure.putString(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, "null");
+ Secure.putString(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, "null");
Secure.putString(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, "null");
assertThat(BatterySaverUtils.setPowerSaveMode(mMockContext, true, true)).isFalse();
@@ -77,15 +78,18 @@ public class BatterySaverUtilsTest {
verify(mMockPowerManager, times(0)).setPowerSaveModeEnabled(anyBoolean());
// They shouldn't have changed.
+ assertEquals(-1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
assertEquals(-1,
- Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
+ Secure.getInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, -1));
assertEquals(-2,
Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
}
@Test
public void testSetPowerSaveMode_enable_secondCall_needWarning() {
- Secure.putInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 1); // Already acked.
+ // Already acked.
+ Secure.putInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 1);
+ Secure.putInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, 1);
Secure.putString(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, "null");
assertThat(BatterySaverUtils.setPowerSaveMode(mMockContext, true, true)).isTrue();
@@ -94,12 +98,17 @@ public class BatterySaverUtilsTest {
verify(mMockPowerManager, times(1)).setPowerSaveModeEnabled(eq(true));
assertEquals(1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
- assertEquals(1, Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
+ assertEquals(1,
+ Secure.getInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, -1));
+ assertEquals(1,
+ Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
}
@Test
public void testSetPowerSaveMode_enable_thridCall_needWarning() {
- Secure.putInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 1); // Already acked.
+ // Already acked.
+ Secure.putInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 1);
+ Secure.putInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, 1);
Secure.putInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, 1);
assertThat(BatterySaverUtils.setPowerSaveMode(mMockContext, true, true)).isTrue();
@@ -108,12 +117,16 @@ public class BatterySaverUtilsTest {
verify(mMockPowerManager, times(1)).setPowerSaveModeEnabled(eq(true));
assertEquals(1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
- assertEquals(2, Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
+ assertEquals(1,
+ Secure.getInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, -1));
+ assertEquals(2,
+ Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
}
@Test
public void testSetPowerSaveMode_enable_firstCall_noWarning() {
Secure.putString(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, "null");
+ Secure.putString(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, "null");
Secure.putString(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, "null");
assertThat(BatterySaverUtils.setPowerSaveMode(mMockContext, true, false)).isTrue();
@@ -122,12 +135,15 @@ public class BatterySaverUtilsTest {
verify(mMockPowerManager, times(1)).setPowerSaveModeEnabled(eq(true));
assertEquals(1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
+ assertEquals(1,
+ Secure.getInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, -1));
assertEquals(1, Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
}
@Test
public void testSetPowerSaveMode_disable_firstCall_noWarning() {
Secure.putString(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, "null");
+ Secure.putString(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, "null");
Secure.putString(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, "null");
// When disabling, needFirstTimeWarning doesn't matter.
@@ -137,6 +153,8 @@ public class BatterySaverUtilsTest {
verify(mMockPowerManager, times(1)).setPowerSaveModeEnabled(eq(false));
assertEquals(-1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
+ assertEquals(-1,
+ Secure.getInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, -1));
assertEquals(-2,
Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
}
@@ -144,6 +162,7 @@ public class BatterySaverUtilsTest {
@Test
public void testSetPowerSaveMode_disable_firstCall_needWarning() {
Secure.putString(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, "null");
+ Secure.putString(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, "null");
Secure.putString(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, "null");
// When disabling, needFirstTimeWarning doesn't matter.
@@ -153,6 +172,8 @@ public class BatterySaverUtilsTest {
verify(mMockPowerManager, times(1)).setPowerSaveModeEnabled(eq(false));
assertEquals(-1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
+ assertEquals(-1,
+ Secure.getInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, -1));
assertEquals(-2,
Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java
index 59d56747ec5d..6b81c1a6f794 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java
@@ -16,6 +16,8 @@
package com.android.settingslib.notification;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
@@ -78,6 +80,8 @@ public class EnableZenModeDialogTest {
mController.mForeverId = Condition.newId(mContext).appendPath("forever").build();
when(mContext.getString(com.android.internal.R.string.zen_mode_forever))
.thenReturn("testSummary");
+ when(mContext.getString(com.android.internal.R.string.selected))
+ .thenReturn("selected");
NotificationManager.Policy alarmsEnabledPolicy = new NotificationManager.Policy(
NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS, 0, 0, 0);
doReturn(alarmsEnabledPolicy).when(mNotificationManager).getNotificationPolicy();
@@ -190,4 +194,25 @@ public class EnableZenModeDialogTest {
// alarm warning should NOT be null
assertNotNull(mController.computeAlarmWarningText(null));
}
+
+ @Test
+ public void testAccessibility() {
+ mController.bindConditions(null);
+ EnableZenModeDialog.ConditionTag forever = mController.getConditionTagAt(
+ ZenDurationDialog.FOREVER_CONDITION_INDEX);
+ EnableZenModeDialog.ConditionTag countdown = mController.getConditionTagAt(
+ ZenDurationDialog.COUNTDOWN_CONDITION_INDEX);
+ EnableZenModeDialog.ConditionTag alwaysAsk = mController.getConditionTagAt(
+ ZenDurationDialog.ALWAYS_ASK_CONDITION_INDEX);
+
+ forever.rb.setChecked(true);
+ assertThat(forever.line1.getStateDescription().toString()).isEqualTo("selected");
+ assertThat(countdown.line1.getStateDescription()).isNull();
+ assertThat(alwaysAsk.line1.getStateDescription()).isNull();
+
+ alwaysAsk.rb.setChecked(true);
+ assertThat(forever.line1.getStateDescription()).isNull();
+ assertThat(countdown.line1.getStateDescription()).isNull();
+ assertThat(alwaysAsk.line1.getStateDescription().toString()).isEqualTo("selected");
+ }
} \ No newline at end of file
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java
index 437c0d4f4469..fc45e89a6dd5 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java
@@ -16,6 +16,8 @@
package com.android.settingslib.notification;
+import static com.google.common.truth.Truth.assertThat;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
@@ -205,4 +207,27 @@ public class ZenDurationDialogTest {
ZenDurationDialog.COUNTDOWN_CONDITION_INDEX);
assertEquals(120, tag.countdownZenDuration);
}
+
+ @Test
+ public void testAccessibility() {
+ Settings.Secure.putInt(mContentResolver, Settings.Secure.ZEN_DURATION,
+ Settings.Secure.ZEN_DURATION_FOREVER);
+ mController.setupDialog(mBuilder);
+ ZenDurationDialog.ConditionTag forever = mController.getConditionTagAt(
+ ZenDurationDialog.FOREVER_CONDITION_INDEX);
+ ZenDurationDialog.ConditionTag countdown = mController.getConditionTagAt(
+ ZenDurationDialog.COUNTDOWN_CONDITION_INDEX);
+ ZenDurationDialog.ConditionTag alwaysAsk = mController.getConditionTagAt(
+ ZenDurationDialog.ALWAYS_ASK_CONDITION_INDEX);
+
+ forever.rb.setChecked(true);
+ assertThat(forever.line1.getStateDescription().toString()).isEqualTo("selected");
+ assertThat(countdown.line1.getStateDescription()).isNull();
+ assertThat(alwaysAsk.line1.getStateDescription()).isNull();
+
+ alwaysAsk.rb.setChecked(true);
+ assertThat(forever.line1.getStateDescription()).isNull();
+ assertThat(countdown.line1.getStateDescription()).isNull();
+ assertThat(alwaysAsk.line1.getStateDescription().toString()).isEqualTo("selected");
+ }
} \ No newline at end of file
diff --git a/packages/SettingsProvider/Android.bp b/packages/SettingsProvider/Android.bp
index 1ac20471109f..346462df004b 100644
--- a/packages/SettingsProvider/Android.bp
+++ b/packages/SettingsProvider/Android.bp
@@ -48,6 +48,7 @@ android_test {
"test/**/*.java",
"src/android/provider/settings/backup/*",
"src/android/provider/settings/validators/*",
+ "src/com/android/providers/settings/GenerationRegistry.java",
"src/com/android/providers/settings/SettingsBackupAgent.java",
"src/com/android/providers/settings/SettingsState.java",
"src/com/android/providers/settings/SettingsHelper.java",
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index 210a38796b6a..f66fcba74bc5 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -142,6 +142,8 @@ public class SecureSettings {
Settings.Secure.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION,
Settings.Secure.VOLUME_HUSH_GESTURE,
Settings.Secure.MANUAL_RINGER_TOGGLE_COUNT,
+ Settings.Secure.LOW_POWER_WARNING_ACKNOWLEDGED,
+ Settings.Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED,
Settings.Secure.HUSH_GESTURE_USED,
Settings.Secure.IN_CALL_NOTIFICATION_ENABLED,
Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
@@ -237,5 +239,6 @@ public class SecureSettings {
Settings.Secure.HEARING_AID_CALL_ROUTING,
Settings.Secure.HEARING_AID_MEDIA_ROUTING,
Settings.Secure.HEARING_AID_SYSTEM_SOUNDS_ROUTING,
+ Settings.Secure.ACCESSIBILITY_FONT_SCALING_HAS_BEEN_CHANGED
};
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index 39cd24a3b6d4..558e19f19986 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -219,6 +219,8 @@ public class SecureSettingsValidators {
COLON_SEPARATED_PACKAGE_LIST_VALIDATOR); // legacy restore setting
VALIDATORS.put(Secure.HUSH_GESTURE_USED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.MANUAL_RINGER_TOGGLE_COUNT, NON_NEGATIVE_INTEGER_VALIDATOR);
+ VALIDATORS.put(Secure.LOW_POWER_WARNING_ACKNOWLEDGED, BOOLEAN_VALIDATOR);
+ VALIDATORS.put(Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.IN_CALL_NOTIFICATION_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, BOOLEAN_VALIDATOR);
@@ -374,5 +376,6 @@ public class SecureSettingsValidators {
new DiscreteValueValidator(new String[] {"0", "1", "2"}));
VALIDATORS.put(Secure.HEARING_AID_SYSTEM_SOUNDS_ROUTING,
new DiscreteValueValidator(new String[] {"0", "1", "2"}));
+ VALIDATORS.put(Secure.ACCESSIBILITY_FONT_SCALING_HAS_BEEN_CHANGED, BOOLEAN_VALIDATOR);
}
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java b/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java
index 56173310a8bb..7f3b0ff8c838 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java
@@ -17,19 +17,19 @@
package com.android.providers.settings;
import android.os.Bundle;
-import android.os.UserManager;
import android.provider.Settings;
+import android.util.ArrayMap;
import android.util.MemoryIntArray;
import android.util.Slog;
-import android.util.SparseIntArray;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import java.io.IOException;
/**
* This class tracks changes for config/global/secure/system tables
- * on a per user basis and updates a shared memory region which
+ * on a per user basis and updates shared memory regions which
* client processes can read to determine if their local caches are
* stale.
*/
@@ -40,138 +40,187 @@ final class GenerationRegistry {
private final Object mLock;
+ // Key -> backingStore mapping
@GuardedBy("mLock")
- private final SparseIntArray mKeyToIndexMap = new SparseIntArray();
+ private final ArrayMap<Integer, MemoryIntArray> mKeyToBackingStoreMap = new ArrayMap();
+ // Key -> (String->Index map) mapping
@GuardedBy("mLock")
- private MemoryIntArray mBackingStore;
+ private final ArrayMap<Integer, ArrayMap<String, Integer>> mKeyToIndexMapMap = new ArrayMap<>();
+
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ // Maximum number of backing stores allowed
+ static final int NUM_MAX_BACKING_STORE = 8;
+
+ @GuardedBy("mLock")
+ private int mNumBackingStore = 0;
+
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ // Maximum size of an individual backing store
+ static final int MAX_BACKING_STORE_SIZE = MemoryIntArray.getMaxSize();
public GenerationRegistry(Object lock) {
mLock = lock;
}
- public void incrementGeneration(int key) {
+ /**
+ * Increment the generation number if the setting is already cached in the backing stores.
+ * Otherwise, do nothing.
+ */
+ public void incrementGeneration(int key, String name) {
+ final boolean isConfig =
+ (SettingsState.getTypeFromKey(key) == SettingsState.SETTINGS_TYPE_CONFIG);
+ // Only store the prefix if the mutated setting is a config
+ final String indexMapKey = isConfig ? (name.split("/")[0] + "/") : name;
synchronized (mLock) {
- MemoryIntArray backingStore = getBackingStoreLocked();
- if (backingStore != null) {
- try {
- final int index = getKeyIndexLocked(key, mKeyToIndexMap, backingStore);
- if (index >= 0) {
- final int generation = backingStore.get(index) + 1;
- backingStore.set(index, generation);
- }
- } catch (IOException e) {
- Slog.e(LOG_TAG, "Error updating generation id", e);
- destroyBackingStore();
+ final MemoryIntArray backingStore = getBackingStoreLocked(key,
+ /* createIfNotExist= */ false);
+ if (backingStore == null) {
+ return;
+ }
+ try {
+ final int index = getKeyIndexLocked(key, indexMapKey, mKeyToIndexMapMap,
+ backingStore, /* createIfNotExist= */ false);
+ if (index < 0) {
+ return;
+ }
+ final int generation = backingStore.get(index) + 1;
+ backingStore.set(index, generation);
+ if (DEBUG) {
+ Slog.i(LOG_TAG, "Incremented generation for setting:" + indexMapKey
+ + " key:" + SettingsState.keyToString(key)
+ + " at index:" + index);
}
+ } catch (IOException e) {
+ Slog.e(LOG_TAG, "Error updating generation id", e);
+ destroyBackingStoreLocked(key);
}
}
}
- public void addGenerationData(Bundle bundle, int key) {
+ /**
+ * Return the backing store's reference, the index and the current generation number
+ * of a cached setting. If it was not in the backing store, first create the entry in it before
+ * returning the result.
+ */
+ public void addGenerationData(Bundle bundle, int key, String indexMapKey) {
synchronized (mLock) {
- MemoryIntArray backingStore = getBackingStoreLocked();
+ final MemoryIntArray backingStore = getBackingStoreLocked(key,
+ /* createIfNotExist= */ true);
+ if (backingStore == null) {
+ // Error accessing existing backing store or no new backing store is available
+ return;
+ }
try {
- if (backingStore != null) {
- final int index = getKeyIndexLocked(key, mKeyToIndexMap, backingStore);
- if (index >= 0) {
- bundle.putParcelable(Settings.CALL_METHOD_TRACK_GENERATION_KEY,
- backingStore);
- bundle.putInt(Settings.CALL_METHOD_GENERATION_INDEX_KEY, index);
- bundle.putInt(Settings.CALL_METHOD_GENERATION_KEY,
- backingStore.get(index));
- if (DEBUG) {
- Slog.i(LOG_TAG, "Exported index:" + index + " for key:"
- + SettingsProvider.keyToString(key));
- }
- }
+ final int index = getKeyIndexLocked(key, indexMapKey, mKeyToIndexMapMap,
+ backingStore, /* createIfNotExist= */ true);
+ if (index < 0) {
+ // Should not happen unless having error accessing the backing store
+ return;
+ }
+ bundle.putParcelable(Settings.CALL_METHOD_TRACK_GENERATION_KEY,
+ backingStore);
+ bundle.putInt(Settings.CALL_METHOD_GENERATION_INDEX_KEY, index);
+ bundle.putInt(Settings.CALL_METHOD_GENERATION_KEY,
+ backingStore.get(index));
+ if (DEBUG) {
+ Slog.i(LOG_TAG, "Exported index:" + index
+ + " for setting:" + indexMapKey
+ + " key:" + SettingsState.keyToString(key));
}
} catch (IOException e) {
Slog.e(LOG_TAG, "Error adding generation data", e);
- destroyBackingStore();
+ destroyBackingStoreLocked(key);
}
}
}
public void onUserRemoved(int userId) {
+ final int secureKey = SettingsState.makeKey(
+ SettingsState.SETTINGS_TYPE_SECURE, userId);
+ final int systemKey = SettingsState.makeKey(
+ SettingsState.SETTINGS_TYPE_SYSTEM, userId);
synchronized (mLock) {
- MemoryIntArray backingStore = getBackingStoreLocked();
- if (backingStore != null && mKeyToIndexMap.size() > 0) {
- try {
- final int secureKey = SettingsProvider.makeKey(
- SettingsProvider.SETTINGS_TYPE_SECURE, userId);
- resetSlotForKeyLocked(secureKey, mKeyToIndexMap, backingStore);
-
- final int systemKey = SettingsProvider.makeKey(
- SettingsProvider.SETTINGS_TYPE_SYSTEM, userId);
- resetSlotForKeyLocked(systemKey, mKeyToIndexMap, backingStore);
- } catch (IOException e) {
- Slog.e(LOG_TAG, "Error cleaning up for user", e);
- destroyBackingStore();
- }
+ if (mKeyToIndexMapMap.containsKey(secureKey)) {
+ destroyBackingStoreLocked(secureKey);
+ mKeyToIndexMapMap.remove(secureKey);
+ mNumBackingStore = mNumBackingStore - 1;
+ }
+ if (mKeyToIndexMapMap.containsKey(systemKey)) {
+ destroyBackingStoreLocked(systemKey);
+ mKeyToIndexMapMap.remove(systemKey);
+ mNumBackingStore = mNumBackingStore - 1;
}
}
}
@GuardedBy("mLock")
- private MemoryIntArray getBackingStoreLocked() {
- if (mBackingStore == null) {
- // One for the config table, one for the global table, two for system
- // and secure tables for a managed profile (managed profile is not
- // included in the max user count), ten for partially deleted users if
- // users are quickly removed, and twice max user count for system and
- // secure.
- final int size = 1 + 1 + 2 + 10 + 2 * UserManager.getMaxSupportedUsers();
+ private MemoryIntArray getBackingStoreLocked(int key, boolean createIfNotExist) {
+ MemoryIntArray backingStore = mKeyToBackingStoreMap.get(key);
+ if (!createIfNotExist) {
+ return backingStore;
+ }
+ if (backingStore == null) {
try {
- mBackingStore = new MemoryIntArray(size);
+ if (mNumBackingStore >= NUM_MAX_BACKING_STORE) {
+ Slog.e(LOG_TAG, "Error creating backing store - at capacity");
+ return null;
+ }
+ backingStore = new MemoryIntArray(MAX_BACKING_STORE_SIZE);
+ mKeyToBackingStoreMap.put(key, backingStore);
+ mNumBackingStore += 1;
if (DEBUG) {
- Slog.e(LOG_TAG, "Created backing store " + mBackingStore);
+ Slog.e(LOG_TAG, "Created backing store for "
+ + SettingsState.keyToString(key) + " on user: "
+ + SettingsState.getUserIdFromKey(key));
}
} catch (IOException e) {
Slog.e(LOG_TAG, "Error creating generation tracker", e);
}
}
- return mBackingStore;
+ return backingStore;
}
- private void destroyBackingStore() {
- if (mBackingStore != null) {
+ @GuardedBy("mLock")
+ private void destroyBackingStoreLocked(int key) {
+ MemoryIntArray backingStore = mKeyToBackingStoreMap.get(key);
+ if (backingStore != null) {
try {
- mBackingStore.close();
+ backingStore.close();
if (DEBUG) {
- Slog.e(LOG_TAG, "Destroyed backing store " + mBackingStore);
+ Slog.e(LOG_TAG, "Destroyed backing store " + backingStore);
}
} catch (IOException e) {
Slog.e(LOG_TAG, "Cannot close generation memory array", e);
}
- mBackingStore = null;
+ mKeyToBackingStoreMap.remove(key);
}
}
- private static void resetSlotForKeyLocked(int key, SparseIntArray keyToIndexMap,
- MemoryIntArray backingStore) throws IOException {
- final int index = keyToIndexMap.get(key, -1);
- if (index >= 0) {
- keyToIndexMap.delete(key);
- backingStore.set(index, 0);
- if (DEBUG) {
- Slog.i(LOG_TAG, "Freed index:" + index + " for key:"
- + SettingsProvider.keyToString(key));
+ private static int getKeyIndexLocked(int key, String indexMapKey,
+ ArrayMap<Integer, ArrayMap<String, Integer>> keyToIndexMapMap,
+ MemoryIntArray backingStore, boolean createIfNotExist) throws IOException {
+ ArrayMap<String, Integer> nameToIndexMap = keyToIndexMapMap.get(key);
+ if (nameToIndexMap == null) {
+ if (!createIfNotExist) {
+ return -1;
}
+ nameToIndexMap = new ArrayMap<>();
+ keyToIndexMapMap.put(key, nameToIndexMap);
}
- }
-
- private static int getKeyIndexLocked(int key, SparseIntArray keyToIndexMap,
- MemoryIntArray backingStore) throws IOException {
- int index = keyToIndexMap.get(key, -1);
+ int index = nameToIndexMap.getOrDefault(indexMapKey, -1);
if (index < 0) {
+ if (!createIfNotExist) {
+ return -1;
+ }
index = findNextEmptyIndex(backingStore);
if (index >= 0) {
backingStore.set(index, 1);
- keyToIndexMap.append(key, index);
+ nameToIndexMap.put(indexMapKey, index);
if (DEBUG) {
- Slog.i(LOG_TAG, "Allocated index:" + index + " for key:"
- + SettingsProvider.keyToString(key));
+ Slog.i(LOG_TAG, "Allocated index:" + index + " for setting:" + indexMapKey
+ + " of type:" + SettingsState.keyToString(key)
+ + " on user:" + SettingsState.getUserIdFromKey(key));
}
} else {
Slog.e(LOG_TAG, "Could not allocate generation index");
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index 574fd5a7ec13..11154d165109 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -182,6 +182,8 @@ public class SettingsBackupAgent extends BackupAgentHelper {
"visible_pattern_enabled";
private static final String KEY_LOCK_SETTINGS_POWER_BUTTON_INSTANTLY_LOCKS =
"power_button_instantly_locks";
+ private static final String KEY_LOCK_SETTINGS_PIN_ENHANCED_PRIVACY =
+ "pin_enhanced_privacy";
// Name of the temporary file we use during full backup/restore. This is
// stored in the full-backup tarfile as well, so should not be changed.
@@ -709,6 +711,10 @@ public class SettingsBackupAgent extends BackupAgentHelper {
out.writeUTF(KEY_LOCK_SETTINGS_POWER_BUTTON_INSTANTLY_LOCKS);
out.writeUTF(powerButtonInstantlyLocks ? "1" : "0");
}
+ if (lockPatternUtils.isPinEnhancedPrivacyEverChosen(userId)) {
+ out.writeUTF(KEY_LOCK_SETTINGS_PIN_ENHANCED_PRIVACY);
+ out.writeUTF(lockPatternUtils.isPinEnhancedPrivacyEnabled(userId) ? "1" : "0");
+ }
// End marker
out.writeUTF("");
out.flush();
@@ -961,6 +967,9 @@ public class SettingsBackupAgent extends BackupAgentHelper {
case KEY_LOCK_SETTINGS_POWER_BUTTON_INSTANTLY_LOCKS:
lockPatternUtils.setPowerButtonInstantlyLocks("1".equals(value), userId);
break;
+ case KEY_LOCK_SETTINGS_PIN_ENHANCED_PRIVACY:
+ lockPatternUtils.setPinEnhancedPrivacyEnabled("1".equals(value), userId);
+ break;
}
}
in.close();
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index fb3c3136280e..1a6920803b03 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1852,6 +1852,9 @@ class SettingsProtoDumpUtil {
dumpSetting(s, p,
Settings.Secure.HEARING_AID_SYSTEM_SOUNDS_ROUTING,
SecureSettingsProto.Accessibility.HEARING_AID_SYSTEM_SOUNDS_ROUTING);
+ dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_FONT_SCALING_HAS_BEEN_CHANGED,
+ SecureSettingsProto.Accessibility.ACCESSIBILITY_FONT_SCALING_HAS_BEEN_CHANGED);
p.end(accessibilityToken);
final long adaptiveSleepToken = p.start(SecureSettingsProto.ADAPTIVE_SLEEP);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 683c08e3bfa4..ba275ebca168 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -35,6 +35,7 @@ import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OV
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME;
import static com.android.internal.accessibility.util.AccessibilityUtils.ACCESSIBILITY_MENU_IN_SYSTEM;
import static com.android.providers.settings.SettingsState.FALLBACK_FILE_SUFFIX;
+import static com.android.providers.settings.SettingsState.makeKey;
import android.Manifest;
import android.annotation.NonNull;
@@ -375,10 +376,6 @@ public class SettingsProvider extends ContentProvider {
@GuardedBy("mLock")
private boolean mSyncConfigDisabledUntilReboot;
- public static int makeKey(int type, int userId) {
- return SettingsState.makeKey(type, userId);
- }
-
public static int getTypeFromKey(int key) {
return SettingsState.getTypeFromKey(key);
}
@@ -387,9 +384,6 @@ public class SettingsProvider extends ContentProvider {
return SettingsState.getUserIdFromKey(key);
}
- public static String keyToString(int key) {
- return SettingsState.keyToString(key);
- }
@ChangeId
@EnabledSince(targetSdkVersion=android.os.Build.VERSION_CODES.S)
private static final long ENFORCE_READ_PERMISSION_FOR_MULTI_SIM_DATA_CALL = 172670679L;
@@ -428,22 +422,26 @@ public class SettingsProvider extends ContentProvider {
switch (method) {
case Settings.CALL_METHOD_GET_CONFIG: {
Setting setting = getConfigSetting(name);
- return packageValueForCallResult(setting, isTrackingGeneration(args));
+ return packageValueForCallResult(SETTINGS_TYPE_CONFIG, name, requestingUserId,
+ setting, isTrackingGeneration(args));
}
case Settings.CALL_METHOD_GET_GLOBAL: {
Setting setting = getGlobalSetting(name);
- return packageValueForCallResult(setting, isTrackingGeneration(args));
+ return packageValueForCallResult(SETTINGS_TYPE_GLOBAL, name, requestingUserId,
+ setting, isTrackingGeneration(args));
}
case Settings.CALL_METHOD_GET_SECURE: {
Setting setting = getSecureSetting(name, requestingUserId);
- return packageValueForCallResult(setting, isTrackingGeneration(args));
+ return packageValueForCallResult(SETTINGS_TYPE_SECURE, name, requestingUserId,
+ setting, isTrackingGeneration(args));
}
case Settings.CALL_METHOD_GET_SYSTEM: {
Setting setting = getSystemSetting(name, requestingUserId);
- return packageValueForCallResult(setting, isTrackingGeneration(args));
+ return packageValueForCallResult(SETTINGS_TYPE_SYSTEM, name, requestingUserId,
+ setting, isTrackingGeneration(args));
}
case Settings.CALL_METHOD_PUT_CONFIG: {
@@ -553,7 +551,7 @@ public class SettingsProvider extends ContentProvider {
case Settings.CALL_METHOD_LIST_CONFIG: {
String prefix = getSettingPrefix(args);
- Bundle result = packageValuesForCallResult(getAllConfigFlags(prefix),
+ Bundle result = packageValuesForCallResult(prefix, getAllConfigFlags(prefix),
isTrackingGeneration(args));
reportDeviceConfigAccess(prefix);
return result;
@@ -1319,6 +1317,7 @@ public class SettingsProvider extends ContentProvider {
return false;
}
+ @NonNull
private HashMap<String, String> getAllConfigFlags(@Nullable String prefix) {
if (DEBUG) {
Slog.v(LOG_TAG, "getAllConfigFlags() for " + prefix);
@@ -2316,7 +2315,8 @@ public class SettingsProvider extends ContentProvider {
"get/set setting for user", null);
}
- private Bundle packageValueForCallResult(Setting setting, boolean trackingGeneration) {
+ private Bundle packageValueForCallResult(int type, @NonNull String name, int userId,
+ @Nullable Setting setting, boolean trackingGeneration) {
if (!trackingGeneration) {
if (setting == null || setting.isNull()) {
return NULL_SETTING_BUNDLE;
@@ -2325,21 +2325,40 @@ public class SettingsProvider extends ContentProvider {
}
Bundle result = new Bundle();
result.putString(Settings.NameValueTable.VALUE,
- !setting.isNull() ? setting.getValue() : null);
+ (setting != null && !setting.isNull()) ? setting.getValue() : null);
- mSettingsRegistry.mGenerationRegistry.addGenerationData(result, setting.getKey());
+ if ((setting != null && !setting.isNull()) || isSettingPreDefined(name, type)) {
+ // Don't track generation for non-existent settings unless the name is predefined
+ synchronized (mLock) {
+ mSettingsRegistry.mGenerationRegistry.addGenerationData(result,
+ SettingsState.makeKey(type, userId), name);
+ }
+ }
return result;
}
- private Bundle packageValuesForCallResult(HashMap<String, String> keyValues,
- boolean trackingGeneration) {
+ private boolean isSettingPreDefined(String name, int type) {
+ if (type == SETTINGS_TYPE_GLOBAL) {
+ return sAllGlobalSettings.contains(name);
+ } else if (type == SETTINGS_TYPE_SECURE) {
+ return sAllSecureSettings.contains(name);
+ } else if (type == SETTINGS_TYPE_SYSTEM) {
+ return sAllSystemSettings.contains(name);
+ } else {
+ return false;
+ }
+ }
+
+ private Bundle packageValuesForCallResult(String prefix,
+ @NonNull HashMap<String, String> keyValues, boolean trackingGeneration) {
Bundle result = new Bundle();
result.putSerializable(Settings.NameValueTable.VALUE, keyValues);
if (trackingGeneration) {
+ // Track generation even if the namespace is empty because this is for system apps
synchronized (mLock) {
mSettingsRegistry.mGenerationRegistry.addGenerationData(result,
- mSettingsRegistry.getSettingsLocked(
- SETTINGS_TYPE_CONFIG, UserHandle.USER_SYSTEM).mKey);
+ mSettingsRegistry.getSettingsLocked(SETTINGS_TYPE_CONFIG,
+ UserHandle.USER_SYSTEM).mKey, prefix);
}
}
@@ -3449,7 +3468,7 @@ public class SettingsProvider extends ContentProvider {
private void notifyForSettingsChange(int key, String name) {
// Increment the generation first, so observers always see the new value
- mGenerationRegistry.incrementGeneration(key);
+ mGenerationRegistry.incrementGeneration(key, name);
if (isGlobalSettingsKey(key) || isConfigSettingsKey(key)) {
final long token = Binder.clearCallingIdentity();
@@ -3487,7 +3506,7 @@ public class SettingsProvider extends ContentProvider {
List<String> changedSettings) {
// Increment the generation first, so observers always see the new value
- mGenerationRegistry.incrementGeneration(key);
+ mGenerationRegistry.incrementGeneration(key, prefix);
StringBuilder stringBuilder = new StringBuilder(prefix);
for (int i = 0; i < changedSettings.size(); ++i) {
@@ -3513,7 +3532,7 @@ public class SettingsProvider extends ContentProvider {
if (profileId != userId) {
final int key = makeKey(type, profileId);
// Increment the generation first, so observers always see the new value
- mGenerationRegistry.incrementGeneration(key);
+ mGenerationRegistry.incrementGeneration(key, name);
mHandler.obtainMessage(MyHandler.MSG_NOTIFY_URI_CHANGED,
profileId, 0, uri).sendToTarget();
}
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index c0176d57cd59..278ceb944ef6 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -322,6 +322,7 @@ public class SettingsBackupTest {
Settings.Global.LOW_BATTERY_SOUND,
Settings.Global.LOW_BATTERY_SOUND_TIMEOUT,
Settings.Global.LOW_POWER_MODE,
+ Settings.Global.EXTRA_LOW_POWER_MODE,
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL_MAX,
Settings.Global.LOW_POWER_MODE_STICKY,
Settings.Global.LOW_POWER_MODE_SUGGESTION_PARAMS,
@@ -800,7 +801,6 @@ public class SettingsBackupTest {
Settings.Secure.PARENTAL_CONTROL_REDIRECT_URL,
Settings.Secure.BLUETOOTH_ON_WHILE_DRIVING,
Settings.Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT,
- Settings.Secure.LOW_POWER_WARNING_ACKNOWLEDGED,
Settings.Secure.SUPPRESS_AUTO_BATTERY_SAVER_SUGGESTION,
Settings.Secure.PACKAGES_TO_CLEAR_DATA_BEFORE_FULL_RESTORE,
Settings.Secure.FLASHLIGHT_AVAILABLE,
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/GenerationRegistryTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/GenerationRegistryTest.java
new file mode 100644
index 000000000000..d34fe6943153
--- /dev/null
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/GenerationRegistryTest.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2023 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.providers.settings;
+
+import static android.provider.Settings.CALL_METHOD_GENERATION_INDEX_KEY;
+import static android.provider.Settings.CALL_METHOD_GENERATION_KEY;
+import static android.provider.Settings.CALL_METHOD_TRACK_GENERATION_KEY;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.Bundle;
+import android.util.MemoryIntArray;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+
+@RunWith(AndroidJUnit4.class)
+public class GenerationRegistryTest {
+ @Test
+ public void testGenerationsWithRegularSetting() throws IOException {
+ final GenerationRegistry generationRegistry = new GenerationRegistry(new Object());
+ final int secureKey = SettingsState.makeKey(SettingsState.SETTINGS_TYPE_SECURE, 0);
+ final String testSecureSetting = "test_secure_setting";
+ Bundle b = new Bundle();
+ // IncrementGeneration should have no effect on a non-cached setting.
+ generationRegistry.incrementGeneration(secureKey, testSecureSetting);
+ generationRegistry.incrementGeneration(secureKey, testSecureSetting);
+ generationRegistry.incrementGeneration(secureKey, testSecureSetting);
+ generationRegistry.addGenerationData(b, secureKey, testSecureSetting);
+ // Default index is 0 and generation is only 1 despite early calls of incrementGeneration
+ checkBundle(b, 0, 1, false);
+
+ generationRegistry.incrementGeneration(secureKey, testSecureSetting);
+ generationRegistry.addGenerationData(b, secureKey, testSecureSetting);
+ // Index is still 0 and generation is now 2; also check direct array access
+ assertThat(getArray(b).get(0)).isEqualTo(2);
+
+ final int systemKey = SettingsState.makeKey(SettingsState.SETTINGS_TYPE_SYSTEM, 0);
+ final String testSystemSetting = "test_system_setting";
+ generationRegistry.addGenerationData(b, systemKey, testSystemSetting);
+ // Default index is 0 and generation is 1 for another backingStore (system)
+ checkBundle(b, 0, 1, false);
+
+ final String testSystemSetting2 = "test_system_setting2";
+ generationRegistry.addGenerationData(b, systemKey, testSystemSetting2);
+ // Second system setting index is 1 and default generation is 1
+ checkBundle(b, 1, 1, false);
+
+ generationRegistry.incrementGeneration(systemKey, testSystemSetting);
+ generationRegistry.incrementGeneration(systemKey, testSystemSetting);
+ generationRegistry.addGenerationData(b, systemKey, testSystemSetting);
+ // First system setting generation now incremented to 3
+ checkBundle(b, 0, 3, false);
+
+ final int systemKey2 = SettingsState.makeKey(SettingsState.SETTINGS_TYPE_SYSTEM, 10);
+ generationRegistry.addGenerationData(b, systemKey2, testSystemSetting);
+ // User 10 has a new set of backingStores
+ checkBundle(b, 0, 1, false);
+
+ // Check user removal
+ generationRegistry.onUserRemoved(10);
+ generationRegistry.incrementGeneration(systemKey2, testSystemSetting);
+
+ // Removed user should not affect existing caches
+ generationRegistry.addGenerationData(b, secureKey, testSecureSetting);
+ assertThat(getArray(b).get(0)).isEqualTo(2);
+
+ // IncrementGeneration should have no effect for a non-cached user
+ b.clear();
+ checkBundle(b, -1, -1, true);
+ // AddGeneration should create new backing store for the non-cached user
+ generationRegistry.addGenerationData(b, systemKey2, testSystemSetting);
+ checkBundle(b, 0, 1, false);
+ }
+
+ @Test
+ public void testGenerationsWithConfigSetting() throws IOException {
+ final GenerationRegistry generationRegistry = new GenerationRegistry(new Object());
+ final String prefix = "test_namespace/";
+ final int configKey = SettingsState.makeKey(SettingsState.SETTINGS_TYPE_CONFIG, 0);
+
+ Bundle b = new Bundle();
+ generationRegistry.addGenerationData(b, configKey, prefix);
+ checkBundle(b, 0, 1, false);
+
+ final String setting = "test_namespace/test_setting";
+ // Check that the generation of the prefix is incremented correctly
+ generationRegistry.incrementGeneration(configKey, setting);
+ generationRegistry.addGenerationData(b, configKey, prefix);
+ checkBundle(b, 0, 2, false);
+ }
+
+ @Test
+ public void testMaxNumBackingStores() throws IOException {
+ final GenerationRegistry generationRegistry = new GenerationRegistry(new Object());
+ final String testSecureSetting = "test_secure_setting";
+ Bundle b = new Bundle();
+ for (int i = 0; i < GenerationRegistry.NUM_MAX_BACKING_STORE; i++) {
+ b.clear();
+ final int key = SettingsState.makeKey(SettingsState.SETTINGS_TYPE_SECURE, i);
+ generationRegistry.addGenerationData(b, key, testSecureSetting);
+ checkBundle(b, 0, 1, false);
+ }
+ b.clear();
+ final int key = SettingsState.makeKey(SettingsState.SETTINGS_TYPE_SECURE,
+ GenerationRegistry.NUM_MAX_BACKING_STORE + 1);
+ generationRegistry.addGenerationData(b, key, testSecureSetting);
+ // Should fail to add generation because the number of backing stores has reached limit
+ checkBundle(b, -1, -1, true);
+ // Remove one user should free up a backing store
+ generationRegistry.onUserRemoved(0);
+ generationRegistry.addGenerationData(b, key, testSecureSetting);
+ checkBundle(b, 0, 1, false);
+ }
+
+ @Test
+ public void testMaxSizeBackingStore() throws IOException {
+ final GenerationRegistry generationRegistry = new GenerationRegistry(new Object());
+ final int secureKey = SettingsState.makeKey(SettingsState.SETTINGS_TYPE_SECURE, 0);
+ final String testSecureSetting = "test_secure_setting";
+ Bundle b = new Bundle();
+ for (int i = 0; i < GenerationRegistry.MAX_BACKING_STORE_SIZE; i++) {
+ generationRegistry.addGenerationData(b, secureKey, testSecureSetting + i);
+ checkBundle(b, i, 1, false);
+ }
+ b.clear();
+ generationRegistry.addGenerationData(b, secureKey, testSecureSetting);
+ // Should fail to increase index because the number of entries in the backing store has
+ // reached the limit
+ checkBundle(b, -1, -1, true);
+ // Shouldn't affect other cached entries
+ generationRegistry.addGenerationData(b, secureKey, testSecureSetting + "0");
+ checkBundle(b, 0, 1, false);
+ }
+
+ private void checkBundle(Bundle b, int expectedIndex, int expectedGeneration, boolean isNull)
+ throws IOException {
+ final MemoryIntArray array = getArray(b);
+ if (isNull) {
+ assertThat(array).isNull();
+ } else {
+ assertThat(array).isNotNull();
+ }
+ final int index = b.getInt(
+ CALL_METHOD_GENERATION_INDEX_KEY, -1);
+ assertThat(index).isEqualTo(expectedIndex);
+ final int generation = b.getInt(CALL_METHOD_GENERATION_KEY, -1);
+ assertThat(generation).isEqualTo(expectedGeneration);
+ if (!isNull) {
+ // Read into the result array with the result index should match the result generation
+ assertThat(array.get(index)).isEqualTo(generation);
+ }
+ }
+
+ private MemoryIntArray getArray(Bundle b) {
+ return b.getParcelable(
+ CALL_METHOD_TRACK_GENERATION_KEY, android.util.MemoryIntArray.class);
+ }
+}
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 82ca63d1a801..d02e5693bbf3 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -460,6 +460,9 @@
<!-- Permission needed to test registering pull atom callbacks -->
<uses-permission android:name="android.permission.REGISTER_STATS_PULL_ATOM" />
+ <!-- Permission needed to test querying restricted metrics -->
+ <uses-permission android:name="android.permission.READ_RESTRICTED_STATS" />
+
<!-- Permission needed to modify settings overrideable by restore in CTS tests -->
<uses-permission android:name="android.permission.MODIFY_SETTINGS_OVERRIDEABLE_BY_RESTORE" />
@@ -643,7 +646,7 @@
<!-- Permission required for CTS test - ResourceObserverNativeTest -->
<uses-permission android:name="android.permission.REGISTER_MEDIA_RESOURCE_OBSERVER" />
- <!-- Permission required for CTS test - CtsPermission5TestCases -->
+ <!-- Permission required for CTS test - CtsAttributionSourceTestCases -->
<uses-permission android:name="android.permission.RENOUNCE_PERMISSIONS" />
<!-- Permission required for CTS test - android.widget.cts.ToastTest -->
@@ -718,6 +721,7 @@
<!-- Permission required for CTS test - CtsTelephonyTestCases -->
<uses-permission android:name="android.permission.BIND_TELECOM_CONNECTION_SERVICE" />
<uses-permission android:name="android.permission.MODIFY_CELL_BROADCASTS" />
+ <uses-permission android:name="android.permission.SATELLITE_COMMUNICATION" />
<!-- Permission required for CTS test - CtsPersistentDataBlockManagerTestCases -->
<uses-permission android:name="android.permission.ACCESS_PDB_STATE" />
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 9d469611479a..b236ac5af104 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -449,6 +449,7 @@ systemui_optimized_java_defaults {
enabled: true,
optimize: true,
shrink: true,
+ shrink_resources: true,
proguard_compatibility: false,
proguard_flags_files: ["proguard.flags"],
},
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 4e18222355e6..71f438eb0455 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -341,6 +341,8 @@
<uses-permission android:name="android.permission.SET_UNRESTRICTED_KEEP_CLEAR_AREAS" />
+ <uses-permission android:name="android.permission.MONITOR_KEYBOARD_BACKLIGHT" />
+
<protected-broadcast android:name="com.android.settingslib.action.REGISTER_SLICE_RECEIVER" />
<protected-broadcast android:name="com.android.settingslib.action.UNREGISTER_SLICE_RECEIVER" />
<protected-broadcast android:name="com.android.settings.flashlight.action.FLASHLIGHT_CHANGED" />
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/AccessibilityMenuService.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/AccessibilityMenuService.java
index 40af294f9a6f..c1f2aa86c6b5 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/AccessibilityMenuService.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/AccessibilityMenuService.java
@@ -275,7 +275,6 @@ public class AccessibilityMenuService extends AccessibilityService
info.brightnessMinimum,
info.brightnessMaximum
);
- mDisplayManager.setTemporaryBrightness(getDisplayId(), brightness);
mDisplayManager.setBrightness(getDisplayId(), brightness);
mA11yMenuLayout.showSnackbar(
getString(R.string.brightness_percentage_label,
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java
index dd0a4f0173ff..a25790ad7aa0 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java
@@ -16,6 +16,8 @@
package com.android.systemui.accessibility.accessibilitymenu.view;
+import static android.view.Display.DEFAULT_DISPLAY;
+
import static java.lang.Math.max;
import android.animation.Animator;
@@ -133,7 +135,12 @@ public class A11yMenuOverlayLayout {
initLayoutParams();
}
- mLayout = new FrameLayout(mService);
+ final Display display = mService.getSystemService(
+ DisplayManager.class).getDisplay(DEFAULT_DISPLAY);
+
+ mLayout = new FrameLayout(
+ mService.createDisplayContext(display).createWindowContext(
+ WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY, null));
updateLayoutPosition();
inflateLayoutAndSetOnTouchListener(mLayout);
mA11yMenuViewPager = new A11yMenuViewPager(mService);
diff --git a/packages/SystemUI/animation/Android.bp b/packages/SystemUI/animation/Android.bp
index 978ab5d9ddd8..5b5871f95fb3 100644
--- a/packages/SystemUI/animation/Android.bp
+++ b/packages/SystemUI/animation/Android.bp
@@ -29,6 +29,10 @@ android_library {
"src/**/*.java",
"src/**/*.kt",
],
+ exclude_srcs: [
+ "src/com/android/systemui/surfaceeffects/**/*.java",
+ "src/com/android/systemui/surfaceeffects/**/*.kt",
+ ],
resource_dirs: [
"res",
@@ -38,8 +42,30 @@ android_library {
"androidx.core_core-animation-nodeps",
"androidx.core_core-ktx",
"androidx.annotation_annotation",
+ "SystemUIShaderLib",
],
manifest: "AndroidManifest.xml",
kotlincflags: ["-Xjvm-default=all"],
}
+
+android_library {
+ name: "SystemUIShaderLib",
+
+ srcs: [
+ "src/com/android/systemui/surfaceeffects/**/*.java",
+ "src/com/android/systemui/surfaceeffects/**/*.kt",
+ ],
+
+ static_libs: [
+ "androidx.core_core-animation-nodeps",
+ "androidx.core_core-ktx",
+ "androidx.annotation_annotation",
+ ],
+
+ manifest: "AndroidManifest.xml",
+ kotlincflags: ["-Xjvm-default=all"],
+
+ // sdk_version must be specified, otherwise it compiles against private APIs.
+ sdk_version: "current",
+}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/Expandable.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/Expandable.kt
index 40a5e9794d37..c49a487c6766 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/Expandable.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/Expandable.kt
@@ -26,7 +26,7 @@ interface Expandable {
* currently not attached or visible).
*
* @param cujType the CUJ type from the [com.android.internal.jank.InteractionJankMonitor]
- * associated to the launch that will use this controller.
+ * associated to the launch that will use this controller.
*/
fun activityLaunchController(cujType: Int? = null): ActivityLaunchAnimator.Controller?
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt
index 9668066be125..3417ffd6b83a 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt
@@ -75,7 +75,7 @@ class LaunchAnimator(private val timings: Timings, private val interpolators: In
* - Get the associated [Context].
* - Compute whether we are expanding fully above the launch container.
* - Get to overlay to which we initially put the window background layer, until the opening
- * window is made visible (see [openingWindowSyncView]).
+ * window is made visible (see [openingWindowSyncView]).
*
* This container can be changed to force this [Controller] to animate the expanding view
* inside a different location, for instance to ensure correct layering during the
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
index b98b92219c33..ed8e70568b48 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
@@ -24,7 +24,7 @@ interface LaunchableView {
* Set whether this view should block/postpone all calls to [View.setVisibility]. This ensures
* that this view:
* - remains invisible during the launch animation given that it is ghosted and already drawn
- * somewhere else.
+ * somewhere else.
* - remains invisible as long as a dialog expanded from it is shown.
* - restores its expected visibility once the dialog expanded from it is dismissed.
*
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteTransitionAdapter.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteTransitionAdapter.kt
index 0e2d23b04a4f..6946e6bf88a8 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteTransitionAdapter.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteTransitionAdapter.kt
@@ -182,9 +182,9 @@ class RemoteTransitionAdapter {
* Represents a TransitionInfo object as an array of old-style targets
*
* @param wallpapers If true, this will return wallpaper targets; otherwise it returns
- * non-wallpaper targets.
+ * non-wallpaper targets.
* @param leashMap Temporary map of change leash -> launcher leash. Is an output, so should
- * be populated by this function. If null, it is ignored.
+ * be populated by this function. If null, it is ignored.
*/
fun wrapTargets(
info: TransitionInfo,
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ShadeInterpolation.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ShadeInterpolation.kt
index a96f893a8db4..b89a8b0e0272 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ShadeInterpolation.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ShadeInterpolation.kt
@@ -6,6 +6,7 @@ object ShadeInterpolation {
/**
* Interpolate alpha for notification background scrim during shade expansion.
+ *
* @param fraction Shade expansion fraction
*/
@JvmStatic
@@ -16,6 +17,7 @@ object ShadeInterpolation {
/**
* Interpolate alpha for shade content during shade expansion.
+ *
* @param fraction Shade expansion fraction
*/
@JvmStatic
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
index 341784e26257..468a8b10bc01 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
@@ -161,7 +161,6 @@ class TextInterpolator(layout: Layout) {
* This API is useful to continue animation from the middle of the state. For example, if you
* animate weight from 200 to 400, then if you want to move back to 200 at the half of the
* animation, it will look like
- *
* <pre> <code>
* ```
* val interp = TextInterpolator(layout)
@@ -497,7 +496,9 @@ class TextInterpolator(layout: Layout) {
count,
layout.textDirectionHeuristic,
paint
- ) { _, _, glyphs, _ -> runs.add(glyphs) }
+ ) { _, _, glyphs, _ ->
+ runs.add(glyphs)
+ }
out.add(runs)
if (lineNo > 0) {
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableImageView.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableImageView.kt
index a1d9d90523eb..e42b589f05cf 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableImageView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableImageView.kt
@@ -24,7 +24,7 @@ import com.android.systemui.animation.LaunchableView
import com.android.systemui.animation.LaunchableViewDelegate
/** An [ImageView] that also implements [LaunchableView]. */
-class LaunchableImageView : ImageView, LaunchableView {
+open class LaunchableImageView : ImageView, LaunchableView {
private val delegate =
LaunchableViewDelegate(
this,
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableTextView.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableTextView.kt
index 286996dcaeaa..147669528c5e 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableTextView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableTextView.kt
@@ -24,7 +24,7 @@ import com.android.systemui.animation.LaunchableView
import com.android.systemui.animation.LaunchableViewDelegate
/** A [TextView] that also implements [LaunchableView]. */
-class LaunchableTextView : TextView, LaunchableView {
+open class LaunchableTextView : TextView, LaunchableView {
private val delegate =
LaunchableViewDelegate(
this,
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/MultiRippleView.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/MultiRippleView.kt
index 550d2c6d8732..6c175ddf1ea4 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/MultiRippleView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/MultiRippleView.kt
@@ -20,7 +20,6 @@ import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.util.AttributeSet
-import android.util.Log
import android.view.View
import androidx.annotation.VisibleForTesting
@@ -34,24 +33,15 @@ class MultiRippleView(context: Context?, attrs: AttributeSet?) : View(context, a
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
val ripples = ArrayList<RippleAnimation>()
private val ripplePaint = Paint()
- private var isWarningLogged = false
companion object {
private const val TAG = "MultiRippleView"
}
- override fun onDraw(canvas: Canvas?) {
- if (canvas == null || !canvas.isHardwareAccelerated) {
- // Drawing with the ripple shader requires hardware acceleration, so skip
- // if it's unsupported.
- if (!isWarningLogged) {
- // Only log once to not spam.
- Log.w(
- TAG,
- "Can't draw ripple shader. $canvas does not support hardware acceleration."
- )
- isWarningLogged = true
- }
+ override fun onDraw(canvas: Canvas) {
+ if (!canvas.isHardwareAccelerated) {
+ // Drawing with the ripple shader requires hardware acceleration, so skip if it's
+ // unsupported.
return
}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt
index bd91c65ecc6e..d4372507e2c4 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt
@@ -54,7 +54,7 @@ class RippleAnimation(private val config: RippleAnimationConfig) {
}
animator.addListener(
object : AnimatorListenerAdapter() {
- override fun onAnimationEnd(animation: Animator?) {
+ override fun onAnimationEnd(animation: Animator) {
onAnimationEnd?.run()
}
}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
index 0b842ad5331c..b5b6037aeae4 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
@@ -17,15 +17,14 @@ package com.android.systemui.surfaceeffects.ripple
import android.graphics.RuntimeShader
import android.util.Log
-import android.util.MathUtils
+import android.view.animation.Interpolator
+import android.view.animation.PathInterpolator
import androidx.annotation.VisibleForTesting
-import com.android.systemui.animation.Interpolators
import com.android.systemui.surfaceeffects.shaderutil.SdfShaderLibrary
import com.android.systemui.surfaceeffects.shaderutil.ShaderUtilLibrary
/**
* Shader class that renders an expanding ripple effect. The ripple contains three elements:
- *
* 1. an expanding filled [RippleShape] that appears in the beginning and quickly fades away
* 2. an expanding ring that appears throughout the effect
* 3. an expanding ring-shaped area that reveals noise over #2.
@@ -180,6 +179,13 @@ class RippleShader(rippleShape: RippleShape = RippleShape.CIRCLE) :
return Math.min(fadeIn, fadeOut)
}
+
+ private fun lerp(start: Float, stop: Float, amount: Float): Float {
+ return start + (stop - start) * amount
+ }
+
+ // Copied from [Interpolators#STANDARD]. This is to remove dependency on AnimationLib.
+ private val STANDARD: Interpolator = PathInterpolator(0.2f, 0f, 0f, 1f)
}
/** Sets the center position of the ripple. */
@@ -207,7 +213,7 @@ class RippleShader(rippleShape: RippleShape = RippleShape.CIRCLE) :
var rawProgress: Float = 0.0f
set(value) {
field = value
- progress = Interpolators.STANDARD.getInterpolation(value)
+ progress = STANDARD.getInterpolation(value)
setFloatUniform("in_fadeSparkle", getFade(sparkleRingFadeParams, value))
setFloatUniform("in_fadeRing", getFade(baseRingFadeParams, value))
@@ -228,8 +234,7 @@ class RippleShader(rippleShape: RippleShape = RippleShape.CIRCLE) :
"in_cornerRadius",
Math.min(rippleSize.currentWidth, rippleSize.currentHeight)
)
-
- setFloatUniform("in_blur", MathUtils.lerp(blurStart, blurEnd, value))
+ setFloatUniform("in_blur", lerp(1.25f, 0.5f, value))
}
/** Play time since the start of the effect. */
@@ -311,6 +316,7 @@ class RippleShader(rippleShape: RippleShape = RippleShape.CIRCLE) :
* Parameters used for fade in and outs of the ripple.
*
* <p>Note that all the fade in/ outs are "linear" progression.
+ *
* ```
* (opacity)
* 1
@@ -325,6 +331,7 @@ class RippleShader(rippleShape: RippleShape = RippleShape.CIRCLE) :
* fadeIn fadeOut
* Start & End Start & End
* ```
+ *
* <p>If no fade in/ out is needed, set [fadeInStart] and [fadeInEnd] to 0; [fadeOutStart] and
* [fadeOutEnd] to 1.
*/
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt
index 4c7c43548016..ef5ad436ec38 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt
@@ -196,7 +196,7 @@ open class RippleView(context: Context?, attrs: AttributeSet?) : View(context, a
}
animator.addListener(
object : AnimatorListenerAdapter() {
- override fun onAnimationEnd(animation: Animator?) {
+ override fun onAnimationEnd(animation: Animator) {
onAnimationEnd?.run()
}
}
@@ -221,10 +221,10 @@ open class RippleView(context: Context?, attrs: AttributeSet?) : View(context, a
/** Indicates whether the ripple animation is playing. */
fun rippleInProgress(): Boolean = animator.isRunning
- override fun onDraw(canvas: Canvas?) {
- if (canvas == null || !canvas.isHardwareAccelerated) {
- // Drawing with the ripple shader requires hardware acceleration, so skip
- // if it's unsupported.
+ override fun onDraw(canvas: Canvas) {
+ if (!canvas.isHardwareAccelerated) {
+ // Drawing with the ripple shader requires hardware acceleration, so skip if it's
+ // unsupported.
return
}
// To reduce overdraw, we mask the effect to a circle or a rectangle that's bigger than the
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
index 79bc2f432ded..89871fa7d875 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
@@ -30,12 +30,14 @@ data class TurbulenceNoiseAnimationConfig(
* Noise move speed variables.
*
* Its sign determines the direction; magnitude determines the speed. <ul>
+ *
* ```
* <li> [noiseMoveSpeedX] positive: right to left; negative: left to right.
* <li> [noiseMoveSpeedY] positive: bottom to top; negative: top to bottom.
* <li> [noiseMoveSpeedZ] its sign doesn't matter much, as it moves in Z direction. Use it
* to add turbulence in place.
* ```
+ *
* </ul>
*/
val noiseMoveSpeedX: Float = 0f,
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt
index e1e515d14771..c3e84787d4fb 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt
@@ -49,8 +49,8 @@ class TurbulenceNoiseView(context: Context?, attrs: AttributeSet?) : View(contex
@VisibleForTesting var noiseConfig: TurbulenceNoiseAnimationConfig? = null
@VisibleForTesting var currentAnimator: ValueAnimator? = null
- override fun onDraw(canvas: Canvas?) {
- if (canvas == null || !canvas.isHardwareAccelerated) {
+ override fun onDraw(canvas: Canvas) {
+ if (!canvas.isHardwareAccelerated) {
// Drawing with the turbulence noise shader requires hardware acceleration, so skip
// if it's unsupported.
return
diff --git a/packages/SystemUI/animation/src/com/android/systemui/util/AnimatorExtensions.kt b/packages/SystemUI/animation/src/com/android/systemui/util/AnimatorExtensions.kt
new file mode 100644
index 000000000000..35dbb89ad801
--- /dev/null
+++ b/packages/SystemUI/animation/src/com/android/systemui/util/AnimatorExtensions.kt
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2023 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.util
+
+import androidx.core.animation.Animator
+
+/**
+ * Add an action which will be invoked when the animation has ended.
+ *
+ * @return the [Animator.AnimatorListener] added to the Animator
+ * @see Animator.end
+ */
+inline fun Animator.doOnEnd(
+ crossinline action: (animator: Animator) -> Unit
+): Animator.AnimatorListener = addListener(onEnd = action)
+
+/**
+ * Add an action which will be invoked when the animation has started.
+ *
+ * @return the [Animator.AnimatorListener] added to the Animator
+ * @see Animator.start
+ */
+inline fun Animator.doOnStart(
+ crossinline action: (animator: Animator) -> Unit
+): Animator.AnimatorListener = addListener(onStart = action)
+
+/**
+ * Add an action which will be invoked when the animation has been cancelled.
+ *
+ * @return the [Animator.AnimatorListener] added to the Animator
+ * @see Animator.cancel
+ */
+inline fun Animator.doOnCancel(
+ crossinline action: (animator: Animator) -> Unit
+): Animator.AnimatorListener = addListener(onCancel = action)
+
+/**
+ * Add an action which will be invoked when the animation has repeated.
+ *
+ * @return the [Animator.AnimatorListener] added to the Animator
+ */
+inline fun Animator.doOnRepeat(
+ crossinline action: (animator: Animator) -> Unit
+): Animator.AnimatorListener = addListener(onRepeat = action)
+
+/**
+ * Add a listener to this Animator using the provided actions.
+ *
+ * @return the [Animator.AnimatorListener] added to the Animator
+ */
+inline fun Animator.addListener(
+ crossinline onEnd: (animator: Animator) -> Unit = {},
+ crossinline onStart: (animator: Animator) -> Unit = {},
+ crossinline onCancel: (animator: Animator) -> Unit = {},
+ crossinline onRepeat: (animator: Animator) -> Unit = {}
+): Animator.AnimatorListener {
+ val listener =
+ object : Animator.AnimatorListener {
+ override fun onAnimationRepeat(animator: Animator) = onRepeat(animator)
+ override fun onAnimationEnd(animator: Animator) = onEnd(animator)
+ override fun onAnimationCancel(animator: Animator) = onCancel(animator)
+ override fun onAnimationStart(animator: Animator) = onStart(animator)
+ }
+ addListener(listener)
+ return listener
+}
diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/DumpableNotRegisteredDetector.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/DumpableNotRegisteredDetector.kt
new file mode 100644
index 000000000000..30e2a2527a93
--- /dev/null
+++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/DumpableNotRegisteredDetector.kt
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2023 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.systemui.lint
+
+import com.android.tools.lint.detector.api.Category
+import com.android.tools.lint.detector.api.Context
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Issue
+import com.android.tools.lint.detector.api.JavaContext
+import com.android.tools.lint.detector.api.Location
+import com.android.tools.lint.detector.api.Scope
+import com.android.tools.lint.detector.api.Severity
+import com.android.tools.lint.detector.api.SourceCodeScanner
+import com.intellij.psi.PsiMethod
+import org.jetbrains.uast.UCallExpression
+import org.jetbrains.uast.UClass
+
+/**
+ * Checks if any class has implemented the `Dumpable` interface but has not registered itself with
+ * the `DumpManager`.
+ */
+@Suppress("UnstableApiUsage")
+class DumpableNotRegisteredDetector : Detector(), SourceCodeScanner {
+
+ private var isDumpable: Boolean = false
+ private var isCoreStartable: Boolean = false
+ private var hasRegisterCall: Boolean = false
+ private var classLocation: Location? = null
+
+ override fun beforeCheckFile(context: Context) {
+ isDumpable = false
+ isCoreStartable = false
+ hasRegisterCall = false
+ classLocation = null
+ }
+
+ override fun applicableSuperClasses(): List<String> {
+ return listOf(DUMPABLE_CLASS_NAME)
+ }
+
+ override fun getApplicableMethodNames(): List<String> {
+ return listOf("registerDumpable", "registerNormalDumpable", "registerCriticalDumpable")
+ }
+
+ override fun visitClass(context: JavaContext, declaration: UClass) {
+ if (declaration.isInterface || context.evaluator.isAbstract(declaration)) {
+ // Don't require interfaces or abstract classes to call `register` (assume the full
+ // implementations will call it). This also means that we correctly don't warn for the
+ // `Dumpable` interface itself.
+ return
+ }
+
+ classLocation = context.getNameLocation(declaration)
+
+ val superTypeClassNames = declaration.superTypes.mapNotNull { it.resolve()?.qualifiedName }
+ isDumpable = superTypeClassNames.contains(DUMPABLE_CLASS_NAME)
+ isCoreStartable = superTypeClassNames.contains(CORE_STARTABLE_CLASS_NAME)
+ }
+
+ override fun visitMethodCall(context: JavaContext, node: UCallExpression, method: PsiMethod) {
+ if (context.evaluator.isMemberInSubClassOf(method, DUMP_MANAGER_CLASS_NAME)) {
+ hasRegisterCall = true
+ }
+ }
+
+ override fun afterCheckFile(context: Context) {
+ if (!isDumpable) {
+ return
+ }
+ if (isDumpable && isCoreStartable) {
+ // CoreStartables will be automatically registered, so classes that implement
+ // CoreStartable do not need a `register` call.
+ return
+ }
+
+ if (!hasRegisterCall) {
+ context.report(
+ issue = ISSUE,
+ location = classLocation!!,
+ message =
+ "Any class implementing `Dumpable` must call " +
+ "`DumpManager.registerNormalDumpable` or " +
+ "`DumpManager.registerCriticalDumpable`",
+ )
+ }
+ }
+
+ companion object {
+ @JvmField
+ val ISSUE: Issue =
+ Issue.create(
+ id = "DumpableNotRegistered",
+ briefDescription = "Dumpable not registered with DumpManager.",
+ explanation =
+ """
+ This class has implemented the `Dumpable` interface, but it has not registered \
+ itself with the `DumpManager`. This means that the class will never actually \
+ be dumped. Please call `DumpManager.registerNormalDumpable` or \
+ `DumpManager.registerCriticalDumpable` in the class's constructor or \
+ initialization method.""",
+ category = Category.CORRECTNESS,
+ priority = 8,
+ severity = Severity.WARNING,
+ implementation =
+ Implementation(DumpableNotRegisteredDetector::class.java, Scope.JAVA_FILE_SCOPE)
+ )
+
+ private const val DUMPABLE_CLASS_NAME = "com.android.systemui.Dumpable"
+ private const val CORE_STARTABLE_CLASS_NAME = "com.android.systemui.CoreStartable"
+ private const val DUMP_MANAGER_CLASS_NAME = "com.android.systemui.dump.DumpManager"
+ }
+}
diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
index 254a6fb4714f..84f70502fa45 100644
--- a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
+++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
@@ -32,6 +32,7 @@ class SystemUIIssueRegistry : IssueRegistry() {
BindServiceOnMainThreadDetector.ISSUE,
BroadcastSentViaContextDetector.ISSUE,
CleanArchitectureDependencyViolationDetector.ISSUE,
+ DumpableNotRegisteredDetector.ISSUE,
SlowUserQueryDetector.ISSUE_SLOW_USER_ID_QUERY,
SlowUserQueryDetector.ISSUE_SLOW_USER_INFO_QUERY,
NonInjectedMainThreadDetector.ISSUE,
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetectorTest.kt
index a4b59fd8e086..a5f832a17de4 100644
--- a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetectorTest.kt
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetectorTest.kt
@@ -64,7 +64,8 @@ class CleanArchitectureDependencyViolationDetectorTest : SystemUILintDetectorTes
class BadClass(
private val viewModel: ViewModel,
)
- """.trimIndent()
+ """
+ .trimIndent()
)
)
.issues(
@@ -98,7 +99,8 @@ class CleanArchitectureDependencyViolationDetectorTest : SystemUILintDetectorTes
class BadClass(
private val repository: Repository,
)
- """.trimIndent()
+ """
+ .trimIndent()
)
)
.issues(
@@ -136,7 +138,8 @@ class CleanArchitectureDependencyViolationDetectorTest : SystemUILintDetectorTes
private val interactor: Interactor,
private val viewmodel: ViewModel,
)
- """.trimIndent()
+ """
+ .trimIndent()
)
)
.issues(
@@ -176,7 +179,8 @@ class CleanArchitectureDependencyViolationDetectorTest : SystemUILintDetectorTes
class BadClass(
private val interactor: Interactor,
)
- """.trimIndent()
+ """
+ .trimIndent()
)
)
.issues(
@@ -207,7 +211,8 @@ class CleanArchitectureDependencyViolationDetectorTest : SystemUILintDetectorTes
data class Model(
private val name: String,
)
- """.trimIndent()
+ """
+ .trimIndent()
)
private val REPOSITORY_FILE =
TestFiles.kotlin(
@@ -228,7 +233,8 @@ class CleanArchitectureDependencyViolationDetectorTest : SystemUILintDetectorTes
return models
}
}
- """.trimIndent()
+ """
+ .trimIndent()
)
private val INTERACTOR_FILE =
TestFiles.kotlin(
@@ -245,7 +251,8 @@ class CleanArchitectureDependencyViolationDetectorTest : SystemUILintDetectorTes
return repository.getModels()
}
}
- """.trimIndent()
+ """
+ .trimIndent()
)
private val VIEW_MODEL_FILE =
TestFiles.kotlin(
@@ -262,7 +269,8 @@ class CleanArchitectureDependencyViolationDetectorTest : SystemUILintDetectorTes
return interactor.getModels().map { model -> model.name }
}
}
- """.trimIndent()
+ """
+ .trimIndent()
)
private val NON_CLEAN_ARCHITECTURE_FILE =
TestFiles.kotlin(
@@ -282,7 +290,8 @@ class CleanArchitectureDependencyViolationDetectorTest : SystemUILintDetectorTes
)
}
}
- """.trimIndent()
+ """
+ .trimIndent()
)
private val LEGITIMATE_FILES =
arrayOf(
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DumpableNotRegisteredDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DumpableNotRegisteredDetectorTest.kt
new file mode 100644
index 000000000000..3d6cbc749569
--- /dev/null
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DumpableNotRegisteredDetectorTest.kt
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2023 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.systemui.lint
+
+import com.android.tools.lint.checks.infrastructure.TestFiles
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Issue
+import org.junit.Test
+
+@Suppress("UnstableApiUsage")
+class DumpableNotRegisteredDetectorTest : SystemUILintDetectorTest() {
+ override fun getDetector(): Detector = DumpableNotRegisteredDetector()
+
+ override fun getIssues(): List<Issue> = listOf(DumpableNotRegisteredDetector.ISSUE)
+
+ @Test
+ fun classIsNotDumpable_noViolation() {
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+
+ class SomeClass() {
+ }
+ """.trimIndent()
+ ),
+ *stubs,
+ )
+ .issues(DumpableNotRegisteredDetector.ISSUE)
+ .run()
+ .expectClean()
+ }
+
+ @Test
+ fun classIsDumpable_andRegisterIsCalled_noViolation() {
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+
+ import com.android.systemui.Dumpable;
+ import com.android.systemui.dump.DumpManager;
+
+ public class SomeClass implements Dumpable {
+ SomeClass(DumpManager dumpManager) {
+ dumpManager.registerDumpable(this);
+ }
+
+ @Override
+ void dump(PrintWriter pw, String[] args) {
+ pw.println("testDump");
+ }
+ }
+ """.trimIndent()
+ ),
+ *stubs,
+ )
+ .issues(DumpableNotRegisteredDetector.ISSUE)
+ .run()
+ .expectClean()
+ }
+
+ @Test
+ fun classIsDumpable_andRegisterNormalIsCalled_noViolation() {
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+
+ import com.android.systemui.Dumpable;
+ import com.android.systemui.dump.DumpManager;
+
+ public class SomeClass implements Dumpable {
+ SomeClass(DumpManager dumpManager) {
+ dumpManager.registerNormalDumpable(this);
+ }
+
+ @Override
+ void dump(PrintWriter pw, String[] args) {
+ pw.println("testDump");
+ }
+ }
+ """.trimIndent()
+ ),
+ *stubs,
+ )
+ .issues(DumpableNotRegisteredDetector.ISSUE)
+ .run()
+ .expectClean()
+ }
+
+ @Test
+ fun classIsDumpable_andRegisterCriticalIsCalled_noViolation() {
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+
+ import com.android.systemui.Dumpable;
+ import com.android.systemui.dump.DumpManager;
+
+ public class SomeClass implements Dumpable {
+ SomeClass(DumpManager dumpManager) {
+ dumpManager.registerCriticalDumpable(this);
+ }
+
+ @Override
+ void dump(PrintWriter pw, String[] args) {
+ pw.println("testDump");
+ }
+ }
+ """.trimIndent()
+ ),
+ *stubs,
+ )
+ .issues(DumpableNotRegisteredDetector.ISSUE)
+ .run()
+ .expectClean()
+ }
+
+ @Test
+ fun classIsDumpable_noRegister_violation() {
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+
+ import com.android.systemui.Dumpable;
+
+ public class SomeClass implements Dumpable {
+ @Override
+ public void dump() {
+ }
+ }
+ """
+ )
+ .indented(),
+ *stubs,
+ )
+ .issues(DumpableNotRegisteredDetector.ISSUE)
+ .run()
+ .expect(
+ ("""
+ src/test/pkg/SomeClass.java:5: Warning: Any class implementing Dumpable must call DumpManager.registerNormalDumpable or DumpManager.registerCriticalDumpable [DumpableNotRegistered]
+ public class SomeClass implements Dumpable {
+ ~~~~~~~~~
+ 0 errors, 1 warnings
+ """)
+ .trimIndent()
+ )
+ }
+
+ @Test
+ fun classIsDumpable_usesNotDumpManagerMethod_violation() {
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+
+ import com.android.systemui.Dumpable;
+ import com.android.systemui.OtherRegistrationObject;
+
+ public class SomeClass implements Dumpable {
+ public SomeClass(OtherRegistrationObject otherRegistrationObject) {
+ otherRegistrationObject.registerDumpable(this);
+ }
+ @Override
+ public void dump() {
+ }
+ }
+ """
+ )
+ .indented(),
+ *stubs,
+ )
+ .issues(DumpableNotRegisteredDetector.ISSUE)
+ .run()
+ .expect(
+ ("""
+ src/test/pkg/SomeClass.java:6: Warning: Any class implementing Dumpable must call DumpManager.registerNormalDumpable or DumpManager.registerCriticalDumpable [DumpableNotRegistered]
+ public class SomeClass implements Dumpable {
+ ~~~~~~~~~
+ 0 errors, 1 warnings
+ """)
+ .trimIndent()
+ )
+ }
+
+ @Test
+ fun classIsDumpableAndCoreStartable_noRegister_noViolation() {
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+
+ import com.android.systemui.Dumpable;
+ import com.android.systemui.CoreStartable;
+
+ public class SomeClass implements Dumpable, CoreStartable {
+ @Override
+ public void start() {
+ }
+
+ @Override
+ public void dump() {
+ }
+ }
+ """
+ )
+ .indented(),
+ *stubs,
+ )
+ .issues(DumpableNotRegisteredDetector.ISSUE)
+ .run()
+ .expectClean()
+ }
+
+ @Test
+ fun classIsAbstract_noRegister_noViolation() {
+ lint()
+ .files(
+ TestFiles.java(
+ """
+ package test.pkg;
+
+ import com.android.systemui.Dumpable;
+
+ public abstract class SomeClass implements Dumpable {
+ void abstractMethodHere();
+
+ @Override
+ public void dump() {
+ }
+ }
+ """
+ )
+ .indented(),
+ *stubs,
+ )
+ .issues(DumpableNotRegisteredDetector.ISSUE)
+ .run()
+ .expectClean()
+ }
+
+ companion object {
+ private val DUMPABLE_STUB =
+ TestFiles.java(
+ """
+ package com.android.systemui;
+
+ import com.android.systemui.dump.DumpManager;
+ import java.io.PrintWriter;
+
+ public interface Dumpable {
+ void dump();
+ }
+ """
+ )
+ .indented()
+
+ private val DUMP_MANAGER_STUB =
+ TestFiles.java(
+ """
+ package com.android.systemui.dump;
+
+ public interface DumpManager {
+ void registerDumpable(Dumpable module);
+ void registerNormalDumpable(Dumpable module);
+ void registerCriticalDumpable(Dumpable module);
+ }
+ """
+ )
+ .indented()
+
+ private val OTHER_REGISTRATION_OBJECT_STUB =
+ TestFiles.java(
+ """
+ package com.android.systemui;
+
+ public interface OtherRegistrationObject {
+ void registerDumpable(Dumpable module);
+ }
+ """
+ )
+ .indented()
+
+ private val CORE_STARTABLE_STUB =
+ TestFiles.java(
+ """
+ package com.android.systemui;
+
+ public interface CoreStartable {
+ void start();
+ }
+ """
+ )
+ .indented()
+
+ private val stubs =
+ arrayOf(
+ DUMPABLE_STUB,
+ DUMP_MANAGER_STUB,
+ OTHER_REGISTRATION_OBJECT_STUB,
+ CORE_STARTABLE_STUB,
+ )
+ }
+}
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/SystemUiController.kt b/packages/SystemUI/compose/core/src/com/android/compose/SystemUiController.kt
index a02954ab4800..08ab1462b161 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/SystemUiController.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/SystemUiController.kt
@@ -78,11 +78,10 @@ interface SystemUiController {
* Set the status bar color.
*
* @param color The **desired** [Color] to set. This may require modification if running on an
- * API level that only supports white status bar icons.
+ * API level that only supports white status bar icons.
* @param darkIcons Whether dark status bar icons would be preferable.
* @param transformColorForLightContent A lambda which will be invoked to transform [color] if
- * dark icons were requested but are not available. Defaults to applying a black scrim.
- *
+ * dark icons were requested but are not available. Defaults to applying a black scrim.
* @see statusBarDarkContentEnabled
*/
fun setStatusBarColor(
@@ -95,16 +94,15 @@ interface SystemUiController {
* Set the navigation bar color.
*
* @param color The **desired** [Color] to set. This may require modification if running on an
- * API level that only supports white navigation bar icons. Additionally this will be ignored
- * and [Color.Transparent] will be used on API 29+ where gesture navigation is preferred or the
- * system UI automatically applies background protection in other navigation modes.
+ * API level that only supports white navigation bar icons. Additionally this will be ignored
+ * and [Color.Transparent] will be used on API 29+ where gesture navigation is preferred or
+ * the system UI automatically applies background protection in other navigation modes.
* @param darkIcons Whether dark navigation bar icons would be preferable.
* @param navigationBarContrastEnforced Whether the system should ensure that the navigation bar
- * has enough contrast when a fully transparent background is requested. Only supported on API
- * 29+.
+ * has enough contrast when a fully transparent background is requested. Only supported on API
+ * 29+.
* @param transformColorForLightContent A lambda which will be invoked to transform [color] if
- * dark icons were requested but are not available. Defaults to applying a black scrim.
- *
+ * dark icons were requested but are not available. Defaults to applying a black scrim.
* @see navigationBarDarkContentEnabled
* @see navigationBarContrastEnforced
*/
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt b/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt
index cfc38df08b0a..d4a81f9c765d 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt
@@ -255,7 +255,9 @@ fun Expandable(
.onGloballyPositioned {
controller.boundsInComposeViewRoot.value = it.boundsInRoot()
}
- ) { wrappedContent(controller.expandable) }
+ ) {
+ wrappedContent(controller.expandable)
+ }
}
else -> {
val clickModifier =
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt b/packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt
index edb10c7d392f..767756e17747 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt
@@ -156,9 +156,9 @@ internal class ExpandableControllerImpl(
* Create a [LaunchAnimator.Controller] that is going to be used to drive an activity or dialog
* animation. This controller will:
* 1. Compute the start/end animation state using [boundsInComposeViewRoot] and the location of
- * composeViewRoot on the screen.
+ * composeViewRoot on the screen.
* 2. Update [animatorState] with the current animation state if we are animating, or null
- * otherwise.
+ * otherwise.
*/
private fun launchController(): LaunchAnimator.Controller {
return object : LaunchAnimator.Controller {
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/pager/Pager.kt b/packages/SystemUI/compose/core/src/com/android/compose/pager/Pager.kt
index eb9d62506faa..a80a1f934dab 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/pager/Pager.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/pager/Pager.kt
@@ -86,21 +86,20 @@ object PagerDefaults {
/**
* A horizontally scrolling layout that allows users to flip between items to the left and right.
*
- * @sample com.google.accompanist.sample.pager.HorizontalPagerSample
- *
* @param count the number of pages.
* @param modifier the modifier to apply to this layout.
* @param state the state object to be used to control or observe the pager's state.
* @param reverseLayout reverse the direction of scrolling and layout, when `true` items will be
- * composed from the end to the start and [PagerState.currentPage] == 0 will mean the first item is
- * located at the end.
+ * composed from the end to the start and [PagerState.currentPage] == 0 will mean the first item
+ * is located at the end.
* @param itemSpacing horizontal spacing to add between items.
* @param flingBehavior logic describing fling behavior.
* @param key the scroll position will be maintained based on the key, which means if you add/remove
- * items before the current visible item the item with the given key will be kept as the first
- * visible one.
+ * items before the current visible item the item with the given key will be kept as the first
+ * visible one.
* @param content a block which describes the content. Inside this block you can reference
- * [PagerScope.currentPage] and other properties in [PagerScope].
+ * [PagerScope.currentPage] and other properties in [PagerScope].
+ * @sample com.google.accompanist.sample.pager.HorizontalPagerSample
*/
@ExperimentalPagerApi
@Composable
@@ -134,21 +133,20 @@ fun HorizontalPager(
/**
* A vertically scrolling layout that allows users to flip between items to the top and bottom.
*
- * @sample com.google.accompanist.sample.pager.VerticalPagerSample
- *
* @param count the number of pages.
* @param modifier the modifier to apply to this layout.
* @param state the state object to be used to control or observe the pager's state.
* @param reverseLayout reverse the direction of scrolling and layout, when `true` items will be
- * composed from the bottom to the top and [PagerState.currentPage] == 0 will mean the first item is
- * located at the bottom.
+ * composed from the bottom to the top and [PagerState.currentPage] == 0 will mean the first item
+ * is located at the bottom.
* @param itemSpacing vertical spacing to add between items.
* @param flingBehavior logic describing fling behavior.
* @param key the scroll position will be maintained based on the key, which means if you add/remove
- * items before the current visible item the item with the given key will be kept as the first
- * visible one.
+ * items before the current visible item the item with the given key will be kept as the first
+ * visible one.
* @param content a block which describes the content. Inside this block you can reference
- * [PagerScope.currentPage] and other properties in [PagerScope].
+ * [PagerScope.currentPage] and other properties in [PagerScope].
+ * @sample com.google.accompanist.sample.pager.VerticalPagerSample
*/
@ExperimentalPagerApi
@Composable
@@ -246,7 +244,9 @@ internal fun Pager(
// Constraint the content to be <= than the size of the pager.
.fillParentMaxHeight()
.wrapContentSize()
- ) { pagerScope.content(page) }
+ ) {
+ pagerScope.content(page)
+ }
}
}
} else {
@@ -272,7 +272,9 @@ internal fun Pager(
// Constraint the content to be <= than the size of the pager.
.fillParentMaxWidth()
.wrapContentSize()
- ) { pagerScope.content(page) }
+ ) {
+ pagerScope.content(page)
+ }
}
}
}
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/pager/PagerState.kt b/packages/SystemUI/compose/core/src/com/android/compose/pager/PagerState.kt
index 2e6ae78b43c7..1822a68f1e77 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/pager/PagerState.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/pager/PagerState.kt
@@ -198,7 +198,7 @@ class PagerState(
*
* @param page the page to animate to. Must be between 0 and [pageCount] (inclusive).
* @param pageOffset the percentage of the page width to offset, from the start of [page]. Must
- * be in the range 0f..1f.
+ * be in the range 0f..1f.
*/
suspend fun animateScrollToPage(
@IntRange(from = 0) page: Int,
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/pager/SnappingFlingBehavior.kt b/packages/SystemUI/compose/core/src/com/android/compose/pager/SnappingFlingBehavior.kt
index 23122de56758..98140295306a 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/pager/SnappingFlingBehavior.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/pager/SnappingFlingBehavior.kt
@@ -44,11 +44,11 @@ internal object SnappingFlingBehaviorDefaults {
/**
* Create and remember a snapping [FlingBehavior] to be used with [LazyListState].
*
- * TODO: move this to a new module and make it public
- *
* @param lazyListState The [LazyListState] to update.
* @param decayAnimationSpec The decay animation spec to use for decayed flings.
* @param snapAnimationSpec The animation spec to use when snapping.
+ *
+ * TODO: move this to a new module and make it public
*/
@Composable
internal fun rememberSnappingFlingBehavior(
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreen.kt b/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreen.kt
index 3eeadae5385f..a74e56b6e2f2 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreen.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreen.kt
@@ -60,7 +60,7 @@ import com.android.systemui.people.ui.viewmodel.PeopleViewModel
*
* @param viewModel the [PeopleViewModel] that should be composed.
* @param onResult the callback called with the result of this screen. Callers should usually finish
- * the Activity/Fragment/View hosting this Composable once a result is available.
+ * the Activity/Fragment/View hosting this Composable once a result is available.
*/
@Composable
fun PeopleScreen(
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreenEmpty.kt b/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreenEmpty.kt
index 3f590df697cb..0484ff475cdf 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreenEmpty.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreenEmpty.kt
@@ -79,7 +79,9 @@ internal fun PeopleScreenEmpty(
containerColor = androidColors.colorAccentPrimary,
contentColor = androidColors.textColorOnAccent,
)
- ) { Text(stringResource(R.string.got_it)) }
+ ) {
+ Text(stringResource(R.string.got_it))
+ }
}
}
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
index ab36d5899739..00c0a0b3e7b3 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
@@ -38,6 +38,7 @@ import kotlinx.coroutines.launch
private val TAG = ClockRegistry::class.simpleName!!
private const val DEBUG = true
+private val KEY_TIMESTAMP = "appliedTimestamp"
/** ClockRegistry aggregates providers and plugins */
open class ClockRegistry(
@@ -134,9 +135,9 @@ open class ClockRegistry(
assertNotMainThread()
try {
- value?._applied_timestamp = System.currentTimeMillis()
- val json = ClockSettings.serialize(value)
+ value?.metadata?.put(KEY_TIMESTAMP, System.currentTimeMillis())
+ val json = ClockSettings.serialize(value)
if (handleAllUsers) {
Settings.Secure.putStringForUser(
context.contentResolver,
@@ -172,7 +173,7 @@ open class ClockRegistry(
clockChangeListeners.forEach(func)
}
- private fun mutateSetting(mutator: (ClockSettings) -> ClockSettings) {
+ public fun mutateSetting(mutator: (ClockSettings) -> ClockSettings) {
scope.launch(bgDispatcher) { applySettings(mutator(settings ?: ClockSettings())) }
}
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
index 2a40f5c70420..4df7a44d3e1d 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
@@ -95,7 +95,7 @@ class DefaultClockController(
open inner class DefaultClockFaceController(
override val view: AnimatableClockView,
- val seedColor: Int?,
+ var seedColor: Int?,
) : ClockFaceController {
// MAGENTA is a placeholder, and will be assigned correctly in initialize
@@ -111,9 +111,9 @@ class DefaultClockController(
init {
if (seedColor != null) {
- currentColor = seedColor
+ currentColor = seedColor!!
}
- view.setColors(currentColor, currentColor)
+ view.setColors(DOZE_COLOR, currentColor)
}
override val events =
@@ -141,7 +141,7 @@ class DefaultClockController(
fun updateColor() {
val color =
if (seedColor != null) {
- seedColor
+ seedColor!!
} else if (isRegionDark) {
resources.getColor(android.R.color.system_accent1_100)
} else {
@@ -194,6 +194,14 @@ class DefaultClockController(
smallClock.updateColor()
}
+ override fun onSeedColorChanged(seedColor: Int?) {
+ largeClock.seedColor = seedColor
+ smallClock.seedColor = seedColor
+
+ largeClock.updateColor()
+ smallClock.updateColor()
+ }
+
override fun onLocaleChanged(locale: Locale) {
val nf = NumberFormat.getInstance(locale)
if (nf.format(FORMAT_NUMBER.toLong()) == burmeseNumerals) {
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderContract.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderContract.kt
index c120876a7a63..0d880759bd09 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderContract.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/customization/data/content/CustomizationProviderContract.kt
@@ -51,7 +51,7 @@ object CustomizationProviderContract {
*
* Supported operations:
* - Query - to know which slots are available, query the [SlotTable.URI] [Uri]. The result
- * set will contain rows with the [SlotTable.Columns] columns.
+ * set will contain rows with the [SlotTable.Columns] columns.
*/
object SlotTable {
const val TABLE_NAME = "slots"
@@ -74,8 +74,8 @@ object CustomizationProviderContract {
*
* Supported operations:
* - Query - to know about all the affordances that are available on the device, regardless
- * of which ones are currently selected, query the [AffordanceTable.URI] [Uri]. The result
- * set will contain rows, each with the columns specified in [AffordanceTable.Columns].
+ * of which ones are currently selected, query the [AffordanceTable.URI] [Uri]. The result
+ * set will contain rows, each with the columns specified in [AffordanceTable.Columns].
*/
object AffordanceTable {
const val TABLE_NAME = "affordances"
@@ -128,14 +128,14 @@ object CustomizationProviderContract {
*
* Supported operations:
* - Insert - to insert an affordance and place it in a slot, insert values for the columns
- * into the [SelectionTable.URI] [Uri]. The maximum capacity rule is enforced by the system.
- * Selecting a new affordance for a slot that is already full will automatically remove the
- * oldest affordance from the slot.
+ * into the [SelectionTable.URI] [Uri]. The maximum capacity rule is enforced by the
+ * system. Selecting a new affordance for a slot that is already full will automatically
+ * remove the oldest affordance from the slot.
* - Query - to know which affordances are set on which slots, query the
- * [SelectionTable.URI] [Uri]. The result set will contain rows, each of which with the
- * columns from [SelectionTable.Columns].
+ * [SelectionTable.URI] [Uri]. The result set will contain rows, each of which with the
+ * columns from [SelectionTable.Columns].
* - Delete - to unselect an affordance, removing it from a slot, delete from the
- * [SelectionTable.URI] [Uri], passing in values for each column.
+ * [SelectionTable.URI] [Uri], passing in values for each column.
*/
object SelectionTable {
const val TABLE_NAME = "selections"
@@ -160,7 +160,7 @@ object CustomizationProviderContract {
*
* Supported operations:
* - Query - to know the values of flags, query the [FlagsTable.URI] [Uri]. The result set will
- * contain rows, each of which with the columns from [FlagsTable.Columns].
+ * contain rows, each of which with the columns from [FlagsTable.Columns].
*/
object FlagsTable {
const val TABLE_NAME = "flags"
diff --git a/packages/SystemUI/ktfmt_includes.txt b/packages/SystemUI/ktfmt_includes.txt
index ec860b58bb4a..18753fd9c0c7 100644
--- a/packages/SystemUI/ktfmt_includes.txt
+++ b/packages/SystemUI/ktfmt_includes.txt
@@ -1,28 +1,20 @@
+packages/SystemUI
-packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt
-packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt
--packages/SystemUI/checks/src/com/android/internal/systemui/lint/BindServiceViaContextDetector.kt
-packages/SystemUI/checks/src/com/android/internal/systemui/lint/BroadcastSentViaContextDetector.kt
--packages/SystemUI/checks/src/com/android/internal/systemui/lint/GetMainLooperViaContextDetector.kt
-packages/SystemUI/checks/src/com/android/internal/systemui/lint/RegisterReceiverViaContextDetector.kt
-packages/SystemUI/checks/src/com/android/internal/systemui/lint/SoftwareBitmapDetector.kt
--packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
--packages/SystemUI/checks/tests/com/android/systemui/lint/BindServiceViaContextDetectorTest.kt
--packages/SystemUI/checks/tests/com/android/systemui/lint/BroadcastSentViaContextDetectorTest.kt
--packages/SystemUI/checks/tests/com/android/systemui/lint/GetMainLooperViaContextDetectorTest.kt
--packages/SystemUI/checks/tests/com/android/systemui/lint/RegisterReceiverViaContextDetectorTest.kt
--packages/SystemUI/checks/tests/com/android/systemui/lint/SoftwareBitmapDetectorTest.kt
+-packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
+-packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
-packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
--packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSContainerController.kt
+-packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/View.kt
-packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt
-packages/SystemUI/shared/src/com/android/systemui/flags/FlagListenable.kt
-packages/SystemUI/shared/src/com/android/systemui/flags/FlagManager.kt
-packages/SystemUI/shared/src/com/android/systemui/flags/FlagSerializer.kt
-packages/SystemUI/shared/src/com/android/systemui/flags/FlagSettingsHelper.kt
-packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt
--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
+-packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionDarkness.kt
-packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButtonPositionCalculator.kt
-packages/SystemUI/shared/src/com/android/systemui/shared/system/UncaughtExceptionPreHandlerManager.kt
-packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/SmartspaceState.kt
@@ -35,8 +27,6 @@
-packages/SystemUI/src/com/android/keyguard/BouncerPanelExpansionCalculator.kt
-packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
-packages/SystemUI/src/com/android/keyguard/KeyguardBiometricLockoutLogger.kt
--packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
--packages/SystemUI/src/com/android/keyguard/KeyguardListenQueue.kt
-packages/SystemUI/src/com/android/keyguard/KeyguardUnfoldTransition.kt
-packages/SystemUI/src/com/android/keyguard/KeyguardUserSwitcherAnchor.kt
-packages/SystemUI/src/com/android/keyguard/clock/ClockPalette.kt
@@ -65,12 +55,10 @@
-packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceView.kt
-packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
-packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.kt
--packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricIconController.kt
-packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
-packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
-packages/SystemUI/src/com/android/systemui/biometrics/BiometricDisplayListener.kt
-packages/SystemUI/src/com/android/systemui/biometrics/DwellRippleShader.kt
--packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.kt
-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationViewController.kt
-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpView.kt
-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpViewController.kt
@@ -80,7 +68,6 @@
-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpmEmptyView.kt
-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpmEmptyViewController.kt
-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsHapticsSimulator.kt
--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsOverlayParams.kt
-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsShell.kt
-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.kt
-packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt
@@ -93,8 +80,6 @@
-packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
-packages/SystemUI/src/com/android/systemui/broadcast/logging/BroadcastDispatcherLogger.kt
-packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt
--packages/SystemUI/src/com/android/systemui/camera/CameraIntents.kt
--packages/SystemUI/src/com/android/systemui/camera/CameraIntentsWrapper.kt
-packages/SystemUI/src/com/android/systemui/charging/WiredChargingRippleController.kt
-packages/SystemUI/src/com/android/systemui/controls/ControlStatus.kt
-packages/SystemUI/src/com/android/systemui/controls/ControlsMetricsLogger.kt
@@ -102,7 +87,6 @@
-packages/SystemUI/src/com/android/systemui/controls/ControlsServiceInfo.kt
-packages/SystemUI/src/com/android/systemui/controls/CustomIconCache.kt
-packages/SystemUI/src/com/android/systemui/controls/TooltipManager.kt
--packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt
-packages/SystemUI/src/com/android/systemui/controls/controller/ControlInfo.kt
-packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingController.kt
-packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
@@ -132,6 +116,7 @@
-packages/SystemUI/src/com/android/systemui/controls/management/FavoritesModel.kt
-packages/SystemUI/src/com/android/systemui/controls/management/ManagementPageIndicator.kt
-packages/SystemUI/src/com/android/systemui/controls/management/StructureAdapter.kt
+-packages/SystemUI/src/com/android/systemui/controls/start/ControlsStartable.kt
-packages/SystemUI/src/com/android/systemui/controls/ui/Behavior.kt
-packages/SystemUI/src/com/android/systemui/controls/ui/ChallengeDialogs.kt
-packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinator.kt
@@ -162,7 +147,6 @@
-packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderImpl.kt
-packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt
-packages/SystemUI/src/com/android/systemui/demomode/DemoModeAvailabilityTracker.kt
--packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt
-packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt
-packages/SystemUI/src/com/android/systemui/doze/util/BurnInHelper.kt
-packages/SystemUI/src/com/android/systemui/dreams/smartspace/DreamSmartspaceController.kt
@@ -172,20 +156,16 @@
-packages/SystemUI/src/com/android/systemui/dump/LogBufferEulogizer.kt
-packages/SystemUI/src/com/android/systemui/dump/LogBufferFreezer.kt
-packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.kt
+-packages/SystemUI/src/com/android/systemui/flags/Flags.kt
-packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt
-packages/SystemUI/src/com/android/systemui/flags/SystemPropertiesHelper.kt
-packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
--packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt
+-packages/SystemUI/src/com/android/systemui/keyguard/LifecycleScreenStatusProvider.kt
+-packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfig.kt
+-packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceCoreStartable.kt
+-packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
-packages/SystemUI/src/com/android/systemui/log/LogBufferFactory.kt
--packages/SystemUI/src/com/android/systemui/log/LogLevel.kt
--packages/SystemUI/src/com/android/systemui/log/LogMessage.kt
--packages/SystemUI/src/com/android/systemui/log/LogMessageImpl.kt
--packages/SystemUI/src/com/android/systemui/log/LogcatEchoTracker.kt
--packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerDebug.kt
--packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerProd.kt
--packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
-packages/SystemUI/src/com/android/systemui/media/MediaProjectionCaptureTarget.kt
--packages/SystemUI/src/com/android/systemui/media/dagger/MediaProjectionModule.kt
-packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogFactory.kt
-packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt
-packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogReceiver.kt
@@ -202,9 +182,15 @@
-packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt
-packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt
-packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderUiEventLogger.kt
+-packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorResultHandler.kt
+-packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewController.kt
+-packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionTaskView.kt
+-packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/RecentTasksAdapter.kt
+-packages/SystemUI/src/com/android/systemui/mediaprojection/devicepolicy/ScreenCaptureDevicePolicyResolver.kt
-packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt
-packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
-packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt
+-packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEventLogger.kt
-packages/SystemUI/src/com/android/systemui/power/BatteryStateSnapshot.kt
-packages/SystemUI/src/com/android/systemui/privacy/AppOpsPrivacyItemMonitor.kt
-packages/SystemUI/src/com/android/systemui/privacy/MediaProjectionPrivacyItemMonitor.kt
@@ -220,8 +206,6 @@
-packages/SystemUI/src/com/android/systemui/privacy/logging/PrivacyLogger.kt
-packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.kt
-packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
--packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt
--packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt
-packages/SystemUI/src/com/android/systemui/qs/HeaderPrivacyIconsController.kt
-packages/SystemUI/src/com/android/systemui/qs/QSEvents.kt
-packages/SystemUI/src/com/android/systemui/qs/QSExpansionPathInterpolator.kt
@@ -237,7 +221,6 @@
-packages/SystemUI/src/com/android/systemui/qs/external/TileRequestDialog.kt
-packages/SystemUI/src/com/android/systemui/qs/external/TileRequestDialogEventLogger.kt
-packages/SystemUI/src/com/android/systemui/qs/external/TileServiceRequestController.kt
--packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt
-packages/SystemUI/src/com/android/systemui/qs/tileimpl/HeightOverrideable.kt
-packages/SystemUI/src/com/android/systemui/qs/tileimpl/IgnorableChildLinearLayout.kt
-packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
@@ -245,10 +228,6 @@
-packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt
-packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt
-packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt
--packages/SystemUI/src/com/android/systemui/ripple/RippleShader.kt
--packages/SystemUI/src/com/android/systemui/ripple/RippleShaderUtilLibrary.kt
--packages/SystemUI/src/com/android/systemui/ripple/RippleView.kt
--packages/SystemUI/src/com/android/systemui/ripple/SdfShaderLibrary.kt
-packages/SystemUI/src/com/android/systemui/screenshot/ImageCaptureImpl.kt
-packages/SystemUI/src/com/android/systemui/screenshot/RequestProcessor.kt
-packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicy.kt
@@ -259,23 +238,21 @@
-packages/SystemUI/src/com/android/systemui/settings/UserContentResolverProvider.kt
-packages/SystemUI/src/com/android/systemui/settings/UserContextProvider.kt
-packages/SystemUI/src/com/android/systemui/settings/UserFileManager.kt
--packages/SystemUI/src/com/android/systemui/settings/UserFileManagerImpl.kt
-packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
-packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
-packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessMirrorHandler.kt
-packages/SystemUI/src/com/android/systemui/settings/brightness/MirroredBrightnessController.kt
-packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManager.kt
-packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManagerImpl.kt
--packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt
-packages/SystemUI/src/com/android/systemui/shade/NPVCDownEventState.kt
--packages/SystemUI/src/com/android/systemui/shade/NotifPanelEvents.kt
-packages/SystemUI/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationController.kt
-packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt
-packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt
+-packages/SystemUI/src/com/android/systemui/shade/ShadeHeightLogger.kt
-packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
+-packages/SystemUI/src/com/android/systemui/shade/ShadeWindowLogger.kt
-packages/SystemUI/src/com/android/systemui/shade/transition/ScrimShadeTransitionController.kt
-packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt
--packages/SystemUI/src/com/android/systemui/shade/transition/SplitShadeOverScroller.kt
-packages/SystemUI/src/com/android/systemui/smartspace/SmartspacePrecondition.kt
-packages/SystemUI/src/com/android/systemui/smartspace/SmartspaceTargetFilter.kt
-packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceModule.kt
@@ -284,9 +261,7 @@
-packages/SystemUI/src/com/android/systemui/smartspace/preconditions/LockscreenPrecondition.kt
-packages/SystemUI/src/com/android/systemui/statusbar/AbstractLockscreenShadeTransitionController.kt
-packages/SystemUI/src/com/android/systemui/statusbar/ActionClickLogger.kt
--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBarWifiView.kt
-packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
--packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
-packages/SystemUI/src/com/android/systemui/statusbar/LockScreenShadeOverScroller.kt
-packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeKeyguardTransitionController.kt
-packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeScrimTransitionController.kt
@@ -311,10 +286,12 @@
-packages/SystemUI/src/com/android/systemui/statusbar/dagger/StartCentralSurfacesModule.kt
-packages/SystemUI/src/com/android/systemui/statusbar/disableflags/DisableFlagsLogger.kt
-packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/events/StatusBarEventsModule.kt
-packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt
-packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt
-packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt
-packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImpl.kt
-packages/SystemUI/src/com/android/systemui/statusbar/gesture/GenericGestureDetector.kt
-packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeUpGestureHandler.kt
-packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeUpGestureLogger.kt
@@ -325,7 +302,6 @@
-packages/SystemUI/src/com/android/systemui/statusbar/notification/LaunchAnimationParameters.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClickerLogger.kt
--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManagerLogger.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.kt
@@ -403,6 +379,7 @@
-packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinderLogger.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryViewWalker.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/people/NotificationPersonExtractor.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/people/ViewPipeline.kt
@@ -444,13 +421,10 @@
-packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
-packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallFlags.kt
-packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallLogger.kt
--packages/SystemUI/src/com/android/systemui/statusbar/phone/panelstate/PanelExpansionStateManager.kt
--packages/SystemUI/src/com/android/systemui/statusbar/phone/panelstate/ShadeStateListener.kt
--packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserInfoTracker.kt
-packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherContainer.kt
--packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherController.kt
--packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherFeatureController.kt
-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/model/ConnectivitySlots.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiView.kt
-packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateNotifier.kt
-packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsController.kt
-packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImpl.kt
@@ -470,19 +444,17 @@
-packages/SystemUI/src/com/android/systemui/statusbar/tv/VpnStatusObserver.kt
-packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowModule.kt
-packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowStateController.kt
--packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewInfo.kt
-packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt
+-packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewInfo.kt
-packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarRootView.kt
-packages/SystemUI/src/com/android/systemui/toast/ToastDefaultAnimation.kt
-packages/SystemUI/src/com/android/systemui/toast/ToastLogger.kt
-packages/SystemUI/src/com/android/systemui/tv/TVSystemUICoreStartableModule.kt
+-packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt
-packages/SystemUI/src/com/android/systemui/unfold/FoldStateLogger.kt
-packages/SystemUI/src/com/android/systemui/unfold/SysUIUnfoldModule.kt
--packages/SystemUI/src/com/android/systemui/unfold/UnfoldLatencyTracker.kt
-packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt
-packages/SystemUI/src/com/android/systemui/unfold/UnfoldProgressProvider.kt
--packages/SystemUI/src/com/android/systemui/user/UserCreator.kt
--packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt
-packages/SystemUI/src/com/android/systemui/user/UserSwitcherPopupMenu.kt
-packages/SystemUI/src/com/android/systemui/user/UserSwitcherRootView.kt
-packages/SystemUI/src/com/android/systemui/util/AsyncActivityLauncher.kt
@@ -509,7 +481,6 @@
-packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayout.kt
-packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayoutController.kt
-packages/SystemUI/src/com/android/systemui/util/animation/UniqueObjectHostView.kt
--packages/SystemUI/src/com/android/systemui/util/collection/RingBuffer.kt
-packages/SystemUI/src/com/android/systemui/util/concurrency/Execution.kt
-packages/SystemUI/src/com/android/systemui/util/concurrency/PendingTasksContainer.kt
-packages/SystemUI/src/com/android/systemui/util/drawable/DrawableSize.kt
@@ -517,6 +488,7 @@
-packages/SystemUI/src/com/android/systemui/util/kotlin/Flow.kt
-packages/SystemUI/src/com/android/systemui/util/kotlin/IpcSerializer.kt
-packages/SystemUI/src/com/android/systemui/util/kotlin/nullability.kt
+-packages/SystemUI/src/com/android/systemui/util/recycler/HorizontalSpacerItemDecoration.kt
-packages/SystemUI/src/com/android/systemui/util/view/ViewUtil.kt
-packages/SystemUI/src/com/android/systemui/util/wrapper/RotationPolicyWrapper.kt
-packages/SystemUI/src/com/android/systemui/volume/VolumePanelDialogReceiver.kt
@@ -525,7 +497,6 @@
-packages/SystemUI/tests/src/com/android/keyguard/BouncerPanelExpansionCalculatorTest.kt
-packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
-packages/SystemUI/tests/src/com/android/keyguard/KeyguardBiometricLockoutLoggerTest.kt
--packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt
-packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
-packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
-packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.kt
@@ -549,8 +520,6 @@
-packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt
-packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
-packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricTestExtensions.kt
--packages/SystemUI/tests/src/com/android/systemui/biometrics/SidefpsControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
-packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsViewTest.kt
-packages/SystemUI/tests/src/com/android/systemui/broadcast/ActionReceiverTest.kt
@@ -569,7 +538,6 @@
-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsFavoritePersistenceWrapperTest.kt
-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsTileResourceConfigurationImplTest.kt
--packages/SystemUI/tests/src/com/android/systemui/controls/controller/DeletionJobServiceTest.kt
-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ServiceWrapperTest.kt
-packages/SystemUI/tests/src/com/android/systemui/controls/controller/StatefulControlSubscriberTest.kt
-packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt
@@ -579,7 +547,6 @@
-packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsRequestDialogTest.kt
-packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsRequestReceiverTest.kt
-packages/SystemUI/tests/src/com/android/systemui/controls/management/FavoritesModelTest.kt
--packages/SystemUI/tests/src/com/android/systemui/controls/management/TestControlsRequestDialog.kt
-packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlViewHolderTest.kt
-packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt
-packages/SystemUI/tests/src/com/android/systemui/decor/CutoutDecorProviderFactoryTest.kt
@@ -596,13 +563,17 @@
-packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseTest.kt
-packages/SystemUI/tests/src/com/android/systemui/flags/FlagManagerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfigTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceCoreStartableTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepositoryTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt
-packages/SystemUI/tests/src/com/android/systemui/lifecycle/InstantTaskExecutorRule.kt
--packages/SystemUI/tests/src/com/android/systemui/log/LogBufferTest.kt
-packages/SystemUI/tests/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManagerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/media/nearby/NearbyMediaDevicesManagerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelperTest.kt
-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt
-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderUiEventLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt
-packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/FloatingRotationButtonPositionCalculatorTest.kt
-packages/SystemUI/tests/src/com/android/systemui/privacy/AppOpsPrivacyItemMonitorTest.kt
-packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyChipBuilderTest.kt
@@ -610,7 +581,6 @@
-packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogTest.kt
-packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/qs/HeaderPrivacyIconsControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/qs/QSContainerImplTest.kt
-packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentDisableFlagsLoggerTest.kt
@@ -641,35 +611,28 @@
-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt
-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt
--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt
-packages/SystemUI/tests/src/com/android/systemui/qs/user/UserSwitchDialogControllerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/ripple/RippleViewTest.kt
-packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordDialogTest.kt
--packages/SystemUI/tests/src/com/android/systemui/screenshot/ImageCaptureImplTest.kt
--packages/SystemUI/tests/src/com/android/systemui/screenshot/RequestProcessorTest.kt
-packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt
--packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotServiceTest.kt
--packages/SystemUI/tests/src/com/android/systemui/settings/UserFileManagerImplTest.kt
-packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
-packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt
--packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerCombinedTest.kt
--packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/shade/NotificationQSContainerControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/shade/transition/SplitShadeOverScrollerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt
-packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt
-packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shared/navigationbar/RegionSamplingHelperTest.kt
-packages/SystemUI/tests/src/com/android/systemui/shared/rotation/RotationButtonControllerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/shared/system/UncaughtExceptionPreHandlerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenAndDreamTargetFilterTest.kt
-packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenPreconditionTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/BlurUtilsTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/DragDownHelperTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/LSShadeTransitionLoggerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/LightRevealScrimTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
@@ -683,6 +646,7 @@
-packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/CommandRegistryTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImplTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/DisableFlagsLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/DisableStateTrackerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/gesture/GenericGestureDetectorTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorControllerTest.kt
@@ -719,7 +683,6 @@
-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ConfigurationControllerImplTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/FoldStateListenerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LetterboxAppearanceCalculatorTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LetterboxBackgroundProviderTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconContainerTest.kt
@@ -733,8 +696,7 @@
-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallChronometerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallLoggerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/panelstate/ShadeExpansionStateManagerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherControllerOldImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryStateNotifierTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ClockTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImplTest.kt
@@ -744,7 +706,6 @@
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisablerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SafetyControllerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerOldImplTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/VariableDateViewControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/WalletControllerImplTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/window/StatusBarWindowStateControllerTest.kt
@@ -753,40 +714,34 @@
-packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldTransitionWallpaperControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfigTest.kt
--packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt
-packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt
-packages/SystemUI/tests/src/com/android/systemui/unfold/util/FoldableTestUtils.kt
--packages/SystemUI/tests/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProviderTest.kt
-packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt
-packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt
-packages/SystemUI/tests/src/com/android/systemui/usb/UsbPermissionActivityTest.kt
-packages/SystemUI/tests/src/com/android/systemui/user/UserCreatorTest.kt
--packages/SystemUI/tests/src/com/android/systemui/user/UserSwitcherActivityTest.kt
-packages/SystemUI/tests/src/com/android/systemui/util/FakeSharedPreferencesTest.kt
-packages/SystemUI/tests/src/com/android/systemui/util/FloatingContentCoordinatorTest.kt
-packages/SystemUI/tests/src/com/android/systemui/util/ListenerSetTest.kt
-packages/SystemUI/tests/src/com/android/systemui/util/RingerModeLiveDataTest.kt
-packages/SystemUI/tests/src/com/android/systemui/util/WallpaperControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/util/animation/AnimationUtilTest.kt
--packages/SystemUI/tests/src/com/android/systemui/util/collection/RingBufferTest.kt
-packages/SystemUI/tests/src/com/android/systemui/util/drawable/DrawableSizeTest.kt
-packages/SystemUI/tests/src/com/android/systemui/util/kotlin/FlowUtilTests.kt
-packages/SystemUI/tests/src/com/android/systemui/util/kotlin/IpcSerializerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/kotlin/SuspendUtilTests.kt
-packages/SystemUI/tests/src/com/android/systemui/util/view/ViewUtilTest.kt
--packages/SystemUI/tests/utils/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt
-packages/SystemUI/tests/utils/src/com/android/systemui/flags/FakeFeatureFlags.kt
-packages/SystemUI/tests/utils/src/com/android/systemui/util/FakeSharedPreferences.kt
-packages/SystemUI/tests/utils/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt
-packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedModule.kt
-packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionProgressProvider.kt
-packages/SystemUI/unfold/src/com/android/systemui/unfold/compat/ScreenSizeFoldProvider.kt
-packages/SystemUI/unfold/src/com/android/systemui/unfold/compat/SizeScreenStatusProvider.kt
-packages/SystemUI/unfold/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfig.kt
--packages/SystemUI/unfold/src/com/android/systemui/unfold/dagger/UnfoldBackground.kt
-packages/SystemUI/unfold/src/com/android/systemui/unfold/dagger/UnfoldMain.kt
-packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
-packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
-packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt
--packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/hinge/HingeSensorAngleProvider.kt
-packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/screen/ScreenStatusProvider.kt
--packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScaleAwareTransitionProgressProvider.kt
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt b/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
index 314c736e2e44..db88b593e432 100644
--- a/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
@@ -171,7 +171,7 @@ enum class Style(internal val coreSpec: CoreSpec) {
a1 = TonalSpec(HueSource(), ChromaConstant(36.0)),
a2 = TonalSpec(HueSource(), ChromaConstant(16.0)),
a3 = TonalSpec(HueAdd(60.0), ChromaConstant(24.0)),
- n1 = TonalSpec(HueSource(), ChromaConstant(4.0)),
+ n1 = TonalSpec(HueSource(), ChromaConstant(6.0)),
n2 = TonalSpec(HueSource(), ChromaConstant(8.0))
)),
VIBRANT(CoreSpec(
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/DynamicColor.java b/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/DynamicColor.java
index 3a6b3628e937..e6b2c2f9c7ed 100644
--- a/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/DynamicColor.java
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/DynamicColor.java
@@ -350,7 +350,7 @@ public final class DynamicColor {
if (bgDynamicColor != null) {
final boolean bgHasBg =
bgDynamicColor.background != null && bgDynamicColor.background.apply(scheme)
- == null;
+ != null;
final double standardRatio =
Contrast.ratioOfTones(tone.apply(scheme), bgDynamicColor.tone.apply(scheme));
if (decreasingContrast) {
@@ -358,15 +358,15 @@ public final class DynamicColor {
Contrast.ratioOfTones(
toneMinContrast.apply(scheme),
bgDynamicColor.toneMinContrast.apply(scheme));
- minRatio = bgHasBg ? 1.0 : minContrastRatio;
+ minRatio = bgHasBg ? minContrastRatio : 1.0;
maxRatio = standardRatio;
} else {
final double maxContrastRatio =
Contrast.ratioOfTones(
toneMaxContrast.apply(scheme),
bgDynamicColor.toneMaxContrast.apply(scheme));
- minRatio = !bgHasBg ? 1.0 : min(maxContrastRatio, standardRatio);
- maxRatio = !bgHasBg ? 21.0 : max(maxContrastRatio, standardRatio);
+ minRatio = bgHasBg ? min(maxContrastRatio, standardRatio) : 1.0;
+ maxRatio = bgHasBg ? max(maxContrastRatio, standardRatio) : 21.0;
}
}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
index ab4aca569bd4..babe5700a01c 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
@@ -112,6 +112,9 @@ interface ClockEvents {
/** Call whenever the color palette should update */
fun onColorPaletteChanged(resources: Resources) {}
+ /** Call if the seed color has changed and should be updated */
+ fun onSeedColorChanged(seedColor: Int?) {}
+
/** Call whenever the weather data should update */
fun onWeatherDataChanged(data: WeatherData) {}
}
@@ -189,12 +192,13 @@ data class ClockSettings(
val clockId: ClockId? = null,
val seedColor: Int? = null,
) {
- var _applied_timestamp: Long? = null
+ // Exclude metadata from equality checks
+ var metadata: JSONObject = JSONObject()
companion object {
private val KEY_CLOCK_ID = "clockId"
private val KEY_SEED_COLOR = "seedColor"
- private val KEY_TIMESTAMP = "_applied_timestamp"
+ private val KEY_METADATA = "metadata"
fun serialize(setting: ClockSettings?): String {
if (setting == null) {
@@ -204,7 +208,7 @@ data class ClockSettings(
return JSONObject()
.put(KEY_CLOCK_ID, setting.clockId)
.put(KEY_SEED_COLOR, setting.seedColor)
- .put(KEY_TIMESTAMP, setting._applied_timestamp)
+ .put(KEY_METADATA, setting.metadata)
.toString()
}
@@ -216,11 +220,11 @@ data class ClockSettings(
val json = JSONObject(jsonStr)
val result =
ClockSettings(
- json.getString(KEY_CLOCK_ID),
+ if (!json.isNull(KEY_CLOCK_ID)) json.getString(KEY_CLOCK_ID) else null,
if (!json.isNull(KEY_SEED_COLOR)) json.getInt(KEY_SEED_COLOR) else null
)
- if (!json.isNull(KEY_TIMESTAMP)) {
- result._applied_timestamp = json.getLong(KEY_TIMESTAMP)
+ if (!json.isNull(KEY_METADATA)) {
+ result.metadata = json.getJSONObject(KEY_METADATA)
}
return result
}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogBuffer.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogBuffer.kt
index e99b2149bc1d..3e34885a6d9c 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogBuffer.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogBuffer.kt
@@ -35,7 +35,6 @@ import kotlin.math.max
* as the result of taking a bug report).
*
* You can dump the entire buffer at any time by running:
- *
* ```
* $ adb shell dumpsys activity service com.android.systemui/.SystemUIService <bufferName>
* ```
@@ -46,13 +45,11 @@ import kotlin.math.max
* locally (usually for debugging purposes).
*
* To enable logcat echoing for an entire buffer:
- *
* ```
* $ adb shell settings put global systemui/buffer/<bufferName> <level>
* ```
*
* To enable logcat echoing for a specific tag:
- *
* ```
* $ adb shell settings put global systemui/tag/<tag> <level>
* ```
@@ -64,10 +61,10 @@ import kotlin.math.max
* LogBufferFactory.
*
* @param name The name of this buffer, printed when the buffer is dumped and in some other
- * situations.
+ * situations.
* @param maxSize The maximum number of messages to keep in memory at any one time. Buffers start
- * out empty and grow up to [maxSize] as new messages are logged. Once the buffer's size reaches the
- * maximum, it behaves like a ring buffer.
+ * out empty and grow up to [maxSize] as new messages are logged. Once the buffer's size reaches
+ * the maximum, it behaves like a ring buffer.
*/
class LogBuffer
@JvmOverloads
@@ -116,22 +113,22 @@ constructor(
* initializer stored and converts it to a human-readable log message.
*
* @param tag A string of at most 23 characters, used for grouping logs into categories or
- * subjects. If this message is echoed to logcat, this will be the tag that is used.
+ * subjects. If this message is echoed to logcat, this will be the tag that is used.
* @param level Which level to log the message at, both to the buffer and to logcat if it's
- * echoed. In general, a module should split most of its logs into either INFO or DEBUG level.
- * INFO level should be reserved for information that other parts of the system might care
- * about, leaving the specifics of code's day-to-day operations to DEBUG.
+ * echoed. In general, a module should split most of its logs into either INFO or DEBUG level.
+ * INFO level should be reserved for information that other parts of the system might care
+ * about, leaving the specifics of code's day-to-day operations to DEBUG.
* @param messageInitializer A function that will be called immediately to store relevant data
- * on the log message. The value of `this` will be the LogMessage to be initialized.
+ * on the log message. The value of `this` will be the LogMessage to be initialized.
* @param messagePrinter A function that will be called if and when the message needs to be
- * dumped to logcat or a bug report. It should read the data stored by the initializer and
- * convert it to a human-readable string. The value of `this` will be the LogMessage to be
- * printed. **IMPORTANT:** The printer should ONLY ever reference fields on the LogMessage and
- * NEVER any variables in its enclosing scope. Otherwise, the runtime will need to allocate a
- * new instance of the printer for each call, thwarting our attempts at avoiding any sort of
- * allocation.
+ * dumped to logcat or a bug report. It should read the data stored by the initializer and
+ * convert it to a human-readable string. The value of `this` will be the LogMessage to be
+ * printed. **IMPORTANT:** The printer should ONLY ever reference fields on the LogMessage and
+ * NEVER any variables in its enclosing scope. Otherwise, the runtime will need to allocate a
+ * new instance of the printer for each call, thwarting our attempts at avoiding any sort of
+ * allocation.
* @param exception Provide any exception that need to be logged. This is saved as
- * [LogMessage.exception]
+ * [LogMessage.exception]
*/
@JvmOverloads
inline fun log(
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerDebug.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerDebug.kt
index faf1b78c598d..7a125ac14ea1 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerDebug.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerDebug.kt
@@ -28,7 +28,6 @@ import android.provider.Settings
* Version of [LogcatEchoTracker] for debuggable builds
*
* The log level of individual buffers or tags can be controlled via global settings:
- *
* ```
* # Echo any message to <bufferName> of <level> or higher
* $ adb shell settings put global systemui/buffer/<bufferName> <level>
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/util/RingBuffer.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/util/RingBuffer.kt
index 68d78907f028..4773f54a079e 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/util/RingBuffer.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/util/RingBuffer.kt
@@ -30,7 +30,7 @@ import kotlin.math.max
*
* @param maxSize The maximum size the buffer can grow to before it begins functioning as a ring.
* @param factory A function that creates a fresh instance of T. Used by the buffer while it's
- * growing to [maxSize].
+ * growing to [maxSize].
*/
class RingBuffer<T>(private val maxSize: Int, private val factory: () -> T) : Iterable<T> {
diff --git a/packages/SystemUI/res-keyguard/drawable-mdpi/ic_lockscreen_sim.png b/packages/SystemUI/res-keyguard/drawable-mdpi/ic_lockscreen_sim.png
deleted file mode 100644
index 2e259c3e17c1..000000000000
--- a/packages/SystemUI/res-keyguard/drawable-mdpi/ic_lockscreen_sim.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res-keyguard/drawable-xhdpi/ic_lockscreen_sim.png b/packages/SystemUI/res-keyguard/drawable-xhdpi/ic_lockscreen_sim.png
deleted file mode 100644
index f4de96adae30..000000000000
--- a/packages/SystemUI/res-keyguard/drawable-xhdpi/ic_lockscreen_sim.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res-keyguard/drawable-hdpi/ic_lockscreen_sim.png b/packages/SystemUI/res-keyguard/drawable/ic_lockscreen_sim.png
index 7cf9e3699ceb..7cf9e3699ceb 100644
--- a/packages/SystemUI/res-keyguard/drawable-hdpi/ic_lockscreen_sim.png
+++ b/packages/SystemUI/res-keyguard/drawable/ic_lockscreen_sim.png
Binary files differ
diff --git a/packages/SystemUI/res-keyguard/layout/fsi_chrome_view.xml b/packages/SystemUI/res-keyguard/layout/fsi_chrome_view.xml
deleted file mode 100644
index 4ff2967b5ddf..000000000000
--- a/packages/SystemUI/res-keyguard/layout/fsi_chrome_view.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<com.android.systemui.statusbar.notification.fsi.FsiChromeView android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_margin="50dp"
- android:orientation="vertical"
- xmlns:android="http://schemas.android.com/apk/res/android">
-
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:id="@+id/fsi_chrome"
- android:layout_height="50dp"
- android:orientation="horizontal">
-
- <ImageView
- android:id="@+id/fsi_app_icon"
- android:layout_width="50dp"
- android:layout_height="match_parent"
- android:contentDescription="@null" />
-
- <TextView
- android:id="@+id/fsi_app_name"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:padding="10dp"
- android:textSize="22dp"
- android:gravity="center"
- android:textColor="#FFFFFF"
- android:text="AppName" />
-
- <Space
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:layout_weight="1" />
-
- <Button
- android:id="@+id/fsi_fullscreen_button"
- android:layout_width="100dp"
- android:layout_height="match_parent"
- android:text="fullscreen" />
-
- <Button
- android:id="@+id/fsi_dismiss_button"
- android:layout_width="100dp"
- android:layout_height="match_parent"
- android:text="dismiss" />
-
- </LinearLayout>
-
-</com.android.systemui.statusbar.notification.fsi.FsiChromeView> \ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_num_pad_key.xml b/packages/SystemUI/res-keyguard/layout/keyguard_num_pad_key.xml
index 411fea5dd22d..48769fdebd99 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_num_pad_key.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_num_pad_key.xml
@@ -14,10 +14,12 @@
~ limitations under the License
-->
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
+<merge xmlns:android="http://schemas.android.com/apk/res/android" >
<TextView
android:id="@+id/digit_text"
style="@style/Widget.TextView.NumPadKey.Digit"
+ android:autoSizeMaxTextSize="32sp"
+ android:autoSizeTextType="uniform"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
index 7db0fe908ec0..728d861ab693 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
**
** Copyright 2012, The Android Open Source Project
**
@@ -17,185 +16,185 @@
*/
-->
<!-- This is the SIM PIN view that allows the user to enter a SIM PIN to unlock the device. -->
-<com.android.keyguard.KeyguardSimPinView
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/res-auto"
- android:id="@+id/keyguard_sim_pin_view"
- android:orientation="vertical"
+<com.android.keyguard.KeyguardSimPinView xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/res-auto"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/keyguard_sim_pin_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ androidprv:layout_maxWidth="@dimen/keyguard_security_width"
+ android:layout_gravity="center_horizontal|bottom">
+ <include layout="@layout/keyguard_bouncer_message_area"/>
+
+ <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
- android:layout_height="match_parent"
- androidprv:layout_maxWidth="@dimen/keyguard_security_width"
- android:layout_gravity="center_horizontal|bottom">
- <include layout="@layout/keyguard_bouncer_message_area" />
- <Space
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1" />
- <ImageView
- android:id="@+id/keyguard_sim"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:tint="@color/background_protected"
- android:src="@drawable/ic_lockscreen_sim"/>
- <LinearLayout
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:layoutDirection="ltr">
+ <LinearLayout
+ android:id="@+id/pin_area"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
- android:gravity="center"
- android:layoutDirection="ltr"
- >
- <include layout="@layout/keyguard_esim_area"
- android:id="@+id/keyguard_esim_area"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- <RelativeLayout
- android:id="@+id/row0"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingBottom="4dp"
- >
+ android:gravity="center_horizontal"
+ android:paddingTop="@dimen/num_pad_entry_row_margin_bottom"
+ android:paddingBottom="@dimen/num_pad_entry_row_margin_bottom"
+ androidprv:layout_constraintBottom_toTopOf="@+id/flow1"
+ androidprv:layout_constraintEnd_toEndOf="parent"
+ androidprv:layout_constraintStart_toStartOf="parent"
+ androidprv:layout_constraintTop_toTopOf="parent">
+
+ <ImageView
+ android:id="@+id/keyguard_sim"
+ android:layout_width="40dp"
+ android:layout_height="40dp"
+ android:layout_gravity="center_horizontal"
+ android:src="@drawable/ic_lockscreen_sim"
+ app:tint="@color/background_protected" />
+
+ <include
+ android:id="@+id/keyguard_esim_area"
+ layout="@layout/keyguard_esim_area"
+ android:layout_gravity="center_horizontal"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
<com.android.keyguard.PasswordTextView
android:id="@+id/simPinEntry"
style="@style/Widget.TextView.Password"
android:layout_width="@dimen/keyguard_security_width"
android:layout_height="@dimen/keyguard_password_height"
- android:layout_centerHorizontal="true"
- android:layout_marginRight="72dp"
android:contentDescription="@string/keyguard_accessibility_sim_pin_area"
- android:gravity="center"
- androidprv:scaledTextSize="@integer/scaled_password_text_size" />
- </RelativeLayout>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
android:layout_gravity="center_horizontal"
- android:layout_marginBottom="@dimen/num_pad_row_margin_bottom"
- >
- <com.android.keyguard.NumPadKey
- android:id="@+id/key1"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/simPinEntry"
- androidprv:digit="1"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key2"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/simPinEntry"
- androidprv:digit="2"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key3"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- androidprv:textView="@+id/simPinEntry"
- androidprv:digit="3"
- />
- </LinearLayout>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_gravity="center_horizontal"
- android:layout_marginBottom="@dimen/num_pad_row_margin_bottom"
- >
- <com.android.keyguard.NumPadKey
- android:id="@+id/key4"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/simPinEntry"
- androidprv:digit="4"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key5"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/simPinEntry"
- androidprv:digit="5"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key6"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- androidprv:textView="@+id/simPinEntry"
- androidprv:digit="6"
- />
- </LinearLayout>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_gravity="center_horizontal"
- android:layout_marginBottom="@dimen/num_pad_row_margin_bottom"
- >
- <com.android.keyguard.NumPadKey
- android:id="@+id/key7"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/simPinEntry"
- androidprv:digit="7"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key8"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/simPinEntry"
- androidprv:digit="8"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key9"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- androidprv:textView="@+id/simPinEntry"
- androidprv:digit="9"
- />
- </LinearLayout>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_gravity="center_horizontal"
- >
- <com.android.keyguard.NumPadButton
- android:id="@+id/delete_button"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- android:contentDescription="@string/keyboardview_keycode_delete"
- style="@style/NumPadKey.Delete"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key0"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/simPinEntry"
- androidprv:digit="0"
- />
- <com.android.keyguard.NumPadButton
- android:id="@+id/key_enter"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- style="@style/NumPadKey.Enter"
- android:contentDescription="@string/keyboardview_keycode_enter"
- />
+ androidprv:scaledTextSize="@integer/scaled_password_text_size" />
</LinearLayout>
- </LinearLayout>
- <include layout="@layout/keyguard_eca"
- android:id="@+id/keyguard_selector_fade_container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:layout_gravity="bottom|center_horizontal"
- android:layout_marginTop="@dimen/keyguard_eca_top_margin"
- android:layout_marginBottom="2dp"
- android:gravity="center_horizontal"/>
+
+ <androidx.constraintlayout.helper.widget.Flow
+ android:id="@+id/flow1"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:orientation="horizontal"
+ androidprv:constraint_referenced_ids="key1,key2,key3,key4,key5,key6,key7,key8,key9,delete_button,key0,key_enter"
+ androidprv:flow_horizontalGap="@dimen/num_pad_key_margin_end"
+ androidprv:flow_horizontalStyle="packed"
+ androidprv:flow_maxElementsWrap="3"
+ androidprv:flow_verticalBias="1.0"
+ androidprv:flow_verticalGap="@dimen/num_pad_entry_row_margin_bottom"
+ androidprv:flow_verticalStyle="packed"
+ androidprv:flow_wrapMode="aligned"
+ androidprv:layout_constraintBottom_toBottomOf="parent"
+ androidprv:layout_constraintEnd_toEndOf="parent"
+ androidprv:layout_constraintStart_toStartOf="parent"
+ androidprv:layout_constraintTop_toBottomOf="@id/pin_area" />
+
+ <com.android.keyguard.NumPadButton
+ android:id="@+id/delete_button"
+ style="@style/NumPadKey.Delete"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key0"
+ android:contentDescription="@string/keyboardview_keycode_delete" />
+
+ <com.android.keyguard.NumPadButton
+ android:id="@+id/key_enter"
+ style="@style/NumPadKey.Enter"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:contentDescription="@string/keyboardview_keycode_enter" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key1"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key2"
+ androidprv:digit="1"
+ androidprv:textView="@+id/simPinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key2"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key3"
+ androidprv:digit="2"
+ androidprv:textView="@+id/simPinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key3"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key4"
+ androidprv:digit="3"
+ androidprv:textView="@+id/simPinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key4"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key5"
+ androidprv:digit="4"
+ androidprv:textView="@+id/simPinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key5"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key6"
+ androidprv:digit="5"
+ androidprv:textView="@+id/simPinEntry" />
+
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key6"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key7"
+ androidprv:digit="6"
+ androidprv:textView="@+id/simPinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key7"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key8"
+ androidprv:digit="7"
+ androidprv:textView="@+id/simPinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key8"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key9"
+ androidprv:digit="8"
+ androidprv:textView="@+id/simPinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key9"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/delete_button"
+ androidprv:digit="9"
+ androidprv:textView="@+id/simPinEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key0"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key_enter"
+ androidprv:digit="0"
+ androidprv:textView="@+id/simPinEntry" />
+ </androidx.constraintlayout.widget.ConstraintLayout>
+
+ <include
+ android:id="@+id/keyguard_selector_fade_container"
+ layout="@layout/keyguard_eca"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom|center_horizontal"
+ android:layout_marginBottom="2dp"
+ android:layout_marginTop="@dimen/keyguard_eca_top_margin"
+ android:gravity="center_horizontal"
+ android:orientation="vertical" />
</com.android.keyguard.KeyguardSimPinView>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
index 422bd4c12e8e..7e24d1231aee 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
@@ -21,6 +21,7 @@
<com.android.keyguard.KeyguardSimPukView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/res-auto"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/keyguard_sim_puk_view"
android:orientation="vertical"
android:layout_width="match_parent"
@@ -29,173 +30,165 @@
android:layout_gravity="center_horizontal|bottom">
<include layout="@layout/keyguard_bouncer_message_area"/>
- <Space
+ <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="0dp"
- android:layout_weight="1" />
-
- <ImageView
- android:id="@+id/keyguard_sim"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:tint="@color/background_protected"
- android:src="@drawable/ic_lockscreen_sim"/>
-
- <LinearLayout
+ android:layout_weight="1"
+ android:layoutDirection="ltr">
+ <LinearLayout
+ android:id="@+id/pin_area"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
- android:gravity="center"
- android:layoutDirection="ltr"
- >
- <include layout="@layout/keyguard_esim_area"
- android:id="@+id/keyguard_esim_area"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
-
- <RelativeLayout
- android:id="@+id/row0"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingBottom="4dp"
- >
+ android:gravity="center_horizontal"
+ android:paddingTop="@dimen/num_pad_entry_row_margin_bottom"
+ android:paddingBottom="@dimen/num_pad_entry_row_margin_bottom"
+ androidprv:layout_constraintBottom_toTopOf="@+id/flow1"
+ androidprv:layout_constraintEnd_toEndOf="parent"
+ androidprv:layout_constraintStart_toStartOf="parent"
+ androidprv:layout_constraintTop_toTopOf="parent">
+
+ <ImageView
+ android:id="@+id/keyguard_sim"
+ android:layout_width="40dp"
+ android:layout_height="40dp"
+ android:layout_gravity="center_horizontal"
+ android:src="@drawable/ic_lockscreen_sim"
+ app:tint="@color/background_protected" />
+
+ <include
+ android:id="@+id/keyguard_esim_area"
+ layout="@layout/keyguard_esim_area"
+ android:layout_gravity="center_horizontal"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
<com.android.keyguard.PasswordTextView
android:id="@+id/pukEntry"
style="@style/Widget.TextView.Password"
android:layout_width="@dimen/keyguard_security_width"
android:layout_height="@dimen/keyguard_password_height"
- android:layout_centerHorizontal="true"
- android:layout_marginRight="72dp"
- android:contentDescription="@string/keyguard_accessibility_sim_puk_area"
- android:gravity="center"
- androidprv:scaledTextSize="@integer/scaled_password_text_size" />
- </RelativeLayout>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_gravity="center_horizontal"
- android:layout_marginBottom="@dimen/num_pad_row_margin_bottom"
- >
- <com.android.keyguard.NumPadKey
- android:id="@+id/key1"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/pukEntry"
- androidprv:digit="1"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key2"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/pukEntry"
- androidprv:digit="2"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key3"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- androidprv:textView="@+id/pukEntry"
- androidprv:digit="3"
- />
- </LinearLayout>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_gravity="center_horizontal"
- android:layout_marginBottom="@dimen/num_pad_row_margin_bottom"
-
- >
- <com.android.keyguard.NumPadKey
- android:id="@+id/key4"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/pukEntry"
- androidprv:digit="4"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key5"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/pukEntry"
- androidprv:digit="5"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key6"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- androidprv:textView="@+id/pukEntry"
- androidprv:digit="6"
- />
- </LinearLayout>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_gravity="center_horizontal"
- android:layout_marginBottom="@dimen/num_pad_row_margin_bottom"
- >
- <com.android.keyguard.NumPadKey
- android:id="@+id/key7"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/pukEntry"
- androidprv:digit="7"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key8"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/pukEntry"
- androidprv:digit="8"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key9"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- androidprv:textView="@+id/pukEntry"
- androidprv:digit="9"
- />
- </LinearLayout>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
+ android:contentDescription="@string/keyguard_accessibility_sim_pin_area"
android:layout_gravity="center_horizontal"
- >
- <com.android.keyguard.NumPadButton
- android:id="@+id/delete_button"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- android:contentDescription="@string/keyboardview_keycode_delete"
- style="@style/NumPadKey.Delete"
- />
- <com.android.keyguard.NumPadKey
- android:id="@+id/key0"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- android:layout_marginEnd="@dimen/num_pad_key_margin_end"
- androidprv:textView="@+id/pukEntry"
- androidprv:digit="0"
- />
- <com.android.keyguard.NumPadButton
- android:id="@+id/key_enter"
- android:layout_width="@dimen/num_pad_key_width"
- android:layout_height="match_parent"
- style="@style/NumPadKey.Enter"
- android:contentDescription="@string/keyboardview_keycode_enter"
- />
+ androidprv:scaledTextSize="@integer/scaled_password_text_size" />
</LinearLayout>
- </LinearLayout>
+
+ <androidx.constraintlayout.helper.widget.Flow
+ android:id="@+id/flow1"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:orientation="horizontal"
+ androidprv:constraint_referenced_ids="key1,key2,key3,key4,key5,key6,key7,key8,key9,delete_button,key0,key_enter"
+ androidprv:flow_horizontalGap="@dimen/num_pad_key_margin_end"
+ androidprv:flow_horizontalStyle="packed"
+ androidprv:flow_maxElementsWrap="3"
+ androidprv:flow_verticalBias="1.0"
+ androidprv:flow_verticalGap="@dimen/num_pad_entry_row_margin_bottom"
+ androidprv:flow_verticalStyle="packed"
+ androidprv:flow_wrapMode="aligned"
+ androidprv:layout_constraintBottom_toBottomOf="parent"
+ androidprv:layout_constraintEnd_toEndOf="parent"
+ androidprv:layout_constraintStart_toStartOf="parent"
+ androidprv:layout_constraintTop_toBottomOf="@id/pin_area" />
+
+ <com.android.keyguard.NumPadButton
+ android:id="@+id/delete_button"
+ style="@style/NumPadKey.Delete"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key0"
+ android:contentDescription="@string/keyboardview_keycode_delete" />
+
+ <com.android.keyguard.NumPadButton
+ android:id="@+id/key_enter"
+ style="@style/NumPadKey.Enter"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:contentDescription="@string/keyboardview_keycode_enter" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key1"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key2"
+ androidprv:digit="1"
+ androidprv:textView="@+id/pukEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key2"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key3"
+ androidprv:digit="2"
+ androidprv:textView="@+id/pukEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key3"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key4"
+ androidprv:digit="3"
+ androidprv:textView="@+id/pukEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key4"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key5"
+ androidprv:digit="4"
+ androidprv:textView="@+id/pukEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key5"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key6"
+ androidprv:digit="5"
+ androidprv:textView="@+id/pukEntry" />
+
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key6"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key7"
+ androidprv:digit="6"
+ androidprv:textView="@+id/pukEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key7"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key8"
+ androidprv:digit="7"
+ androidprv:textView="@+id/pukEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key8"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key9"
+ androidprv:digit="8"
+ androidprv:textView="@+id/pukEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key9"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/delete_button"
+ androidprv:digit="9"
+ androidprv:textView="@+id/pukEntry" />
+
+ <com.android.keyguard.NumPadKey
+ android:id="@+id/key0"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:accessibilityTraversalBefore="@id/key_enter"
+ androidprv:digit="0"
+ androidprv:textView="@+id/pukEntry" />
+ </androidx.constraintlayout.widget.ConstraintLayout>
<include layout="@layout/keyguard_eca"
android:id="@+id/keyguard_selector_fade_container"
diff --git a/packages/SystemUI/res-keyguard/values-af/strings.xml b/packages/SystemUI/res-keyguard/values-af/strings.xml
index f226deace6bb..205b9e065d84 100644
--- a/packages/SystemUI/res-keyguard/values-af/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-af/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans vinnig"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans stadig"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laaiproses word geoptimeer om battery te beskerm"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Onversoenbare laaiproses"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Druk Kieslys om te ontsluit."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Netwerk is gesluit"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Geen SIM nie"</string>
diff --git a/packages/SystemUI/res-keyguard/values-am/strings.xml b/packages/SystemUI/res-keyguard/values-am/strings.xml
index 647001ecb277..47b7bbe6ce3a 100644
--- a/packages/SystemUI/res-keyguard/values-am/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-am/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • በፍጥነት ኃይልን በመሙላት ላይ"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • በዝግታ ኃይልን በመሙላት ላይ"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ባትሪን ለመጠበቅ ኃይል መሙላት ተብቷል"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ተኳሃኝ ባልሆነ ኃይል በመሙላት ላይ"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ለመክፈት ምናሌ ተጫን።"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"አውታረ መረብ ተቆልፏል"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"ምንም SIM የለም"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ar/strings.xml b/packages/SystemUI/res-keyguard/values-ar/strings.xml
index a7fe8e55fe4c..76b8d4657f6e 100644
--- a/packages/SystemUI/res-keyguard/values-ar/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ar/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن سريعًا"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن ببطء"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • تم تحسين الشحن لحماية البطارية"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • شاحن غير متوافق"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"اضغط على \"القائمة\" لإلغاء التأمين."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"الشبكة مؤمّنة"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"‏لا تتوفر شريحة SIM."</string>
diff --git a/packages/SystemUI/res-keyguard/values-as/strings.xml b/packages/SystemUI/res-keyguard/values-as/strings.xml
index 4fcc56d48d8c..716699bc35ef 100644
--- a/packages/SystemUI/res-keyguard/values-as/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-as/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • দ্ৰুত গতিৰে চ্চাৰ্জ কৰি থকা হৈছে"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • লাহে লাহে চ্চাৰ্জ কৰি থকা হৈছে"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • বেটাৰী সুৰক্ষিত কৰিবলৈ চাৰ্জিং অপ্টিমাইজ কৰা হৈছে"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • অমিল চাৰ্জিং"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"আনলক কৰিবলৈ মেনু টিপক।"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"নেটৱর্ক লক কৰা অৱস্থাত আছে"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"কোনো ছিম নাই"</string>
diff --git a/packages/SystemUI/res-keyguard/values-az/strings.xml b/packages/SystemUI/res-keyguard/values-az/strings.xml
index e8f0f817ab57..1626fd854291 100644
--- a/packages/SystemUI/res-keyguard/values-az/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-az/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sürətlə enerji yığır"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Yavaş enerji yığır"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Batareyanı qorumaq üçün şarj optimallaşdırılıb"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Uyğunsuz şarj"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Kilidi açmaq üçün Menyu düyməsinə basın."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Şəbəkə kilidlidir"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM yoxdur"</string>
diff --git a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
index c3b7cc6bcbbe..9be3eaaf4b61 100644
--- a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Brzo se puni"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sporo se puni"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Punjenje je optimizovano da bi se zaštitila baterija"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nekompatibilno punjenje"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pritisnite Meni da biste otključali."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Mreža je zaključana"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Nema SIM-a"</string>
diff --git a/packages/SystemUI/res-keyguard/values-be/strings.xml b/packages/SystemUI/res-keyguard/values-be/strings.xml
index dce92dce4b76..0c6826c7a8bd 100644
--- a/packages/SystemUI/res-keyguard/values-be/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-be/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе хуткая зарадка"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе павольная зарадка"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • У мэтах зберажэння акумулятара зарадка аптымізавана"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Несумяшчальная зарадная прылада"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Націсніце кнопку \"Меню\", каб разблакіраваць."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Сетка заблакіравана"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Няма SIM-карты"</string>
diff --git a/packages/SystemUI/res-keyguard/values-bg/strings.xml b/packages/SystemUI/res-keyguard/values-bg/strings.xml
index 25c9cf69b4e6..683c87bb24e5 100644
--- a/packages/SystemUI/res-keyguard/values-bg/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bg/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се бързо"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се бавно"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зареждането е оптимизирано с цел запазване на батерията"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • несъвместим начин на зареждане"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Натиснете „Меню“, за да отключите."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Мрежата е заключена"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Няма SIM карта"</string>
diff --git a/packages/SystemUI/res-keyguard/values-bn/strings.xml b/packages/SystemUI/res-keyguard/values-bn/strings.xml
index 1e8758513ec6..ebcf9fbe3770 100644
--- a/packages/SystemUI/res-keyguard/values-bn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bn/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • দ্রুত চার্জ হচ্ছে"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ধীরে চার্জ হচ্ছে"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ব্যাটারি ভাল রাখতে চার্জিং অপ্টিমাইজ করা হয়েছে"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • মানানসই নয় এমন চার্জিং"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"আনলক করতে মেনুতে টিপুন।"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"নেটওয়ার্ক লক করা আছে"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"কোনও সিম নেই"</string>
diff --git a/packages/SystemUI/res-keyguard/values-bs/strings.xml b/packages/SystemUI/res-keyguard/values-bs/strings.xml
index 3118d5be7247..a3280c3eaa4f 100644
--- a/packages/SystemUI/res-keyguard/values-bs/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bs/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Brzo punjenje"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sporo punjenje"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Punjenje je optimizirano radi zaštite baterije"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nekompatibilno punjenje"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pritisnite meni da otključate."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Mreža je zaključana"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Nema SIM-a"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ca/strings.xml b/packages/SystemUI/res-keyguard/values-ca/strings.xml
index e45df7abb0fa..0cb55af4d962 100644
--- a/packages/SystemUI/res-keyguard/values-ca/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ca/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant ràpidament"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant lentament"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Càrrega optimitzada per protegir la bateria"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Càrrega incompatible"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Prem Menú per desbloquejar."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"La xarxa està bloquejada"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"No hi ha cap SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-cs/strings.xml b/packages/SystemUI/res-keyguard/values-cs/strings.xml
index ae1ebcbc4846..75ddff852751 100644
--- a/packages/SystemUI/res-keyguard/values-cs/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-cs/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Rychlé nabíjení"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pomalé nabíjení"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimalizované nabíjení za účelem ochrany baterie"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nekompatibilní nabíjení"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Klávesy odemknete stisknutím tlačítka nabídky."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Síť je blokována"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Žádná SIM karta"</string>
diff --git a/packages/SystemUI/res-keyguard/values-da/strings.xml b/packages/SystemUI/res-keyguard/values-da/strings.xml
index 735aacfc6a6e..47d9416bed51 100644
--- a/packages/SystemUI/res-keyguard/values-da/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-da/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oplader hurtigt"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oplader langsomt"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Opladning er optimeret for at beskytte batteriet"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ikke-kompatibel opladning"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Tryk på menuen for at låse op."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Netværket er låst"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Intet SIM-kort"</string>
diff --git a/packages/SystemUI/res-keyguard/values-de/strings.xml b/packages/SystemUI/res-keyguard/values-de/strings.xml
index 5e7a5c70cbb9..4eae7d934614 100644
--- a/packages/SystemUI/res-keyguard/values-de/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-de/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird schnell geladen"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird langsam geladen"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimiertes Laden zur Akkuschonung"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inkompatibles Ladegerät"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Zum Entsperren die Menütaste drücken."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Netzwerk gesperrt"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Keine SIM-Karte"</string>
diff --git a/packages/SystemUI/res-keyguard/values-el/strings.xml b/packages/SystemUI/res-keyguard/values-el/strings.xml
index cd0b01e79efb..81ac3dc7b76f 100644
--- a/packages/SystemUI/res-keyguard/values-el/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-el/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Γρήγορη φόρτιση"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Αργή φόρτιση"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Η φόρτιση βελτιστοποιήθηκε για την προστασία της μπαταρίας"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Μη συμβατή φόρτιση"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Πατήστε \"Μενού\" για ξεκλείδωμα."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Κλειδωμένο δίκτυο"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Δεν υπάρχει SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
index de9dbaeef5c8..0f84823bacde 100644
--- a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging optimised to protect battery"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Incompatible charging"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"No SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
index 5ae7080cb1f1..a28506be83fe 100644
--- a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging optimized to protect battery"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Incompatible charging"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"No SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
index de9dbaeef5c8..0f84823bacde 100644
--- a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging optimised to protect battery"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Incompatible charging"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"No SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
index de9dbaeef5c8..0f84823bacde 100644
--- a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging optimised to protect battery"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Incompatible charging"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"No SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml b/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml
index 7f29899e1edc..3f1b30a34a1a 100644
--- a/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‏‏‎‎‎‎‎‎‏‎‏‎‎‎‎‎‎‎‏‎‏‎‏‏‎‏‎‏‏‏‎‎‏‎‎‎‏‏‏‏‏‎‏‎‎‎‎‏‎‎‎‏‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ • Charging rapidly‎‏‎‎‏‎"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‎‎‎‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‏‎‏‎‏‏‎‎‎‏‎‎‏‎‎‏‎‏‏‏‏‎‏‏‏‎‏‎‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ • Charging slowly‎‏‎‎‏‎"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‎‎‏‏‏‎‏‎‏‏‏‏‎‎‎‏‎‏‎‎‎‎‎‏‎‏‏‎‎‏‎‎‏‎‏‎‎‎‏‎‎‎‏‏‏‎‎‎‎‎‏‎‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ • Charging optimized to protect battery‎‏‎‎‏‎"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‎‎‏‎‎‎‎‏‏‎‏‏‏‎‏‏‎‏‏‏‎‎‏‏‏‏‎‎‏‎‏‏‏‏‎‎‏‏‏‎‏‎‎‎‏‏‏‏‎‎‎‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ • Incompatible charging‎‏‎‎‏‎"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‎‎‎‎‎‏‎‏‏‏‎‏‎‏‎‎‎‏‏‎‏‎‏‏‎‏‏‎‎‎‏‏‎‎‎‏‎‎‏‏‏‎‎‎‎‏‏‏‎‏‎‎Press Menu to unlock.‎‏‎‎‏‎"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‏‎‏‎‎‏‏‎‎‏‎‎‏‎‏‏‏‏‏‎‏‎‏‏‏‏‏‎‎‏‎‎‎‏‏‎‎‏‎‏‏‎‎‏‎‏‎‎‎‎‎‎‎‎‎‎‎Network locked‎‏‎‎‏‎"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‏‎‎‎‎‎‎‏‏‎‏‏‎‏‏‎‏‏‎‎‎‏‏‏‎‏‏‏‏‎‎‎‏‎‎‎‎‎‎‎‎‏‏‏‏‎‎‏‎‎‏‎‏‎‎‎‎No SIM‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
index e0aa9a8b66f9..4b735e9eb74f 100644
--- a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rápidamente"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando lentamente"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carga optimizada para proteger la batería"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carga no compatible"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Presiona Menú para desbloquear."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Bloqueada para la red"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"No hay ninguna tarjeta SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-es/strings.xml b/packages/SystemUI/res-keyguard/values-es/strings.xml
index fc65751a4377..986192f4862c 100644
--- a/packages/SystemUI/res-keyguard/values-es/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-es/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rápidamente"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando lentamente"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carga optimizada para proteger la batería"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carga no compatible"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pulsa el menú para desbloquear la pantalla."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Bloqueada para la red"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"No hay ninguna SIM."</string>
diff --git a/packages/SystemUI/res-keyguard/values-et/strings.xml b/packages/SystemUI/res-keyguard/values-et/strings.xml
index 86a8b110ec14..f551ab27a032 100644
--- a/packages/SystemUI/res-keyguard/values-et/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-et/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kiirlaadimine"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Aeglane laadimine"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laadimine on aku kaitsmiseks optimeeritud"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ühildumatu laadimine"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Vajutage avamiseks menüüklahvi."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Võrk on lukus"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM-i pole"</string>
diff --git a/packages/SystemUI/res-keyguard/values-eu/strings.xml b/packages/SystemUI/res-keyguard/values-eu/strings.xml
index b79ad393fa34..6a18b3dcfd82 100644
--- a/packages/SystemUI/res-keyguard/values-eu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-eu/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bizkor kargatzen"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mantso kargatzen"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kargatzea optimizatu da bateria ez kaltetzeko"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kargagailua ez da bateragarria"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Desblokeatzeko, sakatu Menua."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Sarea blokeatuta dago"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Ez dago SIMik"</string>
diff --git a/packages/SystemUI/res-keyguard/values-fa/strings.xml b/packages/SystemUI/res-keyguard/values-fa/strings.xml
index 6faaed5b496c..ea591b8f6a13 100644
--- a/packages/SystemUI/res-keyguard/values-fa/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fa/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • درحال شارژ سریع"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • آهسته‌آهسته شارژ می‌شود"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • برای محافظت از باتری، شارژ بهینه می‌شود"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • شارژ ناسازگار است"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"برای باز کردن قفل روی «منو» فشار دهید."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"شبکه قفل شد"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"سیم‌کارتی وجود ندارد"</string>
diff --git a/packages/SystemUI/res-keyguard/values-fi/strings.xml b/packages/SystemUI/res-keyguard/values-fi/strings.xml
index 0c52507c6498..9e26025f3fe8 100644
--- a/packages/SystemUI/res-keyguard/values-fi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fi/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan nopeasti"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan hitaasti"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lataus optimoitu akun suojaamiseksi"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laturi ei ole yhteensopiva"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Poista lukitus painamalla Valikkoa."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Verkko lukittu"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Ei SIM-korttia"</string>
diff --git a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
index 6ac8f4c7050d..2f295f745549 100644
--- a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"En recharge rapide : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"En recharge lente : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge optimisée pour protéger la pile"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • chargeur incompatible"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Appuyez sur la touche Menu pour déverrouiller l\'appareil."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Réseau verrouillé"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Aucune carte SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-fr/strings.xml b/packages/SystemUI/res-keyguard/values-fr/strings.xml
index 8313e6a3b107..77d398723aef 100644
--- a/packages/SystemUI/res-keyguard/values-fr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fr/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge rapide…"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge lente"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge optimisée pour protéger la batterie"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge incompatible"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Appuyez sur \"Menu\" pour déverrouiller le clavier."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Réseau verrouillé"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Aucune SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-gl/strings.xml b/packages/SystemUI/res-keyguard/values-gl/strings.xml
index 5bed71981293..9feb174e5185 100644
--- a/packages/SystemUI/res-keyguard/values-gl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-gl/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rapidamente"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando lentamente"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carga optimizada para protexer a batería"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carga incompatible"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Preme Menú para desbloquear."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Bloqueada pola rede"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Non hai ningunha SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-gu/strings.xml b/packages/SystemUI/res-keyguard/values-gu/strings.xml
index fd93ba0ba832..6d68426f8b4b 100644
--- a/packages/SystemUI/res-keyguard/values-gu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-gu/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ઝડપથી ચાર્જિંગ"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ધીમેથી ચાર્જિંગ"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • બૅટરીની સુરક્ષા કરવા માટે, ચાર્જિંગ ઑપ્ટિમાઇઝ કરવામાં આવ્યું છે"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • અસંગત ચાર્જિંગ"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"અનલૉક કરવા માટે મેનૂ દબાવો."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"નેટવર્ક લૉક થયું"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"કોઈ સિમ કાર્ડ નથી"</string>
diff --git a/packages/SystemUI/res-keyguard/values-hi/strings.xml b/packages/SystemUI/res-keyguard/values-hi/strings.xml
index 459287d3d1b2..335931ba8baa 100644
--- a/packages/SystemUI/res-keyguard/values-hi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hi/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • तेज़ चार्ज हो रहा है"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • धीरे चार्ज हो रहा है"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • बैटरी को नुकसान से बचाने के लिए, उसकी चार्जिंग को ऑप्टिमाइज़ किया गया"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • फ़ोन के साथ काम न करने वाला चार्जर"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"लॉक खोलने के लिए मेन्यू दबाएं."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"नेटवर्क लॉक किया हुआ है"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"कोई सिम नहीं है"</string>
diff --git a/packages/SystemUI/res-keyguard/values-hr/strings.xml b/packages/SystemUI/res-keyguard/values-hr/strings.xml
index f88408f3c583..a865b37cbe32 100644
--- a/packages/SystemUI/res-keyguard/values-hr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hr/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • brzo punjenje"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • sporo punjenje"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Punjenje se optimizira radi zaštite baterije"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nekompatibilno punjenje"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pritisnite Izbornik da biste otključali."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Mreža je zaključana"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Nema SIM-a"</string>
diff --git a/packages/SystemUI/res-keyguard/values-hu/strings.xml b/packages/SystemUI/res-keyguard/values-hu/strings.xml
index b1260303d38d..06dd876df366 100644
--- a/packages/SystemUI/res-keyguard/values-hu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hu/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Gyors töltés"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lassú töltés"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimalizált töltés az akkumulátor védelme érdekében"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nem kompatibilis töltés"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"A feloldáshoz nyomja meg a Menü gombot."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Hálózat zárolva"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Nincs SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-hy/strings.xml b/packages/SystemUI/res-keyguard/values-hy/strings.xml
index 0b0fc0462a42..d1310466b5e8 100644
--- a/packages/SystemUI/res-keyguard/values-hy/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hy/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Արագ լիցքավորում"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Դանդաղ լիցքավորում"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Մարտկոցը պաշտպանելու համար լիցքավորումն օպտիմալացվել է"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Անհամատեղելի ադապտերով լիցքավորում"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Ապակողպելու համար սեղմեք Ընտրացանկը:"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Ցանցը կողպված է"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM քարտ չկա"</string>
diff --git a/packages/SystemUI/res-keyguard/values-in/strings.xml b/packages/SystemUI/res-keyguard/values-in/strings.xml
index 78dee0d0f181..b6a41853d382 100644
--- a/packages/SystemUI/res-keyguard/values-in/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-in/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya dengan cepat"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya dengan lambat"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pengisian daya dioptimalkan untuk melindungi baterai"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pengisi daya tidak kompatibel"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Tekan Menu untuk membuka kunci."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Jaringan terkunci"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Tidak ada SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-is/strings.xml b/packages/SystemUI/res-keyguard/values-is/strings.xml
index d7585651f33b..de0dc64f4d7c 100644
--- a/packages/SystemUI/res-keyguard/values-is/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-is/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hröð hleðsla"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hæg hleðsla"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hleðsla fínstillt til að vernda rafhlöðuna"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ósamhæf hleðsla"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Ýttu á valmyndarhnappinn til að taka úr lás."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Net læst"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Ekkert SIM-kort"</string>
diff --git a/packages/SystemUI/res-keyguard/values-it/strings.xml b/packages/SystemUI/res-keyguard/values-it/strings.xml
index 3b8e42c2f2bf..c0bccecf946a 100644
--- a/packages/SystemUI/res-keyguard/values-it/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-it/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ricarica veloce"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ricarica lenta"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ricarica ottimizzata per proteggere la batteria"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ricarica con un alimentatore non compatibile"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Premi Menu per sbloccare."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Rete bloccata"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Nessuna SIM presente"</string>
diff --git a/packages/SystemUI/res-keyguard/values-iw/strings.xml b/packages/SystemUI/res-keyguard/values-iw/strings.xml
index bdc867b9c93b..3d2bd4646972 100644
--- a/packages/SystemUI/res-keyguard/values-iw/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-iw/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה מהירה"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה איטית"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • הטעינה עברה אופטימיזציה כדי להגן על הסוללה"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • טעינה לא תואמת"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"יש ללחוץ על \'תפריט\' כדי לבטל את הנעילה."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"הרשת נעולה"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"‏אין כרטיס SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ja/strings.xml b/packages/SystemUI/res-keyguard/values-ja/strings.xml
index c4c370d25b4f..a990b8d25234 100644
--- a/packages/SystemUI/res-keyguard/values-ja/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ja/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 急速充電中"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 低速充電中"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電最適化済み(バッテリーを保護)"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電器が対応していません"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"メニューからロックを解除できます。"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"ネットワークがロックされました"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM がありません"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ka/strings.xml b/packages/SystemUI/res-keyguard/values-ka/strings.xml
index 38e5420418e0..81215380526d 100644
--- a/packages/SystemUI/res-keyguard/values-ka/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ka/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • სწრაფად იტენება"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ნელა იტენება"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • დატენვა ოპტიმიზირებულია ბატარეის დასაცავად"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • არათავსებადი დატენვა"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"განსაბლოკად დააჭირეთ მენიუს."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"ქსელი ჩაკეტილია"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM არ არის"</string>
diff --git a/packages/SystemUI/res-keyguard/values-kk/strings.xml b/packages/SystemUI/res-keyguard/values-kk/strings.xml
index 2057b3eafdc6..bfd65c485733 100644
--- a/packages/SystemUI/res-keyguard/values-kk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-kk/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Жылдам зарядталуда"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Баяу зарядталуда"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Батареяны қорғау үшін, зарядтау оңтайландырылды"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Үйлесімді емес зарядтағыш"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Ашу үшін \"Мәзір\" пернесін басыңыз."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Желі құлыптаулы"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM картасы жоқ."</string>
diff --git a/packages/SystemUI/res-keyguard/values-km/strings.xml b/packages/SystemUI/res-keyguard/values-km/strings.xml
index 2e278333b0e3..cdc1ddfbb25d 100644
--- a/packages/SystemUI/res-keyguard/values-km/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-km/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុង​សាកថ្មយ៉ាង​ឆាប់រហ័ស"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុង​សាកថ្មយឺត"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • បានបង្កើនប្រសិទ្ធភាពនៃការសាក ដើម្បីការពារថ្ម"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ការសាកថ្មដែលមិនត្រូវគ្នា"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ចុចម៉ឺនុយ ​ដើម្បី​ដោះ​សោ។"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"បណ្ដាញ​ជាប់​សោ"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"គ្មានស៊ីមទេ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-kn/strings.xml b/packages/SystemUI/res-keyguard/values-kn/strings.xml
index 9ed59129c5ab..66adecb1f81c 100644
--- a/packages/SystemUI/res-keyguard/values-kn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-kn/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ವೇಗವಾಗಿ ಚಾರ್ಜ್‌ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ನಿಧಾನವಾಗಿ ಚಾರ್ಜ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ಬ್ಯಾಟರಿಯನ್ನು ರಕ್ಷಿಸಲು ಚಾರ್ಜಿಂಗ್ ಅನ್ನು ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲಾಗಿದೆ"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ಹೊಂದಾಣಿಕೆಯಾಗದ ಚಾರ್ಜಿಂಗ್"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ಅನ್‌ಲಾಕ್ ಮಾಡಲು ಮೆನು ಒತ್ತಿರಿ."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"ನೆಟ್‌ವರ್ಕ್ ಲಾಕ್ ಆಗಿದೆ"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM ಇಲ್ಲ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ko/strings.xml b/packages/SystemUI/res-keyguard/values-ko/strings.xml
index 0019cd2e2526..9dd5c5d24ee7 100644
--- a/packages/SystemUI/res-keyguard/values-ko/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ko/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 고속 충전 중"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 저속 충전 중"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 배터리 보호를 위해 충전 최적화됨"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 호환되지 않는 충전기"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"잠금 해제하려면 메뉴를 누르세요."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"네트워크 잠김"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM 없음"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ky/strings.xml b/packages/SystemUI/res-keyguard/values-ky/strings.xml
index da646f1b14f4..afae9bcf5f4d 100644
--- a/packages/SystemUI/res-keyguard/values-ky/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ky/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Тез кубатталууда"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Жай кубатталууда"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Батареяны коргоо үчүн кубаттоо процесси оптималдаштырылды"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Кубаттагыч туура келбейт"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Кулпуну ачуу үчүн Менюну басыңыз."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Тармак кулпуланган"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM карта жок"</string>
diff --git a/packages/SystemUI/res-keyguard/values-lo/strings.xml b/packages/SystemUI/res-keyguard/values-lo/strings.xml
index fe1b6c6d21ac..70cc4812e20f 100644
--- a/packages/SystemUI/res-keyguard/values-lo/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-lo/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກແບບດ່ວນ"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກແບບຊ້າ"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ການສາກຖືກປັບໃຫ້ເໝາະສົມເພື່ອປົກປ້ອງແບັດເຕີຣີ"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ການສາກທີ່ເຂົ້າກັນບໍ່ໄດ້"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ກົດ \"ເມນູ\" ເພື່ອປົດລັອກ."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"ເຄືອຂ່າຍຖືກລັອກ"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"ບໍ່ມີຊິມ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-lt/strings.xml b/packages/SystemUI/res-keyguard/values-lt/strings.xml
index f4b7aee8aa75..67038945b5b7 100644
--- a/packages/SystemUI/res-keyguard/values-lt/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-lt/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Greitai įkraunama"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lėtai įkraunama"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Įkrovimas optimizuotas siekiant apsaugoti akumuliatorių"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nesuderinamas įkrovimas"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Paspauskite meniu, jei norite atrakinti."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Tinklas užrakintas"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Nėra SIM kortelės"</string>
diff --git a/packages/SystemUI/res-keyguard/values-lv/strings.xml b/packages/SystemUI/res-keyguard/values-lv/strings.xml
index 68e94d01fd50..c40245e80276 100644
--- a/packages/SystemUI/res-keyguard/values-lv/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-lv/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek ātrā uzlāde"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek lēnā uzlāde"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Uzlāde optimizēta, lai saudzētu akumulatoru"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nesaderīgs lādētājs"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Lai atbloķētu, nospiediet izvēlnes ikonu."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Tīkls ir bloķēts."</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Nav SIM kartes"</string>
diff --git a/packages/SystemUI/res-keyguard/values-mk/strings.xml b/packages/SystemUI/res-keyguard/values-mk/strings.xml
index d50422886c7e..ff4d368806b4 100644
--- a/packages/SystemUI/res-keyguard/values-mk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mk/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Брзо полнење"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Бавно полнење"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Полнењето е оптимизирано за да се заштити батеријата"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Некомпатибилно полнење"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Притиснете „Мени“ за отклучување."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Мрежата е заклучена"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Нема SIM-картичка"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ml/strings.xml b/packages/SystemUI/res-keyguard/values-ml/strings.xml
index 8d466c183c8d..c8410336d3f6 100644
--- a/packages/SystemUI/res-keyguard/values-ml/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ml/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • വേഗത്തിൽ ചാർജ് ചെയ്യുന്നു"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • പതുക്കെ ചാർജ് ചെയ്യുന്നു"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ബാറ്ററി പരിരക്ഷിക്കാൻ ചാർജിംഗ് ഒപ്റ്റിമൈസ് ചെയ്തു"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • അനുയോജ്യമല്ലാത്ത ചാർജിംഗ്"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"അൺലോക്കുചെയ്യാൻ മെനു അമർത്തുക."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"നെറ്റ്‌വർക്ക് ലോക്കുചെയ്‌തു"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"സിം ഇല്ല"</string>
diff --git a/packages/SystemUI/res-keyguard/values-mn/strings.xml b/packages/SystemUI/res-keyguard/values-mn/strings.xml
index 07a21943b410..6ad6d8d38423 100644
--- a/packages/SystemUI/res-keyguard/values-mn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mn/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Хурдан цэнэглэж байна"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Удаан цэнэглэж байна"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Батарейг хамгаалахын тулд цэнэглэх явцыг оновчилсон"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Тохиромжгүй адаптераар цэнэглэх"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Түгжээг тайлах бол цэсийг дарна уу."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Сүлжээ түгжигдсэн"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM байхгүй"</string>
diff --git a/packages/SystemUI/res-keyguard/values-mr/strings.xml b/packages/SystemUI/res-keyguard/values-mr/strings.xml
index 855558d3b7d3..951cf8d9eb58 100644
--- a/packages/SystemUI/res-keyguard/values-mr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mr/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • वेगाने चार्ज होत आहे"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • सावकाश चार्ज होत आहे"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • बॅटरीचे संरक्षण करण्यासाठी चार्जिंग ऑप्टिमाइझ केले आहे"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • कंपॅटिबल नसलेले चार्जिंग"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"अनलॉक करण्यासाठी मेनू दाबा."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"नेटवर्क लॉक केले"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"सिम नाही"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ms/strings.xml b/packages/SystemUI/res-keyguard/values-ms/strings.xml
index 032cb3dcd61f..70965651aaee 100644
--- a/packages/SystemUI/res-keyguard/values-ms/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ms/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas dengan cepat"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas dengan perlahan"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pengecasan dioptimumkan untuk melindungi bateri"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pengecasan tidak serasi"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Tekan Menu untuk membuka kunci."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Rangkaian dikunci"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Tiada SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-my/strings.xml b/packages/SystemUI/res-keyguard/values-my/strings.xml
index d38fb8fcfce3..d4251cd5bf68 100644
--- a/packages/SystemUI/res-keyguard/values-my/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-my/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • အမြန်အားသွင်းနေသည်"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • နှေးကွေးစွာ အားသွင်းနေသည်"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ဘက်ထရီကာကွယ်ရန် အားသွင်းခြင်းကို အကောင်းဆုံးပြင်ဆင်ထားသည်"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • အားသွင်းမှု မကိုက်ညီပါ"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"မီနူးကို နှိပ်၍ လော့ခ်ဖွင့်ပါ။"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"ကွန်ရက်ကို လော့ခ်ချထားသည်"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"ဆင်းမ်မရှိပါ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-nb/strings.xml b/packages/SystemUI/res-keyguard/values-nb/strings.xml
index 3bd4ab74fb8b..9a5e6e580de5 100644
--- a/packages/SystemUI/res-keyguard/values-nb/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-nb/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader raskt"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader sakte"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladingen er optimalisert for å beskytte batteriet"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ukompatibel lading"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Trykk på menyknappen for å låse opp."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Nettverket er låst"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Ingen SIM-kort"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ne/strings.xml b/packages/SystemUI/res-keyguard/values-ne/strings.xml
index 26b28fd148ea..e35e394d2f64 100644
--- a/packages/SystemUI/res-keyguard/values-ne/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ne/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • द्रुत गतिमा चार्ज गरिँदै छ"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • मन्द गतिमा चार्ज गरिँदै"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ब्याट्री जोगाउन चार्ज गर्ने प्रक्रिया अप्टिमाइज गरिएको छ"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • नमिल्दो चार्जिङ"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"अनलक गर्न मेनु थिच्नुहोस्।"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"नेटवर्क लक भएको छ"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM कार्ड हालिएको छैन"</string>
diff --git a/packages/SystemUI/res-keyguard/values-nl/strings.xml b/packages/SystemUI/res-keyguard/values-nl/strings.xml
index 21c9b13ed8a9..ca5bf2a01062 100644
--- a/packages/SystemUI/res-keyguard/values-nl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-nl/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Snel opladen"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Langzaam opladen"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Opladen geoptimaliseerd om de batterij te beschermen"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Incompatibele oplader"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Druk op Menu om te ontgrendelen."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Netwerk vergrendeld"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Geen simkaart"</string>
diff --git a/packages/SystemUI/res-keyguard/values-or/strings.xml b/packages/SystemUI/res-keyguard/values-or/strings.xml
index d8ca55ccf310..aea95e4bd9c8 100644
--- a/packages/SystemUI/res-keyguard/values-or/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-or/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଦ୍ରୁତ ଭାବେ ଚାର୍ଜ ହେଉଛି"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଧୀରେ ଚାର୍ଜ ହେଉଛି"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ବେଟେରୀକୁ ସୁରକ୍ଷିତ ରଖିବା ପାଇଁ ଚାର୍ଜିଂକୁ ଅପ୍ଟିମାଇଜ କରାଯାଇଛି"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଇନକମ୍ପାଟିବଲ ଚାର୍ଜିଂ"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ଅନଲକ୍‌ କରିବା ପାଇଁ ମେନୁକୁ ଦବାନ୍ତୁ।"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"ନେଟୱର୍କକୁ ଲକ୍‌ କରାଯାଇଛି"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"କୌଣସି SIM ନାହିଁ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pa/strings.xml b/packages/SystemUI/res-keyguard/values-pa/strings.xml
index 5bcfd053210f..ac6209e3abe5 100644
--- a/packages/SystemUI/res-keyguard/values-pa/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pa/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਤੇਜ਼ੀ ਨਾਲ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਹੌਲੀ-ਹੌਲੀ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਬੈਟਰੀ ਦੀ ਸੁਰੱਖਿਆ ਲਈ ਚਾਰਜਿੰਗ ਨੂੰ ਸੁਯੋਗ ਬਣਾਇਆ ਗਿਆ"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਗੈਰ-ਅਨੁਰੂਪ ਚਾਰਜਿੰਗ"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ਅਣਲਾਕ ਕਰਨ ਲਈ \"ਮੀਨੂ\" ਦਬਾਓ।"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"ਨੈੱਟਵਰਕ ਲਾਕ ਕੀਤਾ ਗਿਆ"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"ਕੋਈ ਸਿਮ ਨਹੀਂ ਹੈ"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pl/strings.xml b/packages/SystemUI/res-keyguard/values-pl/strings.xml
index 0226297d4268..ebfe22f3dd25 100644
--- a/packages/SystemUI/res-keyguard/values-pl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pl/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Szybkie ładowanie"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wolne ładowanie"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ładowanie zoptymalizowane w celu ochrony baterii"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Niezgodne ładowanie"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Naciśnij Menu, aby odblokować."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Sieć zablokowana"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Brak karty SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
index f4967d15a456..282c40372997 100644
--- a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando rapidamente"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando lentamente"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregamento otimizado para proteger a bateria"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregamento incompatível"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pressione Menu para desbloquear."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Rede bloqueada"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Sem chip"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
index 5d4ddd444ad6..16326dd65148 100644
--- a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar rapidamente…"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar lentamente…"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregamento otimizado para proteger a bateria"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregamento incompatível"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Prima Menu para desbloquear."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Rede bloqueada"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Sem SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pt/strings.xml b/packages/SystemUI/res-keyguard/values-pt/strings.xml
index f4967d15a456..282c40372997 100644
--- a/packages/SystemUI/res-keyguard/values-pt/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando rapidamente"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando lentamente"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregamento otimizado para proteger a bateria"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregamento incompatível"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pressione Menu para desbloquear."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Rede bloqueada"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Sem chip"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ro/strings.xml b/packages/SystemUI/res-keyguard/values-ro/strings.xml
index 844c1062d4cc..a9596fe1f82f 100644
--- a/packages/SystemUI/res-keyguard/values-ro/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ro/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă rapid"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă lent"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Încărcarea este optimizată pentru a proteja bateria"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Încărcare incompatibilă"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Apasă pe Meniu pentru a debloca."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Rețea blocată"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Niciun card SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ru/strings.xml b/packages/SystemUI/res-keyguard/values-ru/strings.xml
index 6957e183d7de..6190ae4d15e8 100644
--- a/packages/SystemUI/res-keyguard/values-ru/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ru/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"Идет быстрая зарядка (<xliff:g id="PERCENTAGE">%s</xliff:g>)"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"Идет медленная зарядка (<xliff:g id="PERCENTAGE">%s</xliff:g>)"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарядка оптимизирована для защиты батареи"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Несовместимое зарядное устройство"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Для разблокировки нажмите \"Меню\"."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Сеть заблокирована"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM-карта отсутствует"</string>
diff --git a/packages/SystemUI/res-keyguard/values-si/strings.xml b/packages/SystemUI/res-keyguard/values-si/strings.xml
index 2402d506b66e..2cac6fec801f 100644
--- a/packages/SystemUI/res-keyguard/values-si/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-si/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • වේගයෙන් ආරෝපණය වෙමින්"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • සෙමින් ආරෝපණය වෙමින්"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • බැටරිය ආරක්ෂා කිරීම සඳහා ආරෝපණය ප්‍රශස්ත කර ඇත"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • නොගැළපෙන ආරෝපණය"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"අගුලු හැරීමට මෙනුව ඔබන්න."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"ජාලය අගුළු දමා ඇත"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM නැත"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sk/strings.xml b/packages/SystemUI/res-keyguard/values-sk/strings.xml
index 9bc746b6d9f5..a893949d10e4 100644
--- a/packages/SystemUI/res-keyguard/values-sk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sk/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa rýchlo"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa pomaly"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíjanie je optimalizované, aby sa chránila batéria"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nekompatibilná nabíjačka"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Odomknete stlačením tlačidla ponuky."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Sieť je zablokovaná"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Žiadna SIM karta"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sl/strings.xml b/packages/SystemUI/res-keyguard/values-sl/strings.xml
index b0a2501c366c..cd4d9440b62e 100644
--- a/packages/SystemUI/res-keyguard/values-sl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sl/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • hitro polnjenje"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • počasno polnjenje"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Polnjenje je optimizirano zaradi zaščite baterije"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Polnjenje z nezdružljivim polnilnikom"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Če želite odkleniti, pritisnite meni."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Omrežje je zaklenjeno"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Ni kartice SIM."</string>
diff --git a/packages/SystemUI/res-keyguard/values-sq/strings.xml b/packages/SystemUI/res-keyguard/values-sq/strings.xml
index 6e1ae2d65f94..b941fd00a2e4 100644
--- a/packages/SystemUI/res-keyguard/values-sq/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sq/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet me shpejtësi"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet ngadalë"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Karikimi u optimizua për të mbrojtur baterinë"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Karikim i papërputhshëm"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Shtyp \"Meny\" për të shkyçur."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Rrjeti është i kyçur"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Nuk ka kartë SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sr/strings.xml b/packages/SystemUI/res-keyguard/values-sr/strings.xml
index f40f9a9fcb69..e4632f3f8717 100644
--- a/packages/SystemUI/res-keyguard/values-sr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sr/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Брзо се пуни"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Споро се пуни"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Пуњење је оптимизовано да би се заштитила батерија"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Некомпатибилно пуњење"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Притисните Мени да бисте откључали."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Мрежа је закључана"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Нема SIM-а"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sv/strings.xml b/packages/SystemUI/res-keyguard/values-sv/strings.xml
index 9d1a51123a0b..8e46838f0b37 100644
--- a/packages/SystemUI/res-keyguard/values-sv/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sv/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas snabbt"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas långsamt"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddningen har optimerats för att skydda batteriet"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inkompatibel laddare"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Lås upp genom att trycka på Meny."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Nätverk låst"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Inget SIM-kort"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sw/strings.xml b/packages/SystemUI/res-keyguard/values-sw/strings.xml
index 86962370be40..9a64f5762f6a 100644
--- a/packages/SystemUI/res-keyguard/values-sw/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sw/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji kwa kasi"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji pole pole"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hali ya kuchaji imeboreshwa ili kulinda betri"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Chaja isiyooana"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Bonyeza Menyu ili kufungua."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Mtandao umefungwa"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Hakuna SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ta/strings.xml b/packages/SystemUI/res-keyguard/values-ta/strings.xml
index cf62c2fb78af..6b9f826ceac9 100644
--- a/packages/SystemUI/res-keyguard/values-ta/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ta/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • வேகமாகச் சார்ஜாகிறது"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • மெதுவாகச் சார்ஜாகிறது"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • பேட்டரியைப் பாதுகாக்க சார்ஜிங் மேம்படுத்தப்பட்டுள்ளது"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • இணக்கமற்ற சார்ஜிங்"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"அன்லாக் செய்ய மெனுவை அழுத்தவும்."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"நெட்வொர்க் பூட்டப்பட்டது"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"சிம் இல்லை"</string>
diff --git a/packages/SystemUI/res-keyguard/values-te/strings.xml b/packages/SystemUI/res-keyguard/values-te/strings.xml
index 8b21761bb371..2922bc6777ce 100644
--- a/packages/SystemUI/res-keyguard/values-te/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-te/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • వేగంగా ఛార్జ్ అవుతోంది"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • నెమ్మదిగా ఛార్జ్ అవుతోంది"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • బ్యాటరీని రక్షించడానికి ఛార్జింగ్ ఆప్టిమైజ్ చేయబడింది"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ఛార్జింగ్ అనుకూలంగా లేదు"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"అన్‌లాక్ చేయడానికి మెనూను నొక్కండి."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"నెట్‌వర్క్ లాక్ చేయబడింది"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM లేదు"</string>
diff --git a/packages/SystemUI/res-keyguard/values-th/strings.xml b/packages/SystemUI/res-keyguard/values-th/strings.xml
index 688ccdb6db78..830e14aa5a5e 100644
--- a/packages/SystemUI/res-keyguard/values-th/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-th/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จอย่างเร็ว"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จอย่างช้าๆ"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ปรับการชาร์จให้เหมาะสมเพื่อถนอมแบตเตอรี่"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ที่ชาร์จใช้ร่วมกันไม่ได้"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"กด \"เมนู\" เพื่อปลดล็อก"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"เครือข่ายถูกล็อก"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"ไม่มี SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-tl/strings.xml b/packages/SystemUI/res-keyguard/values-tl/strings.xml
index 158570b67ec7..e4b6361ae4fb 100644
--- a/packages/SystemUI/res-keyguard/values-tl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-tl/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mabilis na nagcha-charge"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mabagal na nagcha-charge"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Naka-optimize ang pag-charge para protektahan ang baterya"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hindi compatible na pag-charge"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pindutin ang Menu upang i-unlock."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Naka-lock ang network"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Walang SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-tr/strings.xml b/packages/SystemUI/res-keyguard/values-tr/strings.xml
index 0e5a035fd551..028cd37e8e61 100644
--- a/packages/SystemUI/res-keyguard/values-tr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-tr/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hızlı şarj oluyor"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Yavaş şarj oluyor"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Şarj işlemi pili korumak üzere optimize edildi"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Uyumsuz şarj"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Kilidi açmak için Menü\'ye basın."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Ağ kilitli"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM yok"</string>
diff --git a/packages/SystemUI/res-keyguard/values-uk/strings.xml b/packages/SystemUI/res-keyguard/values-uk/strings.xml
index 4f32ee490e44..78187b785d60 100644
--- a/packages/SystemUI/res-keyguard/values-uk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-uk/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Швидке заряджання"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Повільне заряджання"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Заряджання оптимізовано, щоб захистити акумулятор"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Несумісний зарядний пристрій"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Натисніть меню, щоб розблокувати."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Мережу заблоковано"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Немає SIM-карти"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ur/strings.xml b/packages/SystemUI/res-keyguard/values-ur/strings.xml
index 5cc83a1efb7e..34a3eaafd9f8 100644
--- a/packages/SystemUI/res-keyguard/values-ur/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ur/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • تیزی سے چارج ہو رہا ہے"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • آہستہ چارج ہو رہا ہے"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • بیٹری کی حفاظت کے لیے چارجنگ کو بہتر بنایا گیا"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • غیر مطابقت پذیر چارجنگ"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"غیر مقفل کرنے کیلئے مینو دبائیں۔"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"نیٹ ورک مقفل ہو گیا"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"‏کوئی SIM نہیں ہے"</string>
diff --git a/packages/SystemUI/res-keyguard/values-uz/strings.xml b/packages/SystemUI/res-keyguard/values-uz/strings.xml
index 118d7c484f0b..d448467a90a8 100644
--- a/packages/SystemUI/res-keyguard/values-uz/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-uz/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Tezkor quvvat olmoqda"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sekin quvvat olmoqda"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Batareyani himoyalash uchun quvvatlash optimallashtirildi"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Moslanmagan quvvatlash"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Qulfdan chiqarish uchun Menyu tugmasini bosing."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Tarmoq qulflangan"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM kartasiz"</string>
diff --git a/packages/SystemUI/res-keyguard/values-vi/strings.xml b/packages/SystemUI/res-keyguard/values-vi/strings.xml
index 9f20cd39e5ee..dcca1ca1483e 100644
--- a/packages/SystemUI/res-keyguard/values-vi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-vi/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc nhanh"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc chậm"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Quá trình sạc được tối ưu hoá để bảo vệ pin"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bộ sạc không tương thích"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Nhấn vào Menu để mở khóa."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Mạng đã bị khóa"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Không có SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
index bb9f42c7d865..3c41e8cd10bf 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在快速充电"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在慢速充电"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 为保护电池,充电过程已优化"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充电器不兼容"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"按“菜单”即可解锁。"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"网络已锁定"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"没有 SIM 卡"</string>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml
index 2ca666f3be3a..a07082e6bc39 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 快速充電中"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 慢速充電中"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 為保護電池,系統已優化充電"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在使用不兼容的充電器充電"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"按下 [選單] 即可解鎖。"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"網絡已鎖定"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"沒有 SIM 卡"</string>
diff --git a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
index bb9a448db5b2..01bd491121de 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 快速充電中"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 慢速充電中"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 為保護電池,充電效能已最佳化"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在使用不相容的充電器充電"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"按選單鍵解鎖。"</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"網路已鎖定"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"沒有 SIM 卡"</string>
diff --git a/packages/SystemUI/res-keyguard/values-zu/strings.xml b/packages/SystemUI/res-keyguard/values-zu/strings.xml
index 75273fb6d3dc..c6cabf7d9e85 100644
--- a/packages/SystemUI/res-keyguard/values-zu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zu/strings.xml
@@ -31,6 +31,7 @@
<string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ishaja kaningi"</string>
<string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ishaja kancane"</string>
<string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ukushaja kuthuthukisiwe ukuze kuvikelwe ibhethri"</string>
+ <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ukushaja okungahambisani"</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Chofoza Menyu ukuvula."</string>
<string name="keyguard_network_locked_message" msgid="407096292844868608">"Inethiwekhi ivaliwe"</string>
<string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Ayikho i-SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml
index 51f507cfeddb..11b4d79925c6 100644
--- a/packages/SystemUI/res-keyguard/values/strings.xml
+++ b/packages/SystemUI/res-keyguard/values/strings.xml
@@ -56,7 +56,7 @@
<string name="keyguard_plugged_in_charging_limited"><xliff:g id="percentage">%s</xliff:g> • Charging optimized to protect battery</string>
<!-- When the lock screen is showing and the phone plugged in with incompatible charger. -->
- <string name="keyguard_plugged_in_incompatible_charger"><xliff:g id="percentage">%s</xliff:g> • Incompatible charging</string>
+ <string name="keyguard_plugged_in_incompatible_charger"><xliff:g id="percentage">%s</xliff:g> • Issue with charging accessory</string>
<!-- On the keyguard screen, when pattern lock is disabled, only tell them to press menu to unlock. This is shown in small font at the bottom. -->
<string name="keyguard_instructions_when_pattern_disabled">Press Menu to unlock.</string>
diff --git a/packages/SystemUI/res-product/values/strings.xml b/packages/SystemUI/res-product/values/strings.xml
index 75c82867884f..a677c12ced7b 100644
--- a/packages/SystemUI/res-product/values/strings.xml
+++ b/packages/SystemUI/res-product/values/strings.xml
@@ -122,6 +122,12 @@
Try again in <xliff:g id="number">%3$d</xliff:g> seconds.
</string>
+ <!-- Content description of the fingerprint icon when the system-provided fingerprint dialog is showing, to locate the sensor (tablet) for accessibility (not shown on the screen). [CHAR LIMIT=NONE]-->
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet">The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the tablet.\n\nPressing the power button turns off the screen.</string>
+ <!-- Content description of the fingerprint icon when the system-provided fingerprint dialog is showing, to locate the sensor (device) for accessibility (not shown on the screen). [CHAR LIMIT=NONE]-->
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="device">The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the device.\n\nPressing the power button turns off the screen.</string>
+ <!-- Content description of the fingerprint icon when the system-provided fingerprint dialog is showing, to locate the sensor (default) for accessibility (not shown on the screen). [CHAR LIMIT=NONE]-->
+ <string name="security_settings_sfps_enroll_find_sensor_message" product="default">The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the phone.\n\nPressing the power button turns off the screen.</string>
<!-- Text shown when viewing global actions while phone is locked and additional controls are hidden [CHAR LIMIT=NONE] -->
<string name="global_action_lock_message" product="default">Unlock your phone for more options</string>
@@ -134,4 +140,7 @@
<string name="media_transfer_playing_this_device" product="default">Playing on this phone</string>
<!-- Text informing the user that their media is now playing on this tablet device. [CHAR LIMIT=50] -->
<string name="media_transfer_playing_this_device" product="tablet">Playing on this tablet</string>
+
+
+
</resources>
diff --git a/packages/SystemUI/res/drawable/controls_panel_background.xml b/packages/SystemUI/res/drawable/controls_panel_background.xml
index 9092877fc6fa..fc108a5e1e06 100644
--- a/packages/SystemUI/res/drawable/controls_panel_background.xml
+++ b/packages/SystemUI/res/drawable/controls_panel_background.xml
@@ -18,5 +18,5 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#1F1F1F" />
- <corners android:radius="@dimen/notification_corner_radius" />
+ <corners android:radius="@dimen/controls_panel_corner_radius" />
</shape> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/qs_footer_edit_circle.xml b/packages/SystemUI/res/drawable/qs_footer_edit_circle.xml
new file mode 100644
index 000000000000..2e29cae0ca4f
--- /dev/null
+++ b/packages/SystemUI/res/drawable/qs_footer_edit_circle.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 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.
+ -->
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ android:inset="@dimen/qs_footer_action_inset">
+ <ripple
+ android:color="?android:attr/colorControlHighlight">
+ <item android:id="@android:id/mask">
+ <!-- We make this shape a rounded rectangle instead of a oval so that it can animate -->
+ <!-- properly into an app/dialog. -->
+ <shape android:shape="rectangle">
+ <solid android:color="@android:color/white"/>
+ <corners android:radius="@dimen/qs_footer_action_corner_radius"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <corners android:radius="@dimen/qs_footer_action_corner_radius"/>
+ </shape>
+ </item>
+
+ </ripple>
+</inset> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/statusbar_chip_bg.xml b/packages/SystemUI/res/drawable/statusbar_chip_bg.xml
new file mode 100644
index 000000000000..d7de16d7c5bb
--- /dev/null
+++ b/packages/SystemUI/res/drawable/statusbar_chip_bg.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2023 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.
+-->
+
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+ <solid android:color="?androidprv:attr/colorAccentPrimary" />
+ <corners android:radius="@dimen/ongoing_appops_chip_bg_corner_radius" />
+</shape> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/privacy_chip_bg.xml b/packages/SystemUI/res/drawable/statusbar_privacy_chip_bg.xml
index 99c0ab4b6220..99c0ab4b6220 100644
--- a/packages/SystemUI/res/drawable/privacy_chip_bg.xml
+++ b/packages/SystemUI/res/drawable/statusbar_privacy_chip_bg.xml
diff --git a/packages/SystemUI/res/layout/battery_status_chip.xml b/packages/SystemUI/res/layout/battery_status_chip.xml
new file mode 100644
index 000000000000..ff68ac0f9a71
--- /dev/null
+++ b/packages/SystemUI/res/layout/battery_status_chip.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ Copyright (C) 2023 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.
+-->
+
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_gravity="center_vertical|end"
+ tools:parentTag="com.android.systemui.statusbar.BatteryStatusChip">
+
+ <LinearLayout
+ android:id="@+id/rounded_container"
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/ongoing_appops_chip_height"
+ android:layout_gravity="center"
+ android:background="@drawable/statusbar_chip_bg"
+ android:clipToOutline="true"
+ android:gravity="center"
+ android:maxWidth="@dimen/ongoing_appops_chip_max_width"
+ android:minWidth="@dimen/ongoing_appops_chip_min_width">
+
+ <com.android.systemui.battery.BatteryMeterView
+ android:id="@+id/battery_meter_view"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_marginHorizontal="10dp" />
+
+ </LinearLayout>
+</merge> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/combined_qs_header.xml b/packages/SystemUI/res/layout/combined_qs_header.xml
index d68982876448..dffe40b8454a 100644
--- a/packages/SystemUI/res/layout/combined_qs_header.xml
+++ b/packages/SystemUI/res/layout/combined_qs_header.xml
@@ -141,11 +141,14 @@
android:layout_width="wrap_content"
android:layout_height="@dimen/large_screen_shade_header_min_height"
android:gravity="center"
- app:layout_constraintEnd_toEndOf="@id/end_guide"
- app:layout_constraintTop_toTopOf="@id/date"
app:layout_constraintBottom_toBottomOf="@id/date"
- >
- <include layout="@layout/ongoing_privacy_chip"/>
+ app:layout_constraintEnd_toEndOf="@id/end_guide"
+ app:layout_constraintTop_toTopOf="@id/date">
+
+ <com.android.systemui.privacy.OngoingPrivacyChip
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent" />
+
</FrameLayout>
</com.android.systemui.util.NoRemeasureMotionLayout> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/controls_fullscreen.xml b/packages/SystemUI/res/layout/controls_fullscreen.xml
index e08e63b39e59..fa703038cc7e 100644
--- a/packages/SystemUI/res/layout/controls_fullscreen.xml
+++ b/packages/SystemUI/res/layout/controls_fullscreen.xml
@@ -15,19 +15,11 @@
limitations under the License.
-->
-<FrameLayout
+<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/control_detail_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
-
- <LinearLayout
- android:id="@+id/global_actions_controls"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:paddingHorizontal="@dimen/controls_padding_horizontal" />
-
-</FrameLayout>
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/controls_with_favorites.xml b/packages/SystemUI/res/layout/controls_with_favorites.xml
index aa211bf8cfdc..71561c07ebd3 100644
--- a/packages/SystemUI/res/layout/controls_with_favorites.xml
+++ b/packages/SystemUI/res/layout/controls_with_favorites.xml
@@ -13,82 +13,94 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<merge
- xmlns:android="http://schemas.android.com/apk/res/android">
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ tools:orientation="vertical"
+ tools:parentTag="android.widget.LinearLayout">
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_marginBottom="@dimen/controls_header_bottom_margin">
-
- <!-- make sure the header stays centered in the layout by adding a spacer -->
- <Space
- android:id="@+id/controls_spacer"
- android:layout_width="@dimen/controls_header_menu_size"
- android:layout_height="1dp"
- android:visibility="gone" />
-
- <ImageView
- android:id="@+id/controls_close"
- android:contentDescription="@string/accessibility_desc_close"
- android:src="@drawable/ic_close"
- android:background="?android:attr/selectableItemBackgroundBorderless"
- android:tint="@color/control_primary_text"
- android:layout_width="@dimen/controls_header_menu_size"
- android:layout_height="@dimen/controls_header_menu_size"
- android:padding="12dp"
- android:visibility="gone" />
- <!-- need to keep this outer view in order to have a correctly sized anchor
- for the dropdown menu, as well as dropdown background in the right place -->
<LinearLayout
- android:id="@+id/controls_header"
- android:orientation="horizontal"
- android:layout_width="0dp"
- android:layout_weight="1"
- android:minHeight="48dp"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:gravity="center">
- <TextView
- style="@style/Control.Spinner.Header"
- android:clickable="false"
- android:id="@+id/app_or_structure_spinner"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center" />
+ android:paddingHorizontal="@dimen/controls_header_horizontal_padding"
+ android:layout_marginBottom="@dimen/controls_header_bottom_margin"
+ android:orientation="horizontal">
+
+ <!-- make sure the header stays centered in the layout by adding a spacer -->
+ <Space
+ android:id="@+id/controls_spacer"
+ android:layout_width="@dimen/controls_header_menu_button_size"
+ android:layout_height="1dp"
+ android:visibility="gone" />
+
+ <ImageView
+ android:id="@+id/controls_close"
+ android:layout_width="@dimen/controls_header_menu_button_size"
+ android:layout_height="@dimen/controls_header_menu_button_size"
+ android:layout_gravity="center_vertical"
+ android:background="?android:attr/selectableItemBackgroundBorderless"
+ android:contentDescription="@string/accessibility_desc_close"
+ android:padding="12dp"
+ android:src="@drawable/ic_close"
+ android:tint="@color/control_primary_text"
+ android:visibility="gone"
+ tools:visibility="visible" />
+
+ <!-- need to keep this outer view in order to have a correctly sized anchor
+ for the dropdown menu, as well as dropdown background in the right place -->
+ <LinearLayout
+ android:id="@+id/controls_header"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_weight="1"
+ android:gravity="center"
+ android:minHeight="48dp"
+ android:orientation="horizontal">
+
+ <TextView
+ android:id="@+id/app_or_structure_spinner"
+ style="@style/Control.Spinner.Header"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:clickable="false"
+ tools:text="Test app" />
+ </LinearLayout>
+
+ <ImageView
+ android:id="@+id/controls_more"
+ android:layout_width="@dimen/controls_header_menu_button_size"
+ android:layout_height="@dimen/controls_header_menu_button_size"
+ android:layout_gravity="center_vertical"
+ android:background="?android:attr/selectableItemBackgroundBorderless"
+ android:contentDescription="@string/accessibility_menu"
+ android:padding="12dp"
+ android:src="@drawable/ic_more_vert"
+ android:tint="@color/control_more_vert" />
</LinearLayout>
- <ImageView
- android:id="@+id/controls_more"
- android:src="@drawable/ic_more_vert"
- android:layout_width="@dimen/controls_header_menu_size"
- android:layout_height="@dimen/controls_header_menu_size"
- android:padding="12dp"
- android:tint="@color/control_more_vert"
- android:layout_gravity="center"
- android:contentDescription="@string/accessibility_menu"
- android:background="?android:attr/selectableItemBackgroundBorderless" />
- </LinearLayout>
- <ScrollView
+ <ScrollView
android:id="@+id/controls_scroll_view"
android:layout_width="match_parent"
android:layout_height="0dp"
+ android:layout_marginHorizontal="@dimen/controls_content_margin_horizontal"
android:layout_weight="1"
- android:orientation="vertical"
android:clipChildren="true"
+ android:orientation="vertical"
android:paddingHorizontal="16dp"
android:scrollbars="none">
- <include layout="@layout/global_actions_controls_list_view" />
- </ScrollView>
+ <include layout="@layout/global_actions_controls_list_view" />
+
+ </ScrollView>
- <FrameLayout
- android:id="@+id/controls_panel"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1"
- android:background="@drawable/controls_panel_background"
- android:visibility="gone"
- />
+ <FrameLayout
+ android:id="@+id/controls_panel"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_marginHorizontal="@dimen/controls_content_margin_horizontal"
+ android:layout_weight="1"
+ android:background="@drawable/controls_panel_background"
+ android:visibility="gone"
+ tools:visibility="visible" />
</merge>
diff --git a/packages/SystemUI/res/layout/large_screen_shade_header.xml b/packages/SystemUI/res/layout/large_screen_shade_header.xml
deleted file mode 100644
index 3029a2777fd9..000000000000
--- a/packages/SystemUI/res/layout/large_screen_shade_header.xml
+++ /dev/null
@@ -1,100 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2021 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.
--->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:systemui="http://schemas.android.com/apk/res-auto"
- android:id="@+id/split_shade_status_bar"
- android:layout_width="match_parent"
- android:layout_height="@dimen/large_screen_shade_header_height"
- android:minHeight="@dimen/large_screen_shade_header_min_height"
- android:clickable="false"
- android:focusable="true"
- android:paddingLeft="@dimen/large_screen_shade_header_left_padding"
- android:paddingRight="@dimen/qs_panel_padding"
- android:visibility="gone"
- android:theme="@style/Theme.SystemUI.QuickSettings.Header">
-
- <com.android.systemui.statusbar.policy.Clock
- android:id="@+id/clock"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:minWidth="48dp"
- android:minHeight="@dimen/large_screen_shade_header_min_height"
- android:gravity="start|center_vertical"
- android:paddingStart="@dimen/status_bar_left_clock_starting_padding"
- android:paddingEnd="@dimen/status_bar_left_clock_end_padding"
- android:singleLine="true"
- android:textAppearance="@style/TextAppearance.QS.Status" />
-
- <com.android.systemui.statusbar.policy.DateView
- android:id="@+id/date"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="start|center_vertical"
- android:gravity="center_vertical"
- android:singleLine="true"
- android:textAppearance="@style/TextAppearance.QS.Status"
- systemui:datePattern="@string/abbrev_wday_month_day_no_year_alarm" />
-
- <FrameLayout
- android:id="@+id/rightLayout"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:gravity="end">
-
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_gravity="end|center_vertical">
-
- <include
- android:id="@+id/carrier_group"
- layout="@layout/qs_carrier_group"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_gravity="end|center_vertical"
- android:layout_marginStart="8dp"
- android:focusable="false"
- android:minHeight="@dimen/large_screen_shade_header_min_height"
- android:minWidth="48dp" />
-
- <com.android.systemui.statusbar.phone.StatusIconContainer
- android:id="@+id/statusIcons"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:paddingEnd="@dimen/signal_cluster_battery_padding" />
-
- <com.android.systemui.battery.BatteryMeterView
- android:id="@+id/batteryRemainingIcon"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- systemui:textAppearance="@style/TextAppearance.QS.Status" />
- <FrameLayout
- android:id="@+id/privacy_container"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:minHeight="48dp"
- android:layout_weight="1"
- android:paddingStart="16dp">
-
- <include layout="@layout/ongoing_privacy_chip" />
-
- </FrameLayout>
- </LinearLayout>
- </FrameLayout>
-
-</LinearLayout>
diff --git a/packages/SystemUI/res/layout/notif_half_shelf.xml b/packages/SystemUI/res/layout/notif_half_shelf.xml
index 8ba1ff38fd63..37b8ae0f40c4 100644
--- a/packages/SystemUI/res/layout/notif_half_shelf.xml
+++ b/packages/SystemUI/res/layout/notif_half_shelf.xml
@@ -76,7 +76,10 @@
android:layout_height="48dp"
android:layout_width="wrap_content"
android:layout_gravity="center_vertical"
- android:padding="8dp" />
+ android:padding="8dp"
+ android:track="@drawable/settingslib_track_selector"
+ android:thumb="@drawable/settingslib_thumb_selector"
+ android:theme="@style/MainSwitch.Settingslib"/>
</com.android.systemui.statusbar.notification.row.AppControlView>
<!-- ChannelRows get added dynamically -->
@@ -101,7 +104,7 @@
android:minWidth="@dimen/notification_importance_toggle_size"
android:minHeight="@dimen/notification_importance_toggle_size"
android:maxWidth="200dp"
- style="@style/TextAppearance.NotificationInfo.Button"/>
+ style="@style/Widget.Dialog.Button"/>
<TextView
android:id="@+id/done_button"
android:text="@string/inline_ok_button"
@@ -113,7 +116,7 @@
android:minWidth="@dimen/notification_importance_toggle_size"
android:minHeight="@dimen/notification_importance_toggle_size"
android:layout_alignParentEnd="true"
- style="@style/TextAppearance.NotificationInfo.Button"/>
+ style="@style/Widget.Dialog.Button"/>
</RelativeLayout>
</LinearLayout>
</FrameLayout>
diff --git a/packages/SystemUI/res/layout/notif_half_shelf_row.xml b/packages/SystemUI/res/layout/notif_half_shelf_row.xml
index d03cd7e87a2d..190f9994b1dc 100644
--- a/packages/SystemUI/res/layout/notif_half_shelf_row.xml
+++ b/packages/SystemUI/res/layout/notif_half_shelf_row.xml
@@ -85,6 +85,9 @@
android:layout_width="wrap_content"
android:layout_gravity="center_vertical"
android:padding="8dp"
+ android:track="@drawable/settingslib_track_selector"
+ android:thumb="@drawable/settingslib_thumb_selector"
+ android:theme="@style/MainSwitch.Settingslib"
/>
</LinearLayout>
</com.android.systemui.statusbar.notification.row.ChannelRow>
diff --git a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
index d1a2cf4c24b2..2c7467d726b4 100644
--- a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
+++ b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
@@ -16,16 +16,15 @@
-->
-<com.android.systemui.privacy.OngoingPrivacyChip
- xmlns:android="http://schemas.android.com/apk/res/android"
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/privacy_chip"
+ xmlns:tools="http://schemas.android.com/tools"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:layout_gravity="center_vertical|end"
- android:focusable="true"
android:clipChildren="false"
android:clipToPadding="false"
- android:paddingStart="8dp"
+ tools:parentTag="com.android.systemui.privacy.OngoingPrivacyChip">
>
<LinearLayout
@@ -35,8 +34,9 @@
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:gravity="center"
+ android:clipToOutline="true"
+ android:clipToPadding="false"
android:layout_gravity="center"
android:minWidth="@dimen/ongoing_appops_chip_min_width"
- android:maxWidth="@dimen/ongoing_appops_chip_max_width"
- />
-</com.android.systemui.privacy.OngoingPrivacyChip> \ No newline at end of file
+ android:maxWidth="@dimen/ongoing_appops_chip_max_width" />
+</merge> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_footer_impl.xml b/packages/SystemUI/res/layout/qs_footer_impl.xml
index b1d3ed05333b..745cfc6c1655 100644
--- a/packages/SystemUI/res/layout/qs_footer_impl.xml
+++ b/packages/SystemUI/res/layout/qs_footer_impl.xml
@@ -64,7 +64,7 @@
android:layout_width="@dimen/qs_footer_action_button_size"
android:layout_height="@dimen/qs_footer_action_button_size"
android:layout_gravity="center_vertical|end"
- android:background="?android:attr/selectableItemBackground"
+ android:background="@drawable/qs_footer_edit_circle"
android:clickable="true"
android:contentDescription="@string/accessibility_quick_settings_edit"
android:focusable="true"
diff --git a/packages/SystemUI/res/layout/quick_qs_status_icons.xml b/packages/SystemUI/res/layout/quick_qs_status_icons.xml
deleted file mode 100644
index 542a1c9d22bd..000000000000
--- a/packages/SystemUI/res/layout/quick_qs_status_icons.xml
+++ /dev/null
@@ -1,111 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 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.
--->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:systemui="http://schemas.android.com/apk/res-auto"
- android:id="@+id/quick_qs_status_icons"
- android:layout_width="match_parent"
- android:layout_height="@*android:dimen/quick_qs_offset_height"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:minHeight="@dimen/qs_header_row_min_height"
- android:clickable="false"
- android:focusable="true"
- android:theme="@style/Theme.SystemUI.QuickSettings.Header">
-
- <LinearLayout
- android:id="@+id/clock_container"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:orientation="horizontal"
- android:layout_gravity="center_vertical|start"
- android:gravity="center_vertical|start"
- >
-
- <com.android.systemui.statusbar.policy.Clock
- android:id="@+id/clock"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:minHeight="@dimen/qs_header_row_min_height"
- android:gravity="center_vertical|start"
- android:paddingStart="@dimen/status_bar_left_clock_starting_padding"
- android:paddingEnd="@dimen/status_bar_left_clock_end_padding"
- android:singleLine="true"
- android:textAppearance="@style/TextAppearance.QS.Status" />
-
- <com.android.systemui.statusbar.policy.VariableDateView
- android:id="@+id/date_clock"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_marginStart="@dimen/status_bar_left_clock_end_padding"
- android:gravity="center_vertical|start"
- android:singleLine="true"
- android:textAppearance="@style/TextAppearance.QS.Status"
- systemui:longDatePattern="@string/abbrev_wday_month_day_no_year_alarm"
- systemui:shortDatePattern="@string/abbrev_month_day_no_year"
- />
- </LinearLayout>
-
- <include layout="@layout/qs_carrier_group"
- android:id="@+id/carrier_group"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:minHeight="@dimen/qs_header_row_min_height"
- android:minWidth="48dp"
- android:layout_marginStart="8dp"
- android:layout_gravity="end|center_vertical"
- android:focusable="false"/>
-
- <View
- android:id="@+id/separator"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_gravity="center"
- android:layout_marginStart="8dp"
- android:layout_marginEnd="8dp"
- android:visibility="gone"
- />
-
- <FrameLayout
- android:id="@+id/rightLayout"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:gravity="end"
- >
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_gravity="center_vertical|end"
- >
- <com.android.systemui.statusbar.phone.StatusIconContainer
- android:id="@+id/statusIcons"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:paddingEnd="@dimen/signal_cluster_battery_padding" />
-
- <com.android.systemui.battery.BatteryMeterView
- android:id="@+id/batteryRemainingIcon"
- android:layout_height="match_parent"
- android:layout_width="0dp"
- android:layout_weight="1"
- systemui:textAppearance="@style/TextAppearance.QS.Status"
- android:paddingEnd="2dp" />
-
- </LinearLayout>
- </FrameLayout>
-
-</LinearLayout>
diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
index 9fc3f409642b..1749ed403c09 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -33,32 +33,16 @@
android:paddingStart="0dp"
android:elevation="4dp" >
- <!-- Date and privacy. Only visible in QS when not in split shade -->
- <include layout="@layout/quick_status_bar_header_date_privacy"/>
-
- <RelativeLayout
- android:id="@+id/qs_container"
+ <com.android.systemui.qs.QuickQSPanel
+ android:id="@+id/quick_qs_panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_gravity="top"
+ android:layout_marginTop="@dimen/qqs_layout_margin_top"
android:clipChildren="false"
- android:clipToPadding="false">
- <!-- Time, icons and Carrier (only in QS when not in split shade) -->
- <include layout="@layout/quick_qs_status_icons"/>
-
- <com.android.systemui.qs.QuickQSPanel
- android:id="@+id/quick_qs_panel"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_below="@id/quick_qs_status_icons"
- android:layout_marginTop="@dimen/qqs_layout_margin_top"
- android:accessibilityTraversalAfter="@id/quick_qs_status_icons"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:focusable="true"
- android:paddingBottom="@dimen/qqs_layout_padding_bottom"
- android:importantForAccessibility="no">
- </com.android.systemui.qs.QuickQSPanel>
- </RelativeLayout>
+ android:clipToPadding="false"
+ android:focusable="true"
+ android:paddingBottom="@dimen/qqs_layout_padding_bottom"
+ android:importantForAccessibility="no">
+ </com.android.systemui.qs.QuickQSPanel>
</com.android.systemui.qs.QuickStatusBarHeader>
diff --git a/packages/SystemUI/res/layout/quick_status_bar_header_date_privacy.xml b/packages/SystemUI/res/layout/quick_status_bar_header_date_privacy.xml
deleted file mode 100644
index 8b5d953c3fe7..000000000000
--- a/packages/SystemUI/res/layout/quick_status_bar_header_date_privacy.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-** Copyright 2017, 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.
--->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:systemui="http://schemas.android.com/apk/res-auto"
- android:id="@+id/quick_status_bar_date_privacy"
- android:layout_width="match_parent"
- android:layout_height="@*android:dimen/quick_qs_offset_height"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:gravity="center"
- android:layout_gravity="top"
- android:orientation="horizontal"
- android:importantForAccessibility="no"
- android:clickable="true"
- android:minHeight="48dp">
-
- <FrameLayout
- android:id="@+id/date_container"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:minHeight="48dp"
- android:layout_weight="1"
- android:gravity="center_vertical|start" >
-
- <com.android.systemui.statusbar.policy.VariableDateView
- android:id="@+id/date"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="start|center_vertical"
- android:gravity="center_vertical"
- android:singleLine="true"
- android:textAppearance="@style/TextAppearance.QS.Status"
- systemui:longDatePattern="@string/abbrev_wday_month_day_no_year_alarm"
- systemui:shortDatePattern="@string/abbrev_month_day_no_year"
- />
- </FrameLayout>
-
- <!-- We want this to be centered (to align with notches). In order to do that, the following
- has to hold (in portrait):
- * date_container and privacy_container must have the same width and weight
- -->
- <android.widget.Space
- android:id="@+id/space"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_gravity="center_vertical|center_horizontal"
- android:visibility="gone" />
-
- <FrameLayout
- android:id="@+id/privacy_container"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:minHeight="48dp"
- android:layout_weight="1"
- android:gravity="center_vertical|end" >
-
- <include layout="@layout/ongoing_privacy_chip" />
-
- </FrameLayout>
-</LinearLayout>
diff --git a/packages/SystemUI/res/layout/window_magnification_settings_view.xml b/packages/SystemUI/res/layout/window_magnification_settings_view.xml
index 7dfe7c4c72be..ae0f8f46599d 100644
--- a/packages/SystemUI/res/layout/window_magnification_settings_view.xml
+++ b/packages/SystemUI/res/layout/window_magnification_settings_view.xml
@@ -21,7 +21,9 @@
android:layout_height="wrap_content"
android:background="@drawable/accessibility_magnification_setting_view_bg"
android:orientation="vertical"
- android:padding="@dimen/magnification_setting_background_padding">
+ android:padding="@dimen/magnification_setting_background_padding"
+ android:focusable="true"
+ android:contentDescription="@string/accessibility_magnification_settings_panel_description">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res/raw/biometricprompt_rear_landscape_base.json b/packages/SystemUI/res/raw/biometricprompt_rear_landscape_base.json
new file mode 100644
index 000000000000..49c1c40f7f4f
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_rear_landscape_base.json
@@ -0,0 +1 @@
+{"v":"5.8.1","fr":60,"ip":0,"op":21,"w":340,"h":340,"nm":"BiometricPrompt_Rear_Landscape_Base_Foldable","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 18","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[169.478,169.749,0],"ix":2,"l":2},"a":{"a":0,"k":[-48.123,-30.19,0],"ix":1,"l":2},"s":{"a":0,"k":[132,132,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".grey400","cl":"grey400","parent":13,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"black circle matte","parent":13,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".grey904","cl":"grey904","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-62.577,35.536,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-2.552,0.087],[0,0]],"o":[[0,0],[0,-3.287],[0,0],[0,0]],"v":[[-2.301,8.869],[-2.301,-3.772],[2.301,-9.806],[2.301,9.806]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"black circle matte 2","parent":13,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".blue401","cl":"blue401","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-62.577,-27.655,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,3.286],[0,0],[-2.552,0.086],[0,0]],"o":[[0,0],[0,-3.286],[0,0],[-2.552,-0.086]],"v":[[-2.301,16.282],[-2.301,-16.281],[2.301,-22.313],[2.301,22.313]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"black circle matte 3","parent":13,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Finger 2","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":-129,"s":[-67]},{"t":-29,"s":[0]}],"ix":10},"p":{"a":0,"k":[-75.352,41.307,0],"ix":2,"l":2},"a":{"a":0,"k":[94.648,211.307,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[6.72,-5.642],[0,0],[-9.394,-0.562],[-0.298,-0.038]],"o":[[-5.153,4.329],[3.882,-16.05],[0.31,0.019],[-0.044,0.75]],"v":[[0.863,12.222],[-8.931,14.755],[8.005,-15.108],[8.931,-15.021]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[81.486,130.081],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 9","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.459,6.045],[-5.153,4.329],[-0.044,0.75],[3.116,-24.664],[5.23,-22.052],[8.666,11.92],[-2.9,9.135]],"o":[[0,0],[6.72,-5.642],[12.723,1.335],[-2.369,18.762],[-13.993,-5.333],[2.255,-5.502],[1.843,-5.815]],"v":[[-9.99,-18.348],[-0.196,-20.881],[7.872,-48.124],[21.578,-9.331],[12.104,48.124],[-22.574,21.555],[-14.791,-0.206]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[82.545,163.184],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 8","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"black circle matte 4","parent":13,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":".grey903","cl":"grey903","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-18.345,-92.442,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[24.07,0],[0,0],[-8.27,0],[0,0]],"o":[[0,0],[0,8.269],[0,0],[-14.024,-17.379]],"v":[[-29.778,-14.252],[-29.778,-0.721],[-14.805,14.252],[29.778,14.252]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.372549027205,0.388235300779,0.407843142748,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"black circle matte 5","parent":13,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":".grey902","cl":"grey902","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-15.947,-30.19,0],"ix":2,"l":2},"a":{"a":0,"k":[154.053,139.81,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[2.3,0.367],[0,0],[-2.364,0.157],[0,0]],"o":[[0,0],[2.3,-0.367],[0,0],[-2.364,-0.157]],"v":[[-3.5,75.533],[-3.5,-75.533],[3.5,-76.312],[3.5,76.312]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[113.225,139.81],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 7","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,8.269],[0,0],[2.181,-0.187],[0,0],[-2.23,0],[0,42.252],[10.593,13.127],[0,0]],"o":[[0,0],[-2.23,0],[0,0],[2.181,0.187],[42.252,0],[0,-18.182],[0,0],[-8.27,0]],"v":[[-34.946,-62.973],[-34.946,-76.504],[-41.558,-76.201],[-41.558,76.201],[-34.946,76.504],[41.558,0],[24.61,-48],[-19.973,-48]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[156.824,139.81],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 5","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":".black 2","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-48.123,-30.19,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.833],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.167],"y":[0,0,0]},"t":-129,"s":[0,0,100]},{"t":-79,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":".grey700","cl":"grey700","parent":15,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-56.481,-59.936,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[3.767,0],[0,0],[0,-3.767],[0,0],[-3.767,0],[0,0],[0,3.767],[0,0]],"o":[[0,0],[-3.767,0],[0,0],[0,3.767],[0,0],[3.767,0],[0,0],[0,-3.767]],"v":[[46.055,-14.479],[-46.056,-14.479],[-52.876,-7.659],[-52.876,7.658],[-46.056,14.479],[46.055,14.479],[52.876,7.658],[52.876,-7.659]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.372549027205,0.388235300779,0.407843142748,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":".grey901","cl":"grey901","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[16.485,2.727,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[50,50,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[4.184,0],[0,0],[0,0],[0,0],[0,-4.375]],"o":[[0,4.184],[0,0],[0,0],[0,0],[4.375,0],[0,0]],"v":[[114.116,92.129],[106.54,99.705],[7.788,99.705],[7.788,-99.704],[106.161,-99.704],[114.116,-91.749]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[5.707,0],[0,0],[1.894,-1.05],[0.886,0.346],[0,0],[2.166,0],[0,0],[0,-5.707],[0,0],[0,-1.46],[0,0],[-1.133,-0.038],[0,0],[0,-1.459],[0,0],[-1.133,-0.038],[0,0],[-5.708,0],[0,0],[-1.894,1.05],[-0.846,-0.289],[0,0],[-2.166,0],[0,0],[0,5.706],[0,0]],"o":[[0,0],[-2.166,0],[-0.883,0.354],[0,0],[-1.895,-1.05],[0,0],[-5.708,0],[0,0],[-1.133,0.038],[0,0],[0,1.46],[0,0],[-1.133,0.038],[0,0],[0,1.46],[0,0],[0,5.707],[0,0],[2.165,0],[0.833,-0.334],[0,0],[1.894,1.05],[0,0],[5.707,0],[0,0],[0,-5.707]],"v":[[106.16,-102.082],[8.455,-102.082],[2.265,-100.48],[-0.488,-100.468],[-0.519,-100.48],[-6.71,-102.082],[-104.116,-102.082],[-114.45,-91.748],[-114.45,-36.119],[-116.494,-33.44],[-116.494,-18.979],[-114.45,-16.3],[-114.45,-0.877],[-116.494,1.802],[-116.494,28.704],[-114.45,31.383],[-114.45,91.749],[-104.116,102.083],[-6.495,102.083],[-0.305,100.481],[2.294,100.425],[2.395,100.481],[9.872,102.083],[106.161,102.083],[116.494,91.75],[116.494,-91.748]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.529411792755,0.54509806633,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0}],"markers":[{"tm":255,"cm":"","dr":0},{"tm":364,"cm":"","dr":0},{"tm":482,"cm":"","dr":0},{"tm":600,"cm":"","dr":0}]} \ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_rear_portrait_base.json b/packages/SystemUI/res/raw/biometricprompt_rear_portrait_base.json
new file mode 100644
index 000000000000..9ea0d35e1de2
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_rear_portrait_base.json
@@ -0,0 +1 @@
+{"v":"5.8.1","fr":60,"ip":0,"op":21,"w":340,"h":340,"nm":"BiometricPrompt_Rear_Portrait_Base_Foldable","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 18","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[169.478,169.749,0],"ix":2,"l":2},"a":{"a":0,"k":[-48.123,-30.19,0],"ix":1,"l":2},"s":{"a":0,"k":[132,132,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".grey400","cl":"grey400","parent":14,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"black circle matte","parent":14,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".grey904","cl":"grey904","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-62.577,35.536,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-2.552,0.087],[0,0]],"o":[[0,0],[0,-3.287],[0,0],[0,0]],"v":[[-2.301,8.869],[-2.301,-3.772],[2.301,-9.806],[2.301,9.806]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"black circle matte 2","parent":14,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".blue401","cl":"blue401","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-62.577,-27.655,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,3.286],[0,0],[-2.552,0.086],[0,0]],"o":[[0,0],[0,-3.286],[0,0],[-2.552,-0.086]],"v":[[-2.301,16.282],[-2.301,-16.281],[2.301,-22.313],[2.301,22.313]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"black circle matte 3","parent":14,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Finger 3","tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-2,"ix":10},"p":{"a":0,"k":[260.134,83.782,0],"ix":2,"l":2},"a":{"a":0,"k":[302.634,38.782,0],"ix":1,"l":2},"s":{"a":0,"k":[178,178,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.262,5.076],[0,0],[-0.424,-7.095],[-0.028,-0.225]],"o":[[3.269,-3.892],[-12.123,2.932],[0.015,0.234],[0.567,-0.034]],"v":[[9.232,0.652],[11.145,-6.746],[-11.412,6.046],[-11.346,6.746]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[241.281,55.033],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 5","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[4.565,-1.102],[3.269,-3.892],[0.566,-0.033],[-18.63,2.353],[-16.656,3.951],[9.004,6.546],[6.9,-2.19]],"o":[[0,0],[-4.262,5.076],[1.008,9.61],[14.171,-1.79],[-4.028,-10.569],[-4.156,1.703],[-4.392,1.392]],"v":[[-13.858,-7.546],[-15.771,-0.148],[-36.349,5.946],[-7.047,16.299],[36.349,9.142],[16.281,-17.051],[-0.156,-11.172]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[266.285,55.833],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 4","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"black circle matte 4","parent":14,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":".grey903","cl":"grey903","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-18.345,-92.442,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[24.07,0],[0,0],[-8.27,0],[0,0]],"o":[[0,0],[0,8.269],[0,0],[-14.024,-17.379]],"v":[[-29.778,-14.252],[-29.778,-0.721],[-14.805,14.252],[29.778,14.252]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.372549027205,0.388235300779,0.407843142748,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"black circle matte 5","parent":14,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":".grey902","cl":"grey902","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-15.947,-30.19,0],"ix":2,"l":2},"a":{"a":0,"k":[154.053,139.81,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[2.3,0.367],[0,0],[-2.364,0.157],[0,0]],"o":[[0,0],[2.3,-0.367],[0,0],[-2.364,-0.157]],"v":[[-3.5,75.533],[-3.5,-75.533],[3.5,-76.312],[3.5,76.312]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[113.225,139.81],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 7","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,8.269],[0,0],[2.181,-0.187],[0,0],[-2.23,0],[0,42.252],[10.593,13.127],[0,0]],"o":[[0,0],[-2.23,0],[0,0],[2.181,0.187],[42.252,0],[0,-18.182],[0,0],[-8.27,0]],"v":[[-34.946,-62.973],[-34.946,-76.504],[-41.558,-76.201],[-41.558,76.201],[-34.946,76.504],[41.558,0],[24.61,-48],[-19.973,-48]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[156.824,139.81],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 5","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":".black 2","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-48.123,-30.19,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.833],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.167],"y":[0,0,0]},"t":-129,"s":[0,0,100]},{"t":-79,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":".grey700","cl":"grey700","parent":16,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-56.481,-59.936,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[3.767,0],[0,0],[0,-3.767],[0,0],[-3.767,0],[0,0],[0,3.767],[0,0]],"o":[[0,0],[-3.767,0],[0,0],[0,3.767],[0,0],[3.767,0],[0,0],[0,-3.767]],"v":[[46.055,-14.479],[-46.056,-14.479],[-52.876,-7.659],[-52.876,7.658],[-46.056,14.479],[46.055,14.479],[52.876,7.658],[52.876,-7.659]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.372549027205,0.388235300779,0.407843142748,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".grey901","cl":"grey901","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[16.485,2.727,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[50,50,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[4.184,0],[0,0],[0,0],[0,0],[0,-4.375]],"o":[[0,4.184],[0,0],[0,0],[0,0],[4.375,0],[0,0]],"v":[[114.116,92.129],[106.54,99.705],[7.788,99.705],[7.788,-99.704],[106.161,-99.704],[114.116,-91.749]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[5.707,0],[0,0],[1.894,-1.05],[0.886,0.346],[0,0],[2.166,0],[0,0],[0,-5.707],[0,0],[0,-1.46],[0,0],[-1.133,-0.038],[0,0],[0,-1.459],[0,0],[-1.133,-0.038],[0,0],[-5.708,0],[0,0],[-1.894,1.05],[-0.846,-0.289],[0,0],[-2.166,0],[0,0],[0,5.706],[0,0]],"o":[[0,0],[-2.166,0],[-0.883,0.354],[0,0],[-1.895,-1.05],[0,0],[-5.708,0],[0,0],[-1.133,0.038],[0,0],[0,1.46],[0,0],[-1.133,0.038],[0,0],[0,1.46],[0,0],[0,5.707],[0,0],[2.165,0],[0.833,-0.334],[0,0],[1.894,1.05],[0,0],[5.707,0],[0,0],[0,-5.707]],"v":[[106.16,-102.082],[8.455,-102.082],[2.265,-100.48],[-0.488,-100.468],[-0.519,-100.48],[-6.71,-102.082],[-104.116,-102.082],[-114.45,-91.748],[-114.45,-36.119],[-116.494,-33.44],[-116.494,-18.979],[-114.45,-16.3],[-114.45,-0.877],[-116.494,1.802],[-116.494,28.704],[-114.45,31.383],[-114.45,91.749],[-104.116,102.083],[-6.495,102.083],[-0.305,100.481],[2.294,100.425],[2.395,100.481],[9.872,102.083],[106.161,102.083],[116.494,91.75],[116.494,-91.748]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.529411792755,0.54509806633,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0}],"markers":[{"tm":255,"cm":"","dr":0},{"tm":364,"cm":"","dr":0},{"tm":482,"cm":"","dr":0},{"tm":600,"cm":"","dr":0}]} \ No newline at end of file
diff --git a/packages/SystemUI/res/raw/biometricprompt_rear_portrait_reverse_base.json b/packages/SystemUI/res/raw/biometricprompt_rear_portrait_reverse_base.json
new file mode 100644
index 000000000000..f2b259335034
--- /dev/null
+++ b/packages/SystemUI/res/raw/biometricprompt_rear_portrait_reverse_base.json
@@ -0,0 +1 @@
+{"v":"5.8.1","fr":60,"ip":0,"op":21,"w":340,"h":340,"nm":"BiometricPrompt_Rear_Portrait_Reverse_Base_Foldable","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 18","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":270,"ix":10},"p":{"a":0,"k":[169.478,169.749,0],"ix":2,"l":2},"a":{"a":0,"k":[-48.123,-30.19,0],"ix":1,"l":2},"s":{"a":0,"k":[132,132,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".grey400","cl":"grey400","parent":13,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.741176486015,0.75686275959,0.776470601559,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"black circle matte","parent":13,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".grey904","cl":"grey904","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-62.577,35.536,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-2.552,0.087],[0,0]],"o":[[0,0],[0,-3.287],[0,0],[0,0]],"v":[[-2.301,8.869],[-2.301,-3.772],[2.301,-9.806],[2.301,9.806]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"black circle matte 2","parent":13,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".blue401","cl":"blue401","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-62.577,-27.655,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,3.286],[0,0],[-2.552,0.086],[0,0]],"o":[[0,0],[0,-3.286],[0,0],[-2.552,-0.086]],"v":[[-2.301,16.282],[-2.301,-16.281],[2.301,-22.313],[2.301,22.313]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"black circle matte 3","parent":13,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Finger 2","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-75.352,41.307,0],"ix":2,"l":2},"a":{"a":0,"k":[94.648,211.307,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[6.72,-5.642],[0,0],[-9.394,-0.562],[-0.298,-0.038]],"o":[[-5.153,4.329],[3.882,-16.05],[0.31,0.019],[-0.044,0.75]],"v":[[0.863,12.222],[-8.931,14.755],[8.005,-15.108],[8.931,-15.021]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.792156875134,0.454901963472,0.376470595598,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[81.486,130.081],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 9","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.459,6.045],[-5.153,4.329],[-0.044,0.75],[3.116,-24.664],[5.23,-22.052],[8.666,11.92],[-2.9,9.135]],"o":[[0,0],[6.72,-5.642],[12.723,1.335],[-2.369,18.762],[-13.993,-5.333],[2.255,-5.502],[1.843,-5.815]],"v":[[-9.99,-18.348],[-0.196,-20.881],[7.872,-48.124],[21.578,-9.331],[12.104,48.124],[-22.574,21.555],[-14.791,-0.206]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.713725507259,0.384313732386,0.282352954149,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[82.545,163.184],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 8","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"black circle matte 4","parent":13,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":".grey903","cl":"grey903","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-18.345,-92.442,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[24.07,0],[0,0],[-8.27,0],[0,0]],"o":[[0,0],[0,8.269],[0,0],[-14.024,-17.379]],"v":[[-29.778,-14.252],[-29.778,-0.721],[-14.805,14.252],[29.778,14.252]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.372549027205,0.388235300779,0.407843142748,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"black circle matte 5","parent":13,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":".grey902","cl":"grey902","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-15.947,-30.19,0],"ix":2,"l":2},"a":{"a":0,"k":[154.053,139.81,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[2.3,0.367],[0,0],[-2.364,0.157],[0,0]],"o":[[0,0],[2.3,-0.367],[0,0],[-2.364,-0.157]],"v":[[-3.5,75.533],[-3.5,-75.533],[3.5,-76.312],[3.5,76.312]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[113.225,139.81],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 7","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,8.269],[0,0],[2.181,-0.187],[0,0],[-2.23,0],[0,42.252],[10.593,13.127],[0,0]],"o":[[0,0],[-2.23,0],[0,0],[2.181,0.187],[42.252,0],[0,-18.182],[0,0],[-8.27,0]],"v":[[-34.946,-62.973],[-34.946,-76.504],[-41.558,-76.201],[-41.558,76.201],[-34.946,76.504],[41.558,0],[24.61,-48],[-19.973,-48]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.525490224361,0.54509806633,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[156.824,139.81],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Layer 5","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":".black 2","cl":"black","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-48.123,-30.19,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.833],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.167],"y":[0,0,0]},"t":-129,"s":[0,0,100]},{"t":-79,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-42.252,0],[0,42.252],[42.252,0],[0,-42.252]],"o":[[42.252,0],[0,-42.252],[-42.252,0],[0,42.252]],"v":[[0,76.504],[76.504,0],[0,-76.504],[-76.504,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":".grey700","cl":"grey700","parent":15,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-56.481,-59.936,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[3.767,0],[0,0],[0,-3.767],[0,0],[-3.767,0],[0,0],[0,3.767],[0,0]],"o":[[0,0],[-3.767,0],[0,0],[0,3.767],[0,0],[3.767,0],[0,0],[0,-3.767]],"v":[[46.055,-14.479],[-46.056,-14.479],[-52.876,-7.659],[-52.876,7.658],[-46.056,14.479],[46.055,14.479],[52.876,7.658],[52.876,-7.659]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.372549027205,0.388235300779,0.407843142748,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":".grey901","cl":"grey901","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[16.485,2.727,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[50,50,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[4.184,0],[0,0],[0,0],[0,0],[0,-4.375]],"o":[[0,4.184],[0,0],[0,0],[0,0],[4.375,0],[0,0]],"v":[[114.116,92.129],[106.54,99.705],[7.788,99.705],[7.788,-99.704],[106.161,-99.704],[114.116,-91.749]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[5.707,0],[0,0],[1.894,-1.05],[0.886,0.346],[0,0],[2.166,0],[0,0],[0,-5.707],[0,0],[0,-1.46],[0,0],[-1.133,-0.038],[0,0],[0,-1.459],[0,0],[-1.133,-0.038],[0,0],[-5.708,0],[0,0],[-1.894,1.05],[-0.846,-0.289],[0,0],[-2.166,0],[0,0],[0,5.706],[0,0]],"o":[[0,0],[-2.166,0],[-0.883,0.354],[0,0],[-1.895,-1.05],[0,0],[-5.708,0],[0,0],[-1.133,0.038],[0,0],[0,1.46],[0,0],[-1.133,0.038],[0,0],[0,1.46],[0,0],[0,5.707],[0,0],[2.165,0],[0.833,-0.334],[0,0],[1.894,1.05],[0,0],[5.707,0],[0,0],[0,-5.707]],"v":[[106.16,-102.082],[8.455,-102.082],[2.265,-100.48],[-0.488,-100.468],[-0.519,-100.48],[-6.71,-102.082],[-104.116,-102.082],[-114.45,-91.748],[-114.45,-36.119],[-116.494,-33.44],[-116.494,-18.979],[-114.45,-16.3],[-114.45,-0.877],[-116.494,1.802],[-116.494,28.704],[-114.45,31.383],[-114.45,91.749],[-104.116,102.083],[-6.495,102.083],[-0.305,100.481],[2.294,100.425],[2.395,100.481],[9.872,102.083],[106.161,102.083],[116.494,91.75],[116.494,-91.748]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.501960813999,0.529411792755,0.54509806633,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-189,"op":711,"st":-189,"bm":0}],"markers":[{"tm":255,"cm":"","dr":0},{"tm":364,"cm":"","dr":0},{"tm":482,"cm":"","dr":0},{"tm":600,"cm":"","dr":0}]} \ No newline at end of file
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 8dad8531001a..f26542690047 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Kennisgewingskerm."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Vinnige instellings."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Kitsinstellings en kennisgewingskerm."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Sluitskerm."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Werksluitskerm"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Maak toe"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Helderheid"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Kleuromkering"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Kleurregstelling"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Lettergrootte"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Bestuur gebruikers"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Klaar"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Maak toe"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Kennisgewings"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Kortpadsleutels"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Wissel sleutelborduitleg"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Vee teks uit"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Kortpaaie"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Soek kortpaaie"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Geen kortpaaie gevind nie"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Stelsel"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Invoer"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Maak apps oop"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Huidige app"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Kry toegang tot kennisgewingskerm"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Neem ’n volle skermskoot"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Kry toegang tot lys met stelsel-/appkortpaaie"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Terug: gaan terug na vorige staat (terugknoppie)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Kry toegang tot tuisskerm"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Oorsig van oop apps"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Beweeg deur onlangse apps (vorentoe)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Beweeg deur onlangse apps (terug)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Kry toegang tot lys met alle apps en soektogte (d.w.s., Search/Lanseerder)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Versteek en wys (weer) taakbalk"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Kry toegang tot stelselinstellings"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Kry toegang tot Google Assistent"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Sluit skerm"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Haal Notas-app op vir vinnige memo"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Verrig veelvuldige stelseltake"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Gaan by verdeelde skerm in met huidige app aan die regterkant"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Gaan by verdeelde skerm in met huidige app aan die linkerkant"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Skakel oor van verdeelde skerm na volskerm"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Tydens verdeelde skerm: verplaas ’n app van een skerm na ’n ander"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Invoer"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Wissel invoertaal (volgende taal)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Wissel invoertaal (vorige taal)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Kry toegang tot emosiekone"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Kry toegang tot steminvoer"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Programme"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Bystand"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Blaaier"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Blaaier (Chrome as verstek)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Kontakte"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"E-pos"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"E-pos (Gmail as verstek)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Musiek"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalender"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Sakrekenaar"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Moenie Steur Nie"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Volumeknoppieskortpad"</string>
<string name="battery" msgid="769686279459897127">"Battery"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"skermopname"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Titelloos"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Bystandmodus"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Lettergrootte"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Maak kleiner"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Maak groter"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Vergrotingvenster"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Vergrotingvensterkontroles"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Zoem in"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Kan nie uitsaai nie"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Kan nie stoor nie. Probeer weer."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Kan nie stoor nie."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Gebruik minstens 4 karakters"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Gebruik minder as 16 karakters"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Bounommer"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Bounommer is na knipbord gekopieer."</string>
<string name="basic_status" msgid="2315371112182658176">"Maak gesprek oop"</string>
@@ -1046,7 +1083,7 @@
<string name="log_access_confirmation_title" msgid="4843557604739943395">"Gee <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> toegang tot alle toestelloglêers?"</string>
<string name="log_access_confirmation_allow" msgid="752147861593202968">"Gee eenmalige toegang"</string>
<string name="log_access_confirmation_deny" msgid="2389461495803585795">"Moenie toelaat nie"</string>
- <string name="log_access_confirmation_body" msgid="6883031912003112634">"Toestelloglêers teken aan wat op jou toestel gebeur. Apps kan hierdie loglêers gebruik om kwessies op te spoor en reg te stel.\n\nSommige loglêers bevat dalk sensitiewe inligting, en daarom moet jy toegang tot alle toestelloglêers net gee aan apps wat jy vertrou. \n\nHierdie app het steeds toegang tot sy eie loglêers as jy nie vir hierdie app toegang tot alle toestelloglêers gee nie. Jou toestelvervaardiger het dalk steeds toegang tot sommige loglêers of inligting op jou toestel."</string>
+ <string name="log_access_confirmation_body" msgid="6883031912003112634">"Toestelloglêers teken aan wat op jou toestel gebeur. Apps kan hierdie loglêers gebruik om kwessies op te spoor en reg te stel.\n\nSommige loglêers bevat dalk sensitiewe inligting, en daarom moet jy net toegang tot alle toestelloglêers gee aan apps wat jy vertrou. \n\nHierdie app het steeds toegang tot sy eie loglêers as jy nie vir hierdie app toegang tot alle toestelloglêers gee nie. Jou toestelvervaardiger het dalk steeds toegang tot sommige loglêers of inligting op jou toestel."</string>
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Kom meer te wete"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Kom meer te wete by <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Maak <xliff:g id="APPNAME">%1$s</xliff:g> oop"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Minstens een toestel beskikbaar is"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Raak en hou kortpad"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Kanselleer"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Draai nou om"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Vou foon oop vir ’n beter selfie"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Draai om na voorste skerm vir ’n beter selfie?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Gebruik die agterste kamera vir ’n breër foto met ’n hoër resolusie."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Hierdie skerm sal afskakel"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Wissel skerms nou"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Ontvou foon"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Wissel skerms?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Gebruik die agterste kamera vir hoër resolusie"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Keer die foon om vir hoër resolusie"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Voubare toestel word ontvou"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Voubare toestel word omgekeer"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> batterykrag oor"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Skakel oor na werkprofiel"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Maak toe"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Sluitskerminstellings"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-fi is nie beskikbaar nie"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera is geblokkeer"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera en mikrofoon is geblokkeer"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofoon is geblokkeer"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioriteitmodus is aan"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistent-aandag is aan"</string>
</resources>
diff --git a/packages/SystemUI/res/values-af/tiles_states_strings.xml b/packages/SystemUI/res/values-af/tiles_states_strings.xml
index e60f23329212..662aa717ffc1 100644
--- a/packages/SystemUI/res/values-af/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-af/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Af"</item>
<item msgid="5966994759929723339">"Aan"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Onbeskikbaar"</item>
+ <item msgid="2478289035899842865">"Af"</item>
+ <item msgid="5137565285664080143">"Aan"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index db7fdb2a00ab..949f19a16739 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -198,6 +198,8 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"የማሳወቂያ ጥላ።"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ፈጣን ቅንብሮች።"</string>
+ <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
+ <skip />
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ማያ ገጽ ቆልፍ።"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"የስራ ማያ ገጽ ቁልፍ"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"ዝጋ"</string>
@@ -258,6 +260,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"ብሩህነት"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"ተቃራኒ ቀለም"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"የቀለም ማስተካከያ"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"የቅርጸ-ቁምፊ መጠን"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"ተጠቃሚዎችን ያስተዳድሩ"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"ተከናውኗል"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"ዝጋ"</string>
@@ -613,14 +616,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"ማሳወቂያዎች"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"የቁልፍ ሰሌዳ አቋራጮች"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"የቁልፍ ሰሌዳ ገጽታ ለውጥ"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"ጽሑፍን አጽዳ"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"አቋራጮች"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"አቋራጮችን ይፈልጉ"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"ምንም አቋራጮች አልተገኙም"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"ሥርዓት"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"ግቤት"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"መተግበሪያዎችን ይክፈቱ"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"የአሁኑ መተግበሪያ"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"የማሳወቂያ ጥላ መዳረሻ"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"ሙሉ ቅጽበታዊ ገጽ እይታ ያነሳል"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"የሥርዓት / የመተግበሪያ አቋራጮች ዝርዝር መዳረሻ"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"ተመለስ፦ ወደ ቀዳሚው ሁኔታ ይመለሳል (ተመለስ አዝራር)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"የመነሻ ማያ ገጽ መዳረሻ"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"የክፍት መተግበሪያዎች አጠቃላይ እይታ"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"የቅርብ ጊዜ መተግበሪያዎች ላይ ዑደት ያደርጋል (ወደ ፊት)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"የቅርብ ጊዜ መተግበሪያዎች ላይ ዑደት ያደርጋል (ወደ ኋላ)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"የሁሉም መተግበሪያዎች ዝርዝር እና ፍለጋ መዳረሻ (ማለትም ፍለጋ/ማስጀመሪያ)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"የተግባር አሞሌን ይደብቃል እና (እንደገና) ያሳያል"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"የሥርዓት ቅንብሮች መዳረሻ"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"የGoogle ረዳት መዳረሻ"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"ማያ ገጽ ቁልፍ"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"ለፈጣን ማስታወሻ የማስታወሻዎች መተግበሪያን ያወጣል"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"የሥርዓት ብዙ ተግባራትን በተመሳሳይ ጊዜ ማከናወን"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"ለአርኤችኤስ በአሁኑ መተግበሪያ ወደ የተከፈለ ማያ ገጽ ይገባል"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"ለኤልኤችኤስ በአሁኑ መተግበሪያ ወደ የተከፈለ ማያ ገጽ ይገባል"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"ከየተከፈለ ማያ ገጽ ወደ ሙሉ ገጽ ዕይታ ይቀይራል"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"በተከፈለ ማያ ገጽ ወቅት፦ መተግበሪያን ከአንዱ ወደ ሌላው ይተካል"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"ግቤት"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"የግቤት ቋንቋን ይቀይራል (ቀጣይ ቋንቋ)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"ግቤት ቋንቋን ይቀይራል (ቀዳሚ ቋንቋ)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"የስሜት ገላጭ ምስል መዳረሻ"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"የድምፅ ትየባ መዳረሻ"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"መተግበሪያዎች"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"ረዳት"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"አሳሽ"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"አሳሸ (Chrome እንደ ነባሪ)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"እውቂያዎች"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"ኢሜይል"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"ኢሜይል (Gmail እንደ ነባሪ)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"ኤስኤምኤስ"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"ሙዚቃ"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"የቀን መቁጠሪያ"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"ሒሳብ ማስያ"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"ካርታዎች"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"አትረብሽ"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"የድምፅ አዝራሮች አቋራጭ"</string>
<string name="battery" msgid="769686279459897127">"ባትሪ"</string>
@@ -783,6 +820,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ማያን መቅረጽ"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"ርዕስ የለም"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"ተጠባባቂ"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"የቅርጸ-ቁምፊ መጠን"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"አሳንስ"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"ተለቅ አድርግ"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"የማጉያ መስኮት"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"የማጉያ መስኮት መቆጣጠሪያዎች"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"አጉላ"</string>
@@ -927,10 +967,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"መሰራጨት አይችልም"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"ማስቀመጥ አልተቻለም። እንደገና ይሞክሩ።"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"ማስቀመጥ አልተቻለም።"</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ቢያንስ 4 ቁምፊዎችን ይጠቀሙ"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"ከ16 የሚያንሱ ቁምፊዎችን ይጠቀሙ"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"የግንብ ቁጥር"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"የገንባ ቁጥር ወደ ቅንጥብ ሰሌዳ ተቀድቷል።"</string>
<string name="basic_status" msgid="2315371112182658176">"ውይይት ይክፈቱ"</string>
@@ -1057,11 +1095,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• ቢያንስ አንድ መሣሪያ ይገኛል"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"የይንኩ እና ይያዙ አቋራጭ"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"ይቅር"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"አሁን ገልበጥ"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"ለተሻለ የራስ ፎቶ ስልክን ይዘርጉ"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"ለተሻለ የራስ ፎቶ ወደፊት ማሳያ ይገልበጥ?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"ከፍተኛ ጥራት ላለው ሰፊ ፎቶ የኋለኛውን ካሜራ ይጠቀሙ።"</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ይህ ማያ ገጽ ይጠፋል"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"ማያ ገፆችን አሁን ይቀይሩ"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"ስልክን ይዘርጉ"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"ማያ ገፆች ይቀየሩ?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"ለከፍተኛ ጥራት የኋላ ካሜራውን ይጠቀሙ"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"ለከፍተኛ ጥራት ስልኩን ይቀይሩ"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"መታጠፍ የሚችል መሣሪያ እየተዘረጋ ነው"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"መታጠፍ የሚችል መሣሪያ እየተገለበጠ ነው"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> ባትሪ ይቀራል"</string>
@@ -1073,4 +1111,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"ወደ የሥራ መገለጫ ቀይር"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"ዝጋ"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"የማያ ገጽ ቁልፍ ቅንብሮች"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi አይገኝም"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"ካሜራ ታግዷል"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"ካሜራ እና ማይክሮፎን ታግደዋል"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"ማይክሮፎን ታግዷል"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"የቅድሚያ ሁነታ በርቷል"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"የረዳት ትኩረት በርቷል"</string>
</resources>
diff --git a/packages/SystemUI/res/values-am/tiles_states_strings.xml b/packages/SystemUI/res/values-am/tiles_states_strings.xml
index bbf2d2385f05..e5d68d985792 100644
--- a/packages/SystemUI/res/values-am/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-am/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"ጠፍቷል"</item>
<item msgid="5966994759929723339">"በርቷል"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"አይገኝም"</item>
+ <item msgid="2478289035899842865">"ጠፍቷል"</item>
+ <item msgid="5137565285664080143">"በርቷል"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index ebc38968228f..4ec413e3a9a5 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"مركز الإشعارات."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"الإعدادات السريعة."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"\"الإعدادات السريعة\" و\"مركز الإشعارات\""</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"شاشة القفل."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"شاشة قفل بيانات العمل"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"إغلاق"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"السطوع"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"قلب الألوان"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"تصحيح الألوان"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"حجم الخط"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"إدارة المستخدمين"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"تم"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"إغلاق"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"الإشعارات"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"اختصارات لوحة المفاتيح"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"تبديل تنسيق لوحة المفاتيح"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"محو النص"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"الاختصارات"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"البحث في الاختصارات"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"لم يُعثَر على اختصارات."</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"النظام"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"إدخال"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"فتح التطبيقات"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"التطبيق الحالي"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"الوصول إلى مركز الإشعارات"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"أخذ لقطة شاشة كاملة"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"الوصول إلى قائمة اختصارات التطبيقات والنظام"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"رجوع: العودة إلى الحالة السابقة (زر الرجوع)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"الوصول إلى الشاشة الرئيسية"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"نظرة عامة على التطبيقات المفتوحة"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"التنقّل بين التطبيقات الحديثة (للأمام)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"التنقّل بين التطبيقات الحديثة (للخلف)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"قائمة الوصول لجميع التطبيقات والبحث (أي البحث/مشغّل التطبيقات)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"إظهار أو إخفاء أو إعادة إظهار شريط التطبيقات"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"الوصول إلى إعدادات النظام"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"‏الوصول إلى \"مساعد Google\""</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"شاشة القفل"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"‏سحب تطبيق Notes لإضافة مذكّرة سريعة"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"تعدُّد المهام في النظام"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"الدخول في وضع \"تقسيم الشاشة\" مع عرض التطبيق الحالي على يسار الشاشة"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"الدخول في وضع \"تقسيم الشاشة\" مع عرض التطبيق الحالي على يمين الشاشة"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"التبديل من وضع \"تقسيم الشاشة\" إلى \"ملء الشاشة\""</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"في وضع \"تقسيم الشاشة\": استبدِل التطبيقات من تطبيق إلى آخر"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"إدخال"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"تبديل لغة الإدخال (اللغة التالية)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"تبديل لغة الإدخال (اللغة السابقة)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"الوصول إلى الرموز التعبيرية"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"الوصول إلى ميزة \"الكتابة بالصوت\""</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"التطبيقات"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"التطبيق المساعد"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"المتصفح"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"‏المتصفّح (فتح Chrome تلقائيًا)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"جهات الاتصال"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"البريد الإلكتروني"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"‏البريد الإلكتروني (فتح Gmail تلقائيًا)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"‏الرسائل القصيرة SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"الموسيقى"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"التقويم"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"الآلة الحاسبة"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"‏خرائط Google"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"عدم الإزعاج"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"اختصار أزرار مستوى الصوت"</string>
<string name="battery" msgid="769686279459897127">"البطارية"</string>
@@ -658,7 +694,7 @@
<string name="right_keycode" msgid="2480715509844798438">"رمز مفتاح اليمين"</string>
<string name="left_icon" msgid="5036278531966897006">"رمز اليسار"</string>
<string name="right_icon" msgid="1103955040645237425">"رمز اليمين"</string>
- <string name="drag_to_add_tiles" msgid="8933270127508303672">"اضغط باستمرار مع السحب لإضافة الميزات."</string>
+ <string name="drag_to_add_tiles" msgid="8933270127508303672">"اضغط باستمرار مع السحب لإضافة المربّعات"</string>
<string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"اضغط باستمرار مع السحب لإعادة ترتيب الميزات."</string>
<string name="drag_to_remove_tiles" msgid="4682194717573850385">"اسحب هنا للإزالة"</string>
<string name="drag_to_remove_disabled" msgid="933046987838658850">"الحدّ الأدنى من عدد المربعات الذي تحتاج إليه هو <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g>"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"تسجيل محتوى الشاشة"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"بلا عنوان"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"وضع الاستعداد"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"حجم الخط"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"تصغير الحجم"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"تكبير الحجم"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"نافذة التكبير"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"عناصر التحكم في نافذة التكبير"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"تكبير"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"حدث خطأ. يُرجى إعادة المحاولة."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"جارٍ التحميل"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"جهاز لوحي"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"بثّ الوسائط"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"جارٍ بثّ \"<xliff:g id="APP_LABEL">%1$s</xliff:g>\""</string>
<string name="controls_error_timeout" msgid="794197289772728958">"غير نشط، تحقّق من التطبيق."</string>
<string name="controls_error_removed" msgid="6675638069846014366">"لم يتم العثور عليه."</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"عنصر التحكّم غير متوفّر"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"يتعذّر البث"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"لا يمكن إجراء الحفظ. يُرجى إعادة المحاولة."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"لا يمكن إجراء الحفظ."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"يجب استخدام 4 أحرف على الأقل."</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"يجب أن يحتوي الرمز على أقل من 16 حرفًا."</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"رقم الإصدار"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"تم نسخ رقم الإصدار إلى الحافظة."</string>
<string name="basic_status" msgid="2315371112182658176">"محادثة مفتوحة"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• توفُّر جهاز واحد على الأقل"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"انقر مع الاستمرار على الاختصار."</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"إلغاء"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"قلب الجهاز الآن"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"عليك فتح الهاتف لالتقاط صورة ذاتية بشكل أفضل."</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"أتريد استخدام الكاميرا الأمامية لصورة ذاتية أفضل؟"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"استخدِم الكاميرا الخلفية لالتقاط صورة أعرض وبدرجة دقة أعلى."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"* سيتم إطفاء هذه الشاشة."</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"تبديل الشاشتَين الآن"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"فتح الهاتف"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"هل تريد تبديل الشاشتَين؟"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"للحصول على درجة دقة أعلى، استخدِم الكاميرا الخلفية."</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"للحصول على درجة دقة أعلى، اقلِب الهاتف."</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"جهاز قابل للطي يجري فتحه"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"جهاز قابل للطي يجري قلبه"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"النسبة المئوية المتبقية من شحن البطارية: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"التبديل إلى الملف الشخصي للعمل"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"إغلاق"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"إعدادات شاشة القفل"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"‏لا يتوفّر اتصال Wi-Fi."</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"استخدام الكاميرا محظور."</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"استخدام الكاميرا والميكروفون محظور."</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"استخدام الميكروفون محظور."</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"وضع الأولوية مفعّل."</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"‏ميزة لفت انتباه \"مساعد Google\" مفعّلة."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ar/tiles_states_strings.xml b/packages/SystemUI/res/values-ar/tiles_states_strings.xml
index 44b58f964ce9..31d97076ce4e 100644
--- a/packages/SystemUI/res/values-ar/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ar/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"غير مفعّلة"</item>
<item msgid="5966994759929723339">"مفعَّلة"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"الخيار غير متوفّر"</item>
+ <item msgid="2478289035899842865">"الخيار غير مفعَّل"</item>
+ <item msgid="5137565285664080143">"الخيار مفعَّل"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 533cf594976a..ae2f1e2286b3 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"জাননী পেনেল।"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ক্ষিপ্ৰ ছেটিং।"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ক্ষিপ্ৰ ছেটিং জাননী পেনেল।"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"বন্ধ স্ক্ৰীন।"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"কৰ্মস্থানৰ প্ৰ\'ফাইলৰ লক স্ক্ৰীন"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"বন্ধ কৰক"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"উজ্জ্বলতা"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"ৰং বিপৰীতকৰণ"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"ৰং শুধৰণী"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"ফণ্টৰ আকাৰ"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"ব্যৱহাৰকাৰী পৰিচালনা কৰক"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"সম্পন্ন কৰা হ’ল"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"বন্ধ কৰক"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"জাননীসমূহ"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"কীব\'ৰ্ড শ্বৰ্টকাটসমূহ"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"কীব\'ৰ্ডৰ সজ্জা সলনি কৰক"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"পাঠ মচক"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"শ্বৰ্টকাট"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"সন্ধানৰ শ্বৰ্টকাট"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"কোনো শ্বৰ্টকাট বিচাৰি পোৱা নাই"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"ছিষ্টেম"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"ইনপুট"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"এপ্ খোলক"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"বৰ্তমানৰ এপ্"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"জাননী পেনেল এক্সেছ কৰক"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"এটা সম্পূৰ্ণ স্ক্ৰীনশ্বট লওক"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"ছিষ্টেম / এপৰ শ্বৰ্টকাটসমূহৰ সূচীখন এক্সেছ কৰক"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"উভতি যাওক: পূৰ্বৱৰ্তী অৱস্থালৈ উভতি যাওক (উভতি যাওক বুটাম)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"গৃহ স্ক্ৰীন এক্সেছ কৰক"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"খোলা এপৰ ৰূপৰেখা"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"শেহতীয়া এপ্‌সমূহ এটা এটাকৈ চাওক (আগলৈ)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"শেহতীয়া এপ্‌সমূহ এটা এটাকৈ চাওক (পিছলৈ)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"আটাইবোৰ এপ্ আৰু সন্ধানৰ এক্সেছৰ সূচী (যেনে, Search/Launcher)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"টাস্কবাৰ লুকুৱাওক আৰু (পুনৰ) দেখুৱাওক"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"ছিষ্টেমৰ ছেটিং এক্সেছ কৰক"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Google Assistant এক্সেছ কৰক"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"লক স্ক্ৰীন"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"ক্ষিপ্ৰ মেম’ৰ বাবে Notes এপ্ উলিয়াওক"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"ছিষ্টেম মাল্টিটাস্কিং"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"বৰ্তমানৰ এপৰ জৰিয়তে বিভাজিত স্ক্ৰীনৰ সোঁফালৰ স্ক্ৰীনখনত সোমাওক"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"বৰ্তমানৰ এপৰ জৰিয়তে বিভাজিত স্ক্ৰীনৰ বাওঁফালৰ স্ক্ৰীনখনত সোমাওক"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"বিভাজিত স্ক্ৰীনৰ পৰা পূৰ্ণ স্ক্ৰীনলৈ সলনি কৰক"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"বিভাজিত স্ক্ৰীনৰ ব্যৱহাৰ কৰাৰ সময়ত: কোনো এপ্ এখন স্ক্ৰীনৰ পৰা আনখনলৈ নিয়ক"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"ইনপুট"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"ইনপুটৰ ভাষা সলনি কৰক (পৰৱৰ্তী ভাষা)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"ইনপুটৰ ভাষা সলনি কৰক (পূৰ্বৱৰ্তী ভাষা)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"ইম’জি এক্সেছ কৰক"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"ভইচ টাইপিং এক্সেছ কৰক"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"এপ্লিকেশ্বনসমূহ"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"সহায়"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"ব্ৰাউজাৰ"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"ব্ৰাউজাৰ (ডিফ’ল্ট হিচাপে Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"সম্পৰ্কসূচী"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"ইমেইল"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"ইমেইল (ডিফ’ল্ট হিচাপে Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"এছএমএছ"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"সংগীত"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"কেলকুলেটৰ"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"মেপ"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"অসুবিধা নিদিব"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"ভলিউম বুটামসমূহৰ শ্বৰ্টকাট"</string>
<string name="battery" msgid="769686279459897127">"বেটাৰী"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"স্ক্ৰীন ৰেকৰ্ডিং"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"কোনো শিৰোনাম নাই"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"ষ্টেণ্ডবাই"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"ফণ্টৰ আকাৰ"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"সৰু কৰক"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"ডাঙৰ কৰক"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"বিবৰ্ধন ৱিণ্ড’"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"বিবৰ্ধন ৱিণ্ড’ৰ নিয়ন্ত্ৰণসমূহ"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"জুম ইন কৰক"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"কিবা ভুল হ’ল। পুনৰ চেষ্টা কৰক।"</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"ল’ড হৈ আছে"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"টেবলেট"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"আপোনাৰ মিডিয়া কাষ্ট কৰি থকা হৈছে"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"<xliff:g id="APP_LABEL">%1$s</xliff:g> কাষ্ট কৰি থকা হৈছে"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"সক্ৰিয় নহয়, এপ্‌টো পৰীক্ষা কৰক"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"বিচাৰি পোৱা নগ’ল"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"নিয়ন্ত্ৰণটো উপলব্ধ নহয়"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"সম্প্ৰচাৰ কৰিব নোৱাৰি"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"ছেভ কৰিব নোৱাৰি। পুনৰ চেষ্টা কৰক।"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"ছেভ কৰিব নোৱাৰি।"</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"অতি কমেও ৪ টা বৰ্ণ ব্যৱহাৰ কৰক"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"১৬ টাতকৈ কম বৰ্ণ ব্যৱহাৰ কৰক"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"বিল্ডৰ নম্বৰ"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"ক্লিপব’ৰ্ডলৈ বিল্ডৰ নম্বৰ প্ৰতিলিপি কৰা হ’ল।"</string>
<string name="basic_status" msgid="2315371112182658176">"বাৰ্তালাপ খোলক"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• অতি কমেও এটা ডিভাইচ উপলব্ধ"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"শ্বৰ্টকাটটোত স্পৰ্শ কৰি ধৰি ৰাখক"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"বাতিল কৰক"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"এতিয়াই ফ্লিপ কৰক"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"উন্নত ছেল্ফিৰ বাবে ফ’নটো আনফ’ল্ড কৰক"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"উন্নত ছেল্ফিৰ বাবে সন্মুখৰ ডিছপ্লে’ ফ্লিপ কৰিবনে?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"অধিক ৰিজ’লিউশ্বনৰ বহল ফট’ৰ বাবে পিছফালে থকা কেমেৰাটো ব্যৱহাৰ কৰক।"</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ এই স্ক্ৰীনখন অফ হ’ব"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"এতিয়াই স্ক্ৰীন সলনি কৰক"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"ফ’নটো আনফ’ল্ড কৰক"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"স্ক্ৰীন সলনি কৰিবনে?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"অধিক ৰিজ’লিউছনৰ বাবে, পিছফালৰ কেমেৰাটো ব্যৱহাৰ কৰক"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"অধিক ৰিজ’লিউছনৰ বাবে, ফ’নটো লুটিয়াই দিয়ক"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"জপাব পৰা ডিভাইচৰ জাপ খুলি থকা হৈছে"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"জপাব পৰা ডিভাইচৰ ওলোটাই থকা হৈছে"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> বেটাৰী বাকী আছে"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"কৰ্মস্থানৰ প্ৰ’ফাইললৈ সলনি কৰক"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"বন্ধ কৰক"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"লক স্ক্ৰীনৰ ছেটিং"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"ৱাই-ফাই উপলব্ধ নহয়"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"কেমেৰা অৱৰোধ কৰা আছে"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"কেমেৰা আৰু মাইক্ৰ’ফ’ন অৱৰোধ কৰা আছে"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"মাইক্ৰ’ফ’ন অৱৰোধ কৰা আছে"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"অগ্ৰাধিকাৰ দিয়া ম’ড অন আছে"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistantএ আপোনাৰ কথা শুনি আছে"</string>
</resources>
diff --git a/packages/SystemUI/res/values-as/tiles_states_strings.xml b/packages/SystemUI/res/values-as/tiles_states_strings.xml
index 3145341cabe4..a9c3e3b997b7 100644
--- a/packages/SystemUI/res/values-as/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-as/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"অফ আছে"</item>
<item msgid="5966994759929723339">"অন আছে"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"উপলব্ধ নহয়"</item>
+ <item msgid="2478289035899842865">"অফ আছে"</item>
+ <item msgid="5137565285664080143">"অন আছে"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 58ea41b5c0de..33496748d751 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Bildiriş kölgəsi."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Tez ayarlar."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Sürətli ayarlar və Bildiriş göstərişi."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Kilid ekranı."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ekran kilidi"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Qapadın"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Parlaqlıq"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Rəng inversiyası"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Rəng korreksiyası"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Şrift ölçüsü"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"İstifadəçiləri idarə edin"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Hazır"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Bağlayın"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Bildirişlər"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Klaviatura qısa yolları"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Klaviatura düzümünü dəyişin"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Mətni silin"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Qısayollar"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Qısayollar axtarın"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Qısayol tapılmadı"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistem"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Daxiletmə"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Açıq tətbiqlər"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Cari tətbiq"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Bildiriş göstərişinə giriş"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Tam skrinşot çəkin"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Sistem siyahısına/tətbiq qısayollarına giriş"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Geri: əvvəlki vəziyyətə geri qayıdın (geri düyməsi)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Ana ekrana giriş"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Açıq tətbiqlərin icmalı"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Son tətbiqlər arasında keçid edin (irəli)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Son tətbiqlər arasında keçid edin (geri)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Tətbiqlər siyahısına və axtarışa (yəni Axtarış/Başladıcı) giriş"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"İşləmə panelini gizlədin və (yenidən) göstərin"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Sistem ayarlarına giriş"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Google Assistentə giriş"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Kilid ekranı"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Sürətli qeyd üçün Qeydlər tətbiqini yuxarı dartın"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Sistemdə çoxsaylı tapşırıq icrası"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Cari tətbiq sağda olmaqla Bölünmüş ekrana daxil olun"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Cari tətbiq solda olmaqla Bölünmüş ekrana daxil olun"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Bölünmüş ekrandan tam ekrana dəyişin"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Bölünmüş ekran rejimində: tətbiqi birindən digərinə dəyişdirin"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Daxiletmə"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Daxiletmə dilini dəyişin (növbəti dil)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Daxiletmə dilini dəyişin (əvvəlki dil)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Emojiyə giriş"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Səslə yazmaya giriş"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Tətbiqlər"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Yardım"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Brauzer"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Brauzer (defolt olaraq Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Kontaktlar"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"E-poçt"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"E-poçt (defolt olaraq Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Musiqi"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Təqvim"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kalkulyator"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Xəritə"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Narahat Etməyin"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Səs düymələri qısayolu"</string>
<string name="battery" msgid="769686279459897127">"Batareya"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ekran çəkimi"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Başlıq yoxdur"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Gözləmə rejimi"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Şrift ölçüsü"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Kiçildin"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Böyüdün"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Böyütmə Pəncərəsi"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Böyütmə Pəncərəsi Kontrolları"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Yaxınlaşdırın"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"Xəta oldu. Yenə cəhd edin."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Yüklənir"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"planşet"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"Medianız yayımlanır"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"<xliff:g id="APP_LABEL">%1$s</xliff:g> yayımlanır"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Aktiv deyil, tətbiqi yoxlayın"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Tapılmadı"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Nəzarət əlçatan deyil"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Yayımlamaq mümkün deyil"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Yadda saxlamaq mümkün deyil. Yenə cəhd edin."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Yadda saxlamaq mümkün deyil."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Ən azı 4 simvoldan istifadə edin"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Maksimum 16 simvoldan istifadə edin"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Montaj nömrəsi"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Versiya nömrəsi mübadilə buferinə kopyalandı."</string>
<string name="basic_status" msgid="2315371112182658176">"Açıq söhbət"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Ən azı bir cihaz əlçatandır"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Qısayola toxunub saxlayın"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Ləğv edin"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"İndi fırladın"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Daha yaxşı selfi üçün telefonu açın"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Daha yaxşı selfi üçün ön displeyə çevrilsin?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Daha yüksək ayırdetmə dəqiqliyi ilə daha geniş şəkil üçün arxaya baxan kameradan istifadə edin."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Bu ekran deaktiv ediləcək"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"İndi ekranları dəyişin"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Telefonu açın"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Ekranlar dəyişdirilsin?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Daha yüksək ayırdetmə dəqiqliyi üçün arxa kameradan istifadə edin"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Daha yüksək ayırdetmə dəqiqliyi üçün telefonu çevirin"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Qatlana bilən cihaz açılır"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Qatlana bilən cihaz fırladılır"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> enerji qalıb"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"İş profilinə keçin"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Bağlayın"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Kilid ekranı ayarları"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi əlçatan deyil"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera bloklanıb"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera və mikrofon bloklanıb"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon bloklanıb"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioritet rejimi aktivdir"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistent aktivdir"</string>
</resources>
diff --git a/packages/SystemUI/res/values-az/tiles_states_strings.xml b/packages/SystemUI/res/values-az/tiles_states_strings.xml
index fb745b251bc9..d973e4ead3c2 100644
--- a/packages/SystemUI/res/values-az/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-az/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Deaktiv"</item>
<item msgid="5966994759929723339">"Aktiv"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Əlçatan deyil"</item>
+ <item msgid="2478289035899842865">"Deaktiv"</item>
+ <item msgid="5137565285664080143">"Aktiv"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 3161e116cee1..82c9bbdb238e 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Prozor sa obaveštenjima."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Brza podešavanja."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Brza podešavanja i traka sa obaveštenjima."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Zaključan ekran."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Zaključan ekran za posao"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Zatvori"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Osvetljenost"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inverzija boja"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Korekcija boja"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Veličina fonta"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Upravljajte korisnicima"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Gotovo"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Zatvori"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Obaveštenja"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Tasterske prečice"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Promeni raspored tastature"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Obrišite tekst"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Prečice"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Pretražite prečice"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nisu pronađene prečice"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistem"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Unos"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Otvaranje aplik"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Aktuelna aplik"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Pristup traci sa obaveštenjima"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Snimanje ekrana"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Pristup listi prečica za sistem/aplikacije"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Nazad: nazad na prethodno stanje (dugme Nazad)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Pristup početnom ekranu"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Pregled otvorenih aplikacija"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Pregled nedavnih aplikacija (napred)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Pregled nedavnih aplikacija (nazad)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Pristup listi svih alpikacija i pretraga (npr. Pretraga/Pokretač)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Skrivanje i ponovno prikazivanje trake zadataka"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Pristup podešavanjima sistema"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Pristup Google pomoćniku"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Zaključavanje ekrana"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Otvaranje aplikacije Beleške za brzo pravljenje beleške"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Obavljanje više zadataka sistema istovremeno"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Pokretanje podeljenog ekrana za aktuelnu aplikaciju na desnoj strani"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Pokretanje podeljenog ekrana za aktuelnu aplikaciju na levoj strani"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Prelazak sa podeljenog ekrana na ceo ekran"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Tokom podeljenog ekrana: zamena jedne aplikacije drugom"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Unos"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Promena jezika unosa (sledeći jezik)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Promena jezika unosa (prethodni jezik)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Pristup emodžijima"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Pristup unosu teksta glasom"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Aplikacije"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Aplikacija za pomoć"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Pregledač"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Pregledač (podrazumevano Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Kontakti"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Imejl"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Imejl (Gmail kao podrazumevani)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Muzika"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalendar"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kalkulator"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Mape"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Ne uznemiravaj"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Prečica za dugmad za jačinu zvuka"</string>
<string name="battery" msgid="769686279459897127">"Baterija"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"snimanje ekrana"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Bez naslova"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Stanje pripravnosti"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Veličina fonta"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Umanjite"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Uvećajte"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Prozor za uvećanje"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kontrole prozora za uvećanje"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Uvećajte"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"Došlo je do greške. Probajte ponovo."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Učitava se"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"tablet"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"Prebacivanje medija"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"Prebacuje se <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno. Vidite aplikaciju"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nije pronađeno"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Kontrola nije dostupna"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Emitovanje nije uspelo"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Čuvanje nije uspelo. Probajte ponovo."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Čuvanje nije uspelo."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Koristite bar 4 znaka"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Koristite manje od 16 znakova"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Broj verzije"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Broj verzije je kopiran u privremenu memoriju."</string>
<string name="basic_status" msgid="2315371112182658176">"Otvorite konverzaciju"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• da je dostupan barem jedan uređaj"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Dodirnite i zadržite prečicu"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Otkaži"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Obrni"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Otvorite telefon za bolji selfi"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Želite da obrnete na prednji ekran za bolji selfi?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Koristite zadnju kameru da biste snimili širu sliku sa višom rezolucijom."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Ovaj ekran će se isključiti"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Zameni ekrane"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Otvorite telefon"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Želite da zamenite ekrane?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Za veću rezoluciju koristite zadnju kameru"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Za veću rezoluciju obrnite telefon"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Uređaj na preklop se otvara"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Uređaj na preklop se obrće"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Preostalo je još<xliff:g id="PERCENTAGE">%s</xliff:g> baterije"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Pređi na poslovni profil"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Zatvori"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Podešavanja zaključanog ekrana"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"WiFi nije dostupan"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera je blokirana"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera i mikrofon su blokirani"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon je blokiran"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioritetni režim je uključen"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Pomoćnik je u aktivnom stanju"</string>
</resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/tiles_states_strings.xml b/packages/SystemUI/res/values-b+sr+Latn/tiles_states_strings.xml
index b69b06419281..32051ef19743 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Isključeno"</item>
<item msgid="5966994759929723339">"Uključeno"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Nedostupno"</item>
+ <item msgid="2478289035899842865">"Isključeno"</item>
+ <item msgid="5137565285664080143">"Uključeno"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index bf084bde7ca9..dbfb012319b8 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Цень апавяшчэння.."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Хуткія налады."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Хуткія налады і шчыток апавяшчэнняў."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Экран блакіроўкі."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Экран блакіроўкі дзейнасці"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Закрыць"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Яркасць"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Інверсія колераў"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Карэкцыя колераў"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Памер шрыфту"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Кіраваць карыстальнікамі"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Гатова"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Закрыць"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Апавяшчэнні"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Спалучэнні клавіш"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Пераключыць раскладку клавіятуры"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Выдаліць тэкст"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Ярлыкі"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Пошук ярлыкоў"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Ярлыкі не знойдзены"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Сістэма"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Увод"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Адкрытыя праграмы"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Бягучая праграма"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Перайсці да шчытка апавяшчэнняў"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Зрабіць здымак усяго экрана"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Перайсці да спіса сістэмных ярлыкоў і ярлыкоў праграм"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Вярнуцца ў папярэдні стан (кнопка \"Назад\")"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Перайсці на галоўны экран"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Агляд адкрытых праграм"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Перайсці да нядаўніх праграм (пераключэнне ўперад)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Перайсці да нядаўніх праграм (пераключэнне назад)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Перайсці да спісу ўсіх праграм і пошуку (Пошук/Панэль запуску)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Схаваць і (зноў) паказаць панэль задач"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Перайсці да налад сістэмы"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Выклік Памочніка Google"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Экран блакіроўкі"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Выклікаць праграму \"Нататкі\", каб зрабіць запіс"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Шматзадачнасць сістэмы"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Перайсці ў рэжым падзеленага экрана з бягучай праграмай справа"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Перайсці ў рэжым падзеленага экрана з бягучай праграмай злева"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Пераключыцца з рэжыму падзеленага экрана на поўнаэкранны рэжым"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"У рэжыме падзеленага экрана замяніць адну праграму на іншую"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Увод"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Пераключыць мову ўводу (наступная мова)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Пераключыць мову ўводу (папярэдняя мова)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Перайсці да эмодзі"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Актываваць галасавы ўвод"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Праграмы"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Памочнік"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Браўзер"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Браўзер (стандартна выкарыстоўваецца Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Кантакты"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Электронная пошта"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Электронная пошта (стандартна выкарыстоўваецца Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS-паведамленні"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Музыка"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Каляндар"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Калькулятар"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Карты"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Не турбаваць"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Доступ праз кнопкі рэгулявання гучнасці"</string>
<string name="battery" msgid="769686279459897127">"Акумулятар"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"запіс экрана"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Без назвы"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Рэжым чакання"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Памер шрыфту"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Паменшыць"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Павялічыць"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Акно павелічэння"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Налады акна павелічэння"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Павялічыць маштаб"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"Нешта пайшло не так. Паўтарыце спробу."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Ідзе загрузка"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"планшэт"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"Трансляцыя мультымедыйнага змесціва"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"Трансляцыя праграмы \"<xliff:g id="APP_LABEL">%1$s</xliff:g>\""</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Неактыўна, праверце праграму"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Не знойдзена"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Кіраванне недаступнае"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Не ўдалося запусціць трансляцыю"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Не ўдалося захаваць. Паўтарыце спробу."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Не ўдалося захаваць."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Скарыстайце не менш як 4 сімвалы"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Скарыстайце менш за 16 сімвалаў"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Нумар зборкі"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Нумар зборкі скапіраваны ў буфер абмену."</string>
<string name="basic_status" msgid="2315371112182658176">"Адкрытая размова"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Даступная хаця б адна прылада."</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Дакраніцеся і ўтрымлівайце ярлык"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Скасаваць"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Пераключыць"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Каб атрымаць лепшае сэлфі, раскрыйце тэлефон"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Пераключыць на пярэдні дысплэй для лепшага сэлфі?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Каб зрабіць шырэйшае фота з больш высокай раздзяляльнасцю, скарыстайце заднюю камеру."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Гэты экран будзе выключаны"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Пераключыцца на іншы экран"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Раскрыйце тэлефон"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Пераключыцца на іншы экран?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Каб рабіць фота з больш высокай раздзяляльнасцю, выкарыстоўвайце заднюю камеру"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Каб зрабіць фота з больш высокай раздзяляльнасцю, павярніце тэлефон"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Складная прылада ў раскладзеным выглядзе"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Перавернутая складная прылада"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Засталося зараду: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Пераключыцца на працоўны профіль"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Закрыць"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Налады экрана блакіроўкі"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Сетка Wi-Fi недаступная"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камера заблакіравана"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камера і мікрафон заблакіраваны"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Мікрафон заблакіраваны"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Прыярытэтны рэжым уключаны"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Памочнік гатовы выконваць каманды"</string>
</resources>
diff --git a/packages/SystemUI/res/values-be/tiles_states_strings.xml b/packages/SystemUI/res/values-be/tiles_states_strings.xml
index 8fb2da26edc2..e71c29bd15de 100644
--- a/packages/SystemUI/res/values-be/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-be/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Выключана"</item>
<item msgid="5966994759929723339">"Уключана"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Недаступна"</item>
+ <item msgid="2478289035899842865">"Выключана"</item>
+ <item msgid="5137565285664080143">"Уключана"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index d159273013ea..e87b628ae8b3 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Падащ панел с известия."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Бързи настройки."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Падащ панел с бързи настройки и известия."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Заключване на екрана."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Заключен екран на служебния профил"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Затваряне"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Яркост"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Цветове: инверт."</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Корекция на цветове"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Размер на шрифта"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Управление на потребителите"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Готово"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Затваряне"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Известия"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Клавишни комбинации"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Превкл. на клавиат. подредба"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Изчистване на текста"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Клавишни комбинации"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Търсете комбинации"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Няма клавишни комбинации"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Система"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Въвеждане"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Отворени прил."</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Текущо прилож."</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Достъп до падащия панел с известия"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Заснемане на целия екран"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Достъп до списъка с клавишни комбинации за системата/приложенията"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Назад: връщане към предишното състояние (бутон за връщане назад)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Достъп до началния екран"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Общ преглед на отворените приложения"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Преглед на скорошните приложения (напред)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Преглед на скорошните приложения (назад)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Достъп до списъка с прилож. и търсене (т.е. Търсене/стартов панел)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Скриване и (повторно) показване на лентата на задачите"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Достъп до системните настройки"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Достъп до Google Асистент"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Заключване на екрана"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Отваряне на приложението за бележки с цел бързо записване"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Едновременно изпълняване на няколко задачи в системата"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Преминаване към разделен екран с текущото приложение отдясно"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Преминаване към разделен екран с текущото приложение отляво"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Превключване от разделен към цял екран"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"При разделен екран: замяна на дадено приложение с друго"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Въвеждане"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Превключване към следващия език на въвеждане"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Превключване към предишния език на въвеждане"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Достъп до емоджи"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Достъп до функцията за печатане с глас"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Приложения"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Помощно приложение"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Браузър"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Браузър (по подразбиране е Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Контакти"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Електронна поща"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Електронна поща (по подразбиране е Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Музика"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Календар"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Калкулатор"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Карти"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Не безпокойте"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Пряк път към бутоните за силата на звука"</string>
<string name="battery" msgid="769686279459897127">"Батерия"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"записване на екрана"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Няма заглавие"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Режим на готовност"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Размер на шрифта"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Намаляване на размера"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Увеличаване на размера"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Прозорец за увеличение"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Контроли за прозореца за увеличение"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Увеличаване на мащаба"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"Нещо се обърка. Опитайте отново."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Зарежда се"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"таблет"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"Мултимедията се предава"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"<xliff:g id="APP_LABEL">%1$s</xliff:g> се предава"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Неактивно, проверете прилож."</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Не е намерено"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Контролата не е налице"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Предаването не е възможно"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Не може да се запази. Опитайте отново."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Не може да се запази."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Използвайте поне 4 знака"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Използвайте по-малко от 16 знака"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Номер на компилацията"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Номерът на компилацията е копиран в буферната памет."</string>
<string name="basic_status" msgid="2315371112182658176">"Отворен разговор"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Налице е поне едно устройство."</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Докоснете и задръжте прекия път"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Отказ"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Обръщане сега"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Отворете телефона за по-добро селфи"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Да се ползва ли предната камера за по-добро селфи?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Използвайте задната камера за по-широка снимка с по-висока разделителна способност."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Този екран ще се изключи"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Превключване на екраните сега"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Отворете телефона"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Да се превключи ли екранът?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"За по-висока разделителна способност използвайте задната камера"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"За по-висока разделителна способност обърнете телефона"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Разгъване на сгъваемо устройство"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Обръщане на сгъваемо устройство"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Оставаща батерия: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Превключване към служебния потребителски профил"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Затваряне"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Настройки за заключения екран"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi не е налице"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Достъпът до камерата е блокиран"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Достъпът до камерата и микрофона е блокиран"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Достъпът до микрофона е блокиран"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Приоритетният режим е включен"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Функцията за активиране на Асистент е включена"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bg/tiles_states_strings.xml b/packages/SystemUI/res/values-bg/tiles_states_strings.xml
index b85133b6bd43..24b41d23e900 100644
--- a/packages/SystemUI/res/values-bg/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-bg/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Изкл."</item>
<item msgid="5966994759929723339">"Вкл."</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Не е налице"</item>
+ <item msgid="2478289035899842865">"Изключено"</item>
+ <item msgid="5137565285664080143">"Включено"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 4a67a52f7727..2a84e59006ed 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"বিজ্ঞপ্তি শেড৷"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"দ্রুত সেটিংস৷"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"দ্রুত সেটিংস এবং বিজ্ঞপ্তি শেড।"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"লক স্ক্রিন।"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"কর্মস্থলের স্ক্রিন লক"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"বন্ধ করুন"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"উজ্জ্বলতা"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"কালার ইনভার্সন"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"রঙ সংশোধন"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"ফন্ট সাইজ"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"ব্যবহারকারীদের ম্যানেজ করুন"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"সম্পন্ন হয়েছে"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"বন্ধ করুন"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"বিজ্ঞপ্তি"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"কীবোর্ড শর্টকাট"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"কীবোর্ড লে-আউট পাল্টান"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"টেক্সট মুছুন"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"শর্টকাট"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"শর্টকাট সার্চ করুন"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"কোনও শর্টকার্ট পাওয়া যায়নি"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"সিস্টেম"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"ইনপুট"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"খুলে রাখা অ্যাপ"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"বর্তমান অ্যাপ"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"বিজ্ঞপ্তি শেড অ্যাক্সেস করুন"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"সম্পূর্ণ স্ক্রিনশট নিন"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"সিস্টেমের তালিকা / অ্যাপ শর্টকাটের তালিকা অ্যাক্সেস করুন"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"ফিরে আসা: আগের স্ট্যাটাসে ফিরে আসুন (ফিরে যাওয়ার বোতাম)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"হোম স্ক্রিন অ্যাক্সেস করুন"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"এক নজরে অফিসের অ্যাপ"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"সাম্প্রতিক অ্যাপ দেখুন (পরবর্তীতে যান)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"সাম্প্রতিক অ্যাপ দেখুন (আগে ফিরে যান)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"সব অ্যাপ ও সার্চের ফলাফলের তালিকা অ্যাক্সেস করুন (যেমন, সার্চ/লঞ্চার)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"টাস্কবার লুকান এবং (আবার)দেখুন"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"সিস্টেমের সেটিংস অ্যাক্সেস করুন"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Google Assistant অ্যাক্সেস করুন"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"লক স্ক্রিন"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"দ্রুত মেমোর জন্য Notes অ্যাপ উপরের দিকে তুলুন"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"সিস্টেম মাল্টিটাস্কিং"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"ডান দিকে থাকা বর্তমান অ্যাপ ব্যবহার করে স্প্লিট স্ক্রিন যোগ করুন"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"বাঁদিকে থাকা বর্তমান অ্যাপ ব্যবহার করে স্প্লিট স্ক্রিন যোগ করুন"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"স্প্লিট স্ক্রিন থেকে ফুল স্ক্রিনে পাল্টান"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"স্প্লিট স্ক্রিন থাকাকালীন: একটি অ্যাপ থেকে অন্যটিতে পরিবর্তন করুন"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"ইনপুট"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"লেখার ভাষা পাল্টান (পরবর্তী ভাষা)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"লেখার ভাষা পাল্টান (আগের ভাষা)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"ইমোজি অ্যাক্সেস করুন"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"ভয়েস টাইপিং অ্যাক্সেস করুন"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"অ্যাপ্লিকেশন"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"সহযোগিতা"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"ব্রাউজার"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"ব্রাউজার (ডিফল্ট হিসেবে Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"পরিচিতি"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"ইমেল"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"ইমেল (ডিফল্ট হিসেবে Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"সংগীত"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"ক্যালকুলেটর"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"ম্যাপ"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"বিরক্ত করবে না"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"ভলিউম বোতামের শর্টকাট"</string>
<string name="battery" msgid="769686279459897127">"ব্যাটারি"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"স্ক্রিন রেকর্ডিং"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"কোনও শীর্ষক নেই"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"স্ট্যান্ডবাই"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"ফন্ট সাইজ"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"আরও ছোট করুন"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"আরও বড় করুন"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"উইন্ডো বড় করে দেখা"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"উইন্ডো কন্ট্রোল বড় করে দেখা"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"বড় করুন"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"কোনও সমস্যা হয়েছে। আবার চেষ্টা করুন।"</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"লোড করা হচ্ছে"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"ট্যাবলেট"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"আপনার মিডিয়া কাস্ট করা"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"<xliff:g id="APP_LABEL">%1$s</xliff:g> কাস্ট করা হচ্ছে"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"বন্ধ আছে, অ্যাপ চেক করুন"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"খুঁজে পাওয়া যায়নি"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"কন্ট্রোল উপলভ্য নেই"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"সম্প্রচার করা যাচ্ছে না"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"সেভ করা যাচ্ছে না। আবার চেষ্টা করুন।"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"সেভ করা যাচ্ছে না।"</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"কমপক্ষে ৪টি অক্ষর ব্যবহার করুন"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"১৬টির চেয়ে কম অক্ষর ব্যবহার করুন"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"বিল্ড নম্বর"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"বিল্ড নম্বর ক্লিপবোর্ডে কপি করা হয়েছে।"</string>
<string name="basic_status" msgid="2315371112182658176">"খোলা কথোপকথন"</string>
@@ -1048,7 +1083,7 @@
<string name="log_access_confirmation_title" msgid="4843557604739943395">"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g>-কে ডিভাইসের সব লগ অ্যাক্সেসের অনুমতি দিতে চান?"</string>
<string name="log_access_confirmation_allow" msgid="752147861593202968">"এককালীন অ্যাক্সেসের অনুমতি দিন"</string>
<string name="log_access_confirmation_deny" msgid="2389461495803585795">"অনুমতি দেবেন না"</string>
- <string name="log_access_confirmation_body" msgid="6883031912003112634">"ডিভাইস লগে আপনার ডিভাইসে করা অ্যাক্টিভিটি রেকর্ড করা হয়। অ্যাপ সমস্যা খুঁজে তা সমাধান করতে এইসব লগ ব্যবহার করতে পারে।\n\nকিছু লগে সংবেদনশীল তথ্য থাকতে পারে, তাই বিশ্বাস করেন শুধুমাত্র এমন অ্যাপকেই সব ডিভাইসের লগ অ্যাক্সেসের অনুমতি দিন। \n\nআপনি এই অ্যাপকে ডিভাইসের সব লগ অ্যাক্সেস করার অনুমতি না দিলেও, এটি নিজে লগ অ্যাক্সেস করতে পারবে। ডিভাইস প্রস্তুতকারকও আপনার ডিভাইসের কিছু লগ বা তথ্য হয়ত অ্যাক্সেস করতে পারবে।"</string>
+ <string name="log_access_confirmation_body" msgid="6883031912003112634">"ডিভাইস লগে আপনার ডিভাইসে করা অ্যাক্টিভিটি রেকর্ড করা হয়। অ্যাপ, সমস্যা খুঁজে তা সমাধান করতে এইসব লগ ব্যবহার করতে পারে।\n\nকিছু লগে সংবেদনশীল তথ্য থাকতে পারে, তাই বিশ্বাস করেন শুধুমাত্র এমন অ্যাপকেই সব ডিভাইসের লগ অ্যাক্সেসের অনুমতি দিন। \n\nআপনি এই অ্যাপকে ডিভাইসের সব লগ অ্যাক্সেস করার অনুমতি না দিলেও, এটি নিজের লগ অ্যাক্সেস করতে পারবে। ডিভাইস প্রস্তুতকারক এখনও আপনার ডিভাইসের কিছু লগ বা তথ্য হয়ত অ্যাক্সেস করতে পারবে।"</string>
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"আরও জানুন"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"আরও জানতে <xliff:g id="URL">%s</xliff:g>-এ যান"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> খুলুন"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• অন্তত একটি ডিভাইস উপলভ্য"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"শর্টকাট টাচ করে ধরে রাখুন"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"বাতিল করুন"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"এখনই উল্টান"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"আরও ভাল সেলফির জন্য ফোন আনফোল্ড করা"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"আরও ভাল সেলফির জন্য সামনের ক্যামেরায় পাল্টাতে চান?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"আরও ভাল রেজোলিউশন সহ আরও বেশি ওয়াইড ছবির জন্য ব্যাক-ক্যামেরা ব্যবহার করুন।"</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ এই স্ক্রিন বন্ধ হয়ে যাবে"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"এখন স্ক্রিন পাল্টান"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"ফোন আনফোল্ড করুন"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"স্ক্রিন পাল্টাবেন?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"আরও বেশি রেজোলিউশনের জন্য, রিয়ার ক্যামেরা ব্যবহার করুন"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"আরও বেশি রেজোলিউশনের জন্য, ফোন ফ্লিপ করুন"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ফোল্ড করা যায় এমন ডিভাইস খোলা হচ্ছে"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ফোল্ড করা যায় এমন ডিভাইস উল্টানো হচ্ছে"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> ব্যাটারির চার্জ বাকি আছে"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"অফিস প্রোফাইলে পাল্টে নিন"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"বন্ধ করুন"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"লক স্ক্রিন সেটিংস"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"ওয়াই-ফাই উপলভ্য নয়"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"ক্যামেরার অ্যাক্সেস ব্লক করা আছে"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"ক্যামেরা এবং মাইক্রোফোনের অ্যাক্সেস ব্লক করা আছে"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"মাইক্রোফোনের অ্যাক্সেস ব্লক করা আছে"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"\'প্রায়োরিটি\' মোড চালু করা আছে"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"অ্যাসিস্ট্যান্ট আপনার কথা শোনার জন্য চালু করা আছে"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bn/tiles_states_strings.xml b/packages/SystemUI/res/values-bn/tiles_states_strings.xml
index d70afc0f7f4f..59061c223580 100644
--- a/packages/SystemUI/res/values-bn/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-bn/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"বন্ধ আছে"</item>
<item msgid="5966994759929723339">"চালু আছে"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"উপলভ্য নেই"</item>
+ <item msgid="2478289035899842865">"বন্ধ আছে"</item>
+ <item msgid="5137565285664080143">"চালু আছে"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 00cab87686b2..e73eab959822 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Obavještenja sa sjenčenjem."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Brze postavke."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Brze postavke i lokacija za obavještenja."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Zaključan ekran."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Zaključan ekran radnog profila"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Zatvori"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Osvjetljenje"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inverzija boja"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Ispravka boja"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Veličina fonta"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Upravljajte korisnicima"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Gotovo"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Zatvori"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Obavještenja"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Prečice tastature"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Zamijeni raspored tastature"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Brisanje teksta"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Prečice"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Pretraživanje prečica"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nisu pronađene prečice"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistem"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Unos"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Otvorene aplik."</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Trenutna aplik."</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Pristup lokaciji za obavještenja"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Snimanje cijelog ekrana"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Pristup listi prečica sistema/aplikacija"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Nazad: vraćanje na prethodno stanje (dugme za nazad)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Pristup početnom ekranu"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Pregled otvorenih aplikacija"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Pregled nedavnih aplikacija (unaprijed)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Pregled nedavnih aplikacija (unazad)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Pristup listi svih aplikacija i pretraživanje (Pretraživanje/Pokretač)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Sakrivanje i (ponovno) prikazivanje trake zadataka"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Pristup postavkama sistema"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Pristup Google Asistentu"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Zaključavanje ekrana"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Preuzimanje aplikacije Bilješke za brzi podsjetnik"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitasking sistema"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Otvaranje podijeljenog ekrana s trenutnom aplikacijom na desnoj strani"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Otvaranje podijeljenog ekrana s trenutnom aplikacijom na lijevoj strani"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Prebacivanje s podijeljenog ekrana na prikaz preko cijelog ekrana"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Za vrijeme podijeljenog ekrana: zamjena jedne aplikacije drugom"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Unos"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Promjena jezika unosa (sljedeći jezik)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Promjena jezika unosa (prethodni jezik)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Pristup emoji sličicama"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Pristup pisanju govorom"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Aplikacije"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Pomoć"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Preglednik"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Preglednik (Chrome kao zadani)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Kontakti"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"E-pošta"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"E-pošta (Gmail kao zadana)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Muzika"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalendar"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kalkulator"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Mape"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Ne ometaj"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Prečica za dugmad za Jačinu zvuka"</string>
<string name="battery" msgid="769686279459897127">"Baterija"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"snimanje ekrana"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Bez naslova"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Stanje mirovanja"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Veličina fonta"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Smanjivanje"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Povećavanje"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Prozor za uvećavanje"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kontrole prozora za uvećavanje"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Uvećavanje"</string>
@@ -889,7 +928,7 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"Nešto nije uredu. Pokušajte ponovo."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Učitavanje"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"tablet"</string>
- <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"Emitiranje medijskih sadržaja"</string>
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"Emitiranje medija"</string>
<string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"Emitiranje aplikacije <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno, vidite aplikaciju"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nije pronađeno"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Nije moguće emitirati"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Nije moguće sačuvati. Pokušajte ponovo."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Nije moguće sačuvati."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Koristite najmanje 4 znaka"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Koristite manje od 16 znakova"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Broj verzije"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Broj verzije je kopiran u međumemoriju."</string>
<string name="basic_status" msgid="2315371112182658176">"Otvoreni razgovor"</string>
@@ -1044,9 +1081,9 @@
<string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string>
<string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string>
<string name="log_access_confirmation_title" msgid="4843557604739943395">"Dozvoliti aplikaciji <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> da pristupa svim zapisnicima uređaja?"</string>
- <string name="log_access_confirmation_allow" msgid="752147861593202968">"Dozvoli jednokratan pristup"</string>
+ <string name="log_access_confirmation_allow" msgid="752147861593202968">"Dozvoli jednokratni pristup"</string>
<string name="log_access_confirmation_deny" msgid="2389461495803585795">"Nemoj dozvoliti"</string>
- <string name="log_access_confirmation_body" msgid="6883031912003112634">"Zapisnici uređaja bilježe šta se dešava na uređaju. Aplikacije mogu koristiti te zapisnike da pronađu i isprave probleme.\n\nNeki zapisnici mogu sadržavati osjetljive podatke, zato pristup svim zapisnicima uređaja dozvolite samo aplikacijama kojima vjerujete. \n\nAko ne dozvolite ovoj aplikaciji da pristupa svim zapisnicima uređaja, ona i dalje može pristupati svojim zapisnicima. Proizvođač uređaja će možda i dalje biti u stanju pristupiti nekim zapisnicima ili podacima na uređaju."</string>
+ <string name="log_access_confirmation_body" msgid="6883031912003112634">"Zapisnici uređaja bilježe šta se dešava na uređaju. Aplikacije mogu koristiti te zapisnike pronađu i riješe probleme.\n\nNeki zapisnici mogu sadržavati osjetljive podatke, zato pristup svim zapisnicima uređaja dozvolite samo aplikacijama kojima vjerujete. \n\nAko ne dozvolite ovoj aplikaciji da pristupa svim zapisnicima uređaja, ona i dalje može pristupati svojim zapisnicima. Proizvođač uređaja će možda i dalje biti u stanju pristupiti nekim zapisnicima ili podacima na uređaju."</string>
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Saznajte više"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Saznajte više na <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Otvori aplikaciju <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Dostupan je najmanje jedan uređaj"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Dodirnite i zadržite prečicu"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Otkaži"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Obrni sada"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Raširite telefon za bolji selfi"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Obrnuti na prednji ekran radi boljeg selfija?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Koristite zadnju kameru za širu fotografiju veće rezolucije."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Ekran će se isključiti"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Promijenite ekran sada"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Rasklopite telefon"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Promijeniti ekran?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Za višu rezoluciju koristite zadnju kameru"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Za višu rezoluciju obrnite telefon"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Sklopivi uređaj se rasklapa"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Sklopivi uređaj se obrće"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Preostalo baterije: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Pređite na radni profil"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Zatvori"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Postavke zaključavanja ekrana"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"WiFi mreža nije dostupna"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera je blokirana"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera i mikrofon su blokirani"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon je blokiran"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Način rada Prioriteti je uključen"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Pažnja Asistenta je uključena"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bs/tiles_states_strings.xml b/packages/SystemUI/res/values-bs/tiles_states_strings.xml
index b69b06419281..32051ef19743 100644
--- a/packages/SystemUI/res/values-bs/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-bs/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Isključeno"</item>
<item msgid="5966994759929723339">"Uključeno"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Nedostupno"</item>
+ <item msgid="2478289035899842865">"Isključeno"</item>
+ <item msgid="5137565285664080143">"Uključeno"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 64965edebb4b..66d20e4889d0 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Àrea de notificacions"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Configuració ràpida"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Configuració ràpida i àrea de notificacions."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Pantalla de bloqueig"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Pantalla de bloqueig per a la feina"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Tanca"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Brillantor"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inversió de colors"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Correcció de color"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Cos de font"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Gestiona els usuaris"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Fet"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Tanca"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notificacions"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Tecles de drecera"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Canvia disposició de teclat"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Esborra el text"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Dreceres"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Cerca dreceres"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"No s\'ha trobat cap drecera"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistema"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Entrada"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Obre aplicacions"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Aplicació actual"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Accedeix a l\'àrea de notificacions"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Fes una captura de pantalla completa"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Accedeix a la llista de dreceres d\'aplicacions i del sistema"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Enrere: torna a l\'estat anterior (botó Enrere)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Accedeix a la pantalla d\'inici"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Informació general sobre les aplicacions obertes"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Recorre les aplicacions recents (endavant)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Recorre les aplicacions recents (enrere)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Accedeix a la llista de totes les apps i a la cerca (Cerca/Launcher)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Amaga i torna a mostrar la barra de tasques"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Accedeix a la configuració del sistema"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Accedeix a l\'Assistent de Google"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Pantalla de bloqueig"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Obre l\'aplicació Notes per prendre notes ràpides"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitasques del sistema"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Entra al mode de pantalla dividida amb l\'aplicació actual a la dreta"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Entra al mode de pantalla dividida amb l\'aplicació actual a l\'esquerra"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Canvia de pantalla dividida a pantalla completa"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Durant el mode de pantalla dividida: substitueix una app per una altra"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Entrada"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Canvia l\'idioma d\'introducció (idioma següent)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Canvia l\'idioma d\'introducció (idioma anterior)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Accedeix als emojis"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Accedeix a l\'escriptura per veu"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Aplicacions"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Assistència"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Navegador"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Navegador (Chrome com a predeterminat)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Contactes"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Correu electrònic"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Correu electrònic (Gmail com a predeterminat)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Música"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculadora"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"No molestis"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Drecera per als botons de volum"</string>
<string name="battery" msgid="769686279459897127">"Bateria"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"gravació de pantalla"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sense títol"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"En espera"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Cos de font"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Redueix"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Amplia"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Finestra d\'ampliació"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Finestra de controls d\'ampliació"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Amplia"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"S\'ha produït un error. Torna-ho a provar."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"S\'està carregant"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"tauleta"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"S\'està emetent el contingut multimèdia"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"S\'està emetent <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactiu; comprova l\'aplicació"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"No s\'ha trobat"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"El control no està disponible"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"No es pot emetre"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"No es pot desar. Torna-ho a provar."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"No es pot desar."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Utilitza 4 caràcters com a mínim"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Utilitza menys de 16 caràcters"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número de compilació"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"El número de compilació s\'ha copiat al porta-retalls."</string>
<string name="basic_status" msgid="2315371112182658176">"Conversa oberta"</string>
@@ -1048,7 +1083,7 @@
<string name="log_access_confirmation_title" msgid="4843557604739943395">"Vols permetre que <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> accedeixi a tots els registres del dispositiu?"</string>
<string name="log_access_confirmation_allow" msgid="752147861593202968">"Permet l\'accés únic"</string>
<string name="log_access_confirmation_deny" msgid="2389461495803585795">"No permetis"</string>
- <string name="log_access_confirmation_body" msgid="6883031912003112634">"Els registres del dispositiu inclouen informació sobre tot allò que passa al teu dispositiu. Les aplicacions poden utilitzar aquests registres per detectar i corregir problemes.\n\nÉs possible que alguns registres continguin informació sensible; per això només has de donar-hi accés a les aplicacions de confiança. \n\nEncara que no permetis que aquesta aplicació pugui accedir a tots els registres del dispositiu, podrà accedir als seus propis registres. És possible que el fabricant del dispositiu també tingui accés a alguns registres o a informació del teu dispositiu."</string>
+ <string name="log_access_confirmation_body" msgid="6883031912003112634">"Els registres del dispositiu inclouen informació sobre tot allò que passa al teu dispositiu. Les aplicacions poden utilitzar aquests registres per detectar i corregir problemes.\n\nCom que és possible que alguns registres continguin informació sensible, et recomanem que només hi permetis l\'accés a les aplicacions de confiança. \n\nEncara que no permetis que aquesta aplicació accedeixi a tots els registres del dispositiu, podrà accedir als seus propis registres. És possible que el fabricant del dispositiu també tingui accés a alguns registres o a informació del teu dispositiu."</string>
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Més informació"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Més informació a <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Obre <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Almenys un dispositiu està disponible."</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Mantén premuda la drecera"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Cancel·la"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Gira ara"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Desplega el telèfon per fer una millor selfie"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Girar a pantalla frontal per fer millors selfies?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Utilitza la càmera posterior per obtenir una foto més àmplia amb una resolució més alta."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Aquesta pantalla s\'apagarà"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Canvia de pantalla ara"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Desplega el telèfon"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Vols canviar de pantalla?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Per a una resolució més alta, utilitza la càmera posterior"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Per a una resolució més alta, gira el telèfon"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositiu plegable desplegant-se"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositiu plegable girant"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g> de bateria"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Canvia al perfil de treball"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Tanca"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Configuració pantalla de bloqueig"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"No hi ha cap Wi‑Fi disponible"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"La càmera està bloquejada"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"La càmera i el micròfon estan bloquejats"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"El micròfon està bloquejat"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"El mode Prioritat està activat"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"L\'Assistent està activat"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ca/tiles_states_strings.xml b/packages/SystemUI/res/values-ca/tiles_states_strings.xml
index aaf19c7c0cc6..e99926c57324 100644
--- a/packages/SystemUI/res/values-ca/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ca/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Desactivat"</item>
<item msgid="5966994759929723339">"Activat"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"No disponible"</item>
+ <item msgid="2478289035899842865">"Desactivat"</item>
+ <item msgid="5137565285664080143">"Activat"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 98b7a7ddf65a..e61a4d0ae672 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Panel oznámení."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Rychlé nastavení."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Rychlé nastavení a panel oznámení"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Obrazovka uzamčení"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Obrazovka uzamčení pracovního profilu"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Zavřít"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Jas"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Převrácení barev"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Korekce barev"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Velikost písma"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Správa uživatelů"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Hotovo"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Zavřít"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Oznámení"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Klávesové zkratky"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Přepnout rozložení klávesnice"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Vymazat text"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Zkratky"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Vyhledat zkratky"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Žádné zkratky nenalezeny"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Systém"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Vstup"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Otevřené aplikace"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Aktuální aplikace"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Otevřít panel oznámení"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Pořídit snímek celé obrazovky"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Otevřít seznam zkratek do systému / aplikací"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Zpět: vrátit se k předchozímu stavu (tlačítko zpět)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Přejít na plochu"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Přehled otevřených aplikací"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Procházet nedávné aplikace (vpřed)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Procházet nedávné aplikace (zpět)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Otevřít seznam všech aplikací a vyhledávání (např. Vyhledávání/Launcher)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Skrýt a (znovu) zobrazit panel aplikací"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Otevřít systémová nastavení"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Otevřít Asistenta Google"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Uzamknout obrazovku"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Spustit aplikaci Poznámky a udělat rychlý zápis"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Systémový multitasking"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Přepnout na rozdělenou obrazovku s aktuálními aplikacemi napravo"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Přepnout na rozdělenou obrazovku s aktuálními aplikacemi nalevo"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Přepnout z rozdělené obrazovky na celou obrazovku"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"V režimu rozdělené obrazovky: nahradit jednu aplikaci druhou"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Vstup"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Přepnout jazyk vstupu (další jazyk)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Přepnout jazyk vstupu (předchozí jazyk)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Otevřít smajlíky"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Otevřít hlasové zadávání"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Aplikace"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Asistence"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Prohlížeč"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Prohlížeč (výchozí je Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Kontakty"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"E-mail"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"E-mail (výchozí je Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Hudba"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalendář"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kalkulačka"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Mapy"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Nerušit"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Zkratka tlačítek hlasitosti"</string>
<string name="battery" msgid="769686279459897127">"Baterie"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"nahrávání obrazovky"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Bez názvu"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Pohotovostní režim"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Velikost písma"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Zmenšit"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Zvětšit"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Zvětšovací okno"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Ovládací prvky zvětšovacího okna"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Přiblížit"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Vysílání se nezdařilo"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Uložení se nezdařilo. Zkuste to znovu."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Uložení se nezdařilo."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Heslo musí mít alespoň 4 znaky"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Použijte méně než 16 znaků"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Číslo sestavení"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Číslo sestavení bylo zkopírováno do schránky."</string>
<string name="basic_status" msgid="2315371112182658176">"Otevřít konverzaci"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Je k dispozici alespoň jedno zařízení"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Podržte zkratku"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Zrušit"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Otočit"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Rozložte telefon, selfie bude lepší"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Otočit na přední displej pro lepší selfie?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Pomocí zadního fotoaparátu pořiďte širší fotku s vyšším rozlišením."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Tato obrazovka se vypne"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Přepnout obrazovky"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Rozevřete telefon"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Přepnout obrazovky?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Pomocí zadního fotoaparátu dosáhnete vyššího rozlišení"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Otočte telefon, abyste dosáhli vyššího rozlišení"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Rozkládání rozkládacího zařízení"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Otáčení rozkládacího zařízení"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Zbývá <xliff:g id="PERCENTAGE">%s</xliff:g> baterie"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Přepnout na pracovní profil"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Zavřít"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Nastavení obrazovky uzamčení"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Síť Wi-Fi není dostupná"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera je blokována"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera a mikrofon jsou blokovány"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon je blokován"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Režim priority je zapnutý"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Pozornost Asistenta je zapnutá"</string>
</resources>
diff --git a/packages/SystemUI/res/values-cs/tiles_states_strings.xml b/packages/SystemUI/res/values-cs/tiles_states_strings.xml
index 64e83e0c31b8..6359f94112bb 100644
--- a/packages/SystemUI/res/values-cs/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-cs/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Vypnuto"</item>
<item msgid="5966994759929723339">"Zapnuto"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Nedostupné"</item>
+ <item msgid="2478289035899842865">"Vypnuto"</item>
+ <item msgid="5137565285664080143">"Zapnuto"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 75e0f39cdbc5..aa6a480373e2 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Notifikationspanel."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Kvikmenu."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Kvikmenu og notifikationspanel."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Låseskærm."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Låseskærm til arbejde"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Luk"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Lysstyrke"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Ombytning af farver"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Farvekorrigering"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Skriftstørrelse"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Administrer brugere"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Udfør"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Luk"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notifikationer"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Tastaturgenveje"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Skift tastaturlayout"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Ryd tekst"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Genveje"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Søg efter genveje"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Ingen genveje blev fundet"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"System"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Input"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Åbn apps"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Aktuel app"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Åbn notifikationspanel"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Tag et screenshot af hele skærmen"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Åbn liste over system-/appgenveje"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Forrige: Gå tilbage til den forrige tilstand (knappen Tilbage)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Åbn startskærm"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Oversigt over åbne apps"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Gennemgå seneste apps (næste)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Gennemgå seneste apps (forrige)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Åbn liste over alle apps, og søg (dvs. Søg/Starter)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Skjul, og vis proceslinjen (igen)"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Åbn systemindstillinger"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Åbn Google Assistent"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Lås skærm"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Hent appen Notes for at skrive et hurtigt notat"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Systemmultitasking"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Start opdelt skærm med aktuel app til højre"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Start opdelt skærm med aktuel app til venstre"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Skift fra opdelt skærm til fuld skærm"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Ved opdelt skærm: Erstat en app med én app ad gangen"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Input"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Skift inputsprog (næste sprog)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Skift inputsprog (forrige sprog)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Find emojis"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Åbn indtaling"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Applikationer"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Assistance"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Browser"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Browser (Chrome som standard)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Kontakter"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Mail"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Mail (Gmail som standard)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"Sms"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Musik"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalender"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Lommeregner"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Forstyr ikke"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Genvej til lydstyrkeknapper"</string>
<string name="battery" msgid="769686279459897127">"Batteri"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"skærmoptagelse"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Ingen titel"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Standby"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Skriftstørrelse"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Formindsk"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Forstør"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Vindue med forstørrelse"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Vindue med forstørrelsesstyring"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Zoom ind"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"Noget gik galt. Prøv igen."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Indlæser"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"tablet"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"Caster medie"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"Caster <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv. Tjek appen"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ikke fundet"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Styringselement ikke tilgængeligt"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Der kan ikke udsendes en fællesbesked"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Der kan ikke gemmes. Prøv igen."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Der kan ikke gemmes."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Angiv mindst 4 tegn"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Angiv højst 16 tegn"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Buildnummer"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Buildnummeret blev kopieret til udklipsholderen."</string>
<string name="basic_status" msgid="2315371112182658176">"Åben samtale"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Mindst én enhed er tilgængelig"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Hold fingeren på genvejen"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Annuller"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Vend nu"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Fold telefonen ud for at tage en bedre selfie"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Vil du bruge frontkameraet for at få bedre selfie?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Brug bagsidekameraet for at få et bredere billede med højere opløsning."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Denne skærm slukkes"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Skift skærm nu"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Fold telefonen ud"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Vil du skifte skærm?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Brug kameraet på bagsiden for at få højere opløsning"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Vend telefonen for at få højere opløsning"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Foldbar enhed foldes ud"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Foldbar enhed vendes om"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> batteri tilbage"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Skift til arbejdsprofil"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Luk"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Indstillinger for låseskærm"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi er ikke tilgængeligt"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kameraet er blokeret"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Der er blokeret for kameraet og mikrofonen"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofonen er blokeret"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioritetstilstand er aktiveret"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistent lytter"</string>
</resources>
diff --git a/packages/SystemUI/res/values-da/tiles_states_strings.xml b/packages/SystemUI/res/values-da/tiles_states_strings.xml
index f0132dc66130..1daed4cd6864 100644
--- a/packages/SystemUI/res/values-da/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-da/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Fra"</item>
<item msgid="5966994759929723339">"Til"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Ikke tilgængelig"</item>
+ <item msgid="2478289035899842865">"Fra"</item>
+ <item msgid="5137565285664080143">"Til"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index bfeded8469f8..621788aa993c 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Benachrichtigungsleiste"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Schnelleinstellungen"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Schnelleinstellungen und Benachrichtigungsleiste."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Sperrbildschirm"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Sperrbildschirm für Arbeitsprofil"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Schließen"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Helligkeit"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Farbumkehr"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Farbkorrektur"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Schriftgröße"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Nutzer verwalten"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Fertig"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Schließen"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Benachrichtigungen"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Tastenkürzel"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Tastaturlayout wechseln"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Text löschen"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Tastenkombinationen"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Tastenkombinationen suchen"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Keine gefunden"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"System"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Eingabe"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Geöffnete Apps"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Aktuelle App"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Auf Benachrichtigungsleiste zugreifen"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Vollbild-Screenshot aufnehmen"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Auf Liste mit System-/App-Verknüpfungen zugreifen"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Zurück: Vorherigen Zustand wiederherstellen (Schaltfläche „Zurück“)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Auf Startbildschirm zugreifen"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Übersicht über geöffnete Apps"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Zuletzt verwendete Apps vorwärts durchgehen"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Zuletzt verwendete Apps rückwärts durchgehen"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Auf Liste mit Apps und Suchmaschinen zugreifen, z. B. Google Suche / Google Now Launcher"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Taskleiste ausblenden und (wieder) einblenden"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Auf Systemeinstellungen zugreifen"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Auf Google Assistant zugreifen"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Sperrbildschirm"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Notizen-App für schnelles Memo aufrufen"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"System-Multitasking"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Geteilten Bildschirm aktivieren, aktuelle App rechts"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Geteilten Bildschirm aktivieren, aktuelle App links"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Vom geteilten Bildschirm zum Vollbild wechseln"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Im geteilten Bildschirm: eine App durch eine andere ersetzen"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Eingabe"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Eingabesprache ändern (nächste Sprache)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Eingabesprache ändern (vorherige Sprache)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Auf Emoji zugreifen"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Auf Spracheingabe zugreifen"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Apps"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Assistent"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Browser"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Browser (Chrome ist Standard)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Kontakte"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"E-Mail"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"E-Mail-Programm (Gmail ist Standard)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Musik"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalender"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Rechner"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Karten"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Bitte nicht stören"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Tastenkombination für Lautstärketasten"</string>
<string name="battery" msgid="769686279459897127">"Akku"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"Bildschirmaufzeichnung"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Kein Titel"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Standby"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Schriftgröße"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Verkleinern"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Vergrößern"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Vergrößerungsfenster"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Einstellungen für Vergrößerungsfenster"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Heranzoomen"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"Ein Fehler ist aufgetreten. Versuch es noch einmal."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Wird geladen"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"Tablet"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"Medien werden gestreamt"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"<xliff:g id="APP_LABEL">%1$s</xliff:g> wird gestreamt"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv – sieh in der App nach"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nicht gefunden"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Steuerelement nicht verfügbar"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Übertragung nicht möglich"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Speichern nicht möglich. Versuche es noch einmal."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Speichern nicht möglich."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Gib mindestens vier Zeichen ein"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Maximal 16 Zeichen möglich"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Build-Nummer"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Build-Nummer in Zwischenablage kopiert."</string>
<string name="basic_status" msgid="2315371112182658176">"Offene Unterhaltung"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Mindestens ein Gerät ist verfügbar"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Verknüpfung berühren &amp; halten"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Abbrechen"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Jetzt umdrehen"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Für ein besseres Selfie Smartphone öffnen"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Für ein besseres Selfie Frontbildschirm verwenden?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Verwende die Rückkamera, um Fotos mit einem weiteren Blickwinkel und höherer Auflösung aufzunehmen."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Dieses Display wird dann ausgeschaltet"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Bildschirm jetzt wechseln"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Smartphone auffalten"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Bildschirm wechseln?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Mit der Rückkamera lassen sich Fotos mit höherer Auflösung aufnehmen"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Smartphone umdrehen, um Fotos mit höherer Auflösung aufzunehmen"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Faltbares Gerät wird geöffnet"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Faltbares Gerät wird umgeklappt"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Akku bei <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1075,4 +1110,16 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Zum Arbeitsprofil wechseln"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Schließen"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Sperrbildschirm-Einstellungen"</string>
+ <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
+ <skip />
+ <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
+ <skip />
+ <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
+ <skip />
+ <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
+ <skip />
+ <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
+ <skip />
+ <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-de/tiles_states_strings.xml b/packages/SystemUI/res/values-de/tiles_states_strings.xml
index bc50e1603ea4..9a087472bd03 100644
--- a/packages/SystemUI/res/values-de/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-de/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Aus"</item>
<item msgid="5966994759929723339">"An"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Nicht verfügbar"</item>
+ <item msgid="2478289035899842865">"Aus"</item>
+ <item msgid="5137565285664080143">"An"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index ffe26bd486de..d81cedb2e400 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Πλαίσιο σκίασης ειδοποιήσεων."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Γρήγορες ρυθμίσεις."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Γρήγορες ρυθμίσεις και πλαίσιο σκίασης ειδοποιήσεων."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Οθόνη κλειδώματος"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Οθόνη κλειδωμένης εργασίας"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Κλείσιμο"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Φωτεινότητα"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Αντιστροφή χρωμάτων"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Διόρθωση χρωμάτων"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Μέγεθος γραμματοσειράς"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Διαχείριση χρηστών"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Τέλος"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Κλείσιμο"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Ειδοποιήσεις"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Συντομεύσεις πληκτρολογίου"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Αλλαγή διάταξης πληκτρολογίου"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Διαγραφή κειμένου"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Συντομεύσεις"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Αναζήτηση συντομεύσεων"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Δεν βρέθηκαν συντομεύσεις"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Σύστημα"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Είσοδος"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Ανοιχτές εφαρμ."</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Τρέχ. εφαρμογή"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Πρόσβαση στο πλαίσιο σκίασης ειδοποιήσεων"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Λήψη πλήρους στιγμιότυπου οθόνης"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Πρόσβαση σε λίστα συστήματος / συντομεύσεις εφαρμογών"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Πίσω: επιστροφή στην προηγούμενη κατάσταση (κουμπί πίσω)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Πρόσβαση στην αρχική οθόνη"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Επισκόπηση ανοιχτών εφαρμογών"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Περιήγηση σε πρόσφατες εφαρμογές (εμπρός)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Περιήγηση σε πρόσφατες εφαρμογές (πίσω)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Πρόσβαση σε λίστα εφαρμογών και αναζήτησης (Αναζήτηση/Εφ. εκκίνησης)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Απόκρυψη και (επαν)εμφάνιση της γραμμής εργαλείων"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Πρόσβαση στις ρυθμίσεις συστήματος"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Πρόσβαση στον Βοηθό Google"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Κλείδωμα οθόνης"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Εμφάνιση εφαρμογής Σημειώσεις για γρήγορη σύνταξη σημείωσης"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Πολυδιεργασία συστήματος"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Ενεργοποίηση διαχωρισμού οθόνης με την τρέχουσα εφαρμογή στα δεξιά"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Ενεργοποίηση διαχωρισμού οθόνης με την τρέχουσα εφαρμογή στα αριστερά"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Εναλλαγή από διαχωρισμό οθόνης σε πλήρη οθόνη"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Κατά τον διαχωρισμό οθόνης: αντικατάσταση μιας εφαρμογής με άλλη"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Είσοδος"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Εναλλαγή γλώσσας εισόδου (επόμενη γλώσσα)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Εναλλαγή γλώσσας εισόδου (προηγούμενη γλώσσα)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Πρόσβαση στα emoji"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Πρόσβαση στη φωνητική πληκτρολόγηση"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Εφαρμογές"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Υποβοήθηση"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Πρόγραμμα περιήγησης"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Πρόγραμμα περιήγησης (Chrome ως προεπιλογή)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Επαφές"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Ηλεκτρονικό ταχυδρομείο"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Ηλεκτρονικό ταχυδρομείο (Gmail ως προεπιλογή)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Μουσική"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Ημερολόγιο"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Αριθμομηχανή"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Χάρτες"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Μην ενοχλείτε"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Συντόμευση κουμπιών έντασης ήχου"</string>
<string name="battery" msgid="769686279459897127">"Μπαταρία"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"εγγραφή οθόνης"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Χωρίς τίτλο"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Κατάσταση αναμονής"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Μέγεθος γραμματοσειράς"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Να μικρύνουν"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Να μεγαλώσουν"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Παράθυρο μεγέθυνσης"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Στοιχεία ελέγχου παραθύρου μεγέθυνσης"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Μεγέθυνση"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Δεν είναι δυνατή η μετάδοση"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Δεν είναι δυνατή η αποθήκευση. Δοκιμάστε ξανά."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Δεν είναι δυνατή η αποθήκευση."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Χρησιμοποιήστε τουλάχιστον 4 χαρακτήρες"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Χρησιμοποιήστε λιγότερους από 16 χαρακτήρες"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Αριθμός έκδοσης"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Ο αριθμός έκδοσης αντιγράφηκε στο πρόχειρο."</string>
<string name="basic_status" msgid="2315371112182658176">"Άνοιγμα συνομιλίας"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Είναι διαθέσιμη τουλάχιστον μία συσκευή"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Παρατεταμένο άγγιγμα συντόμευσης"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Ακύρωση"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Αναστροφή τώρα"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Ξεδιπλώστε το τηλέφωνο για καλύτερη selfie"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Αναστροφή στην μπροστ. οθόνη για καλύτερη selfie;"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Χρησιμοποιήστε την πίσω κάμερα για να βγάλετε μια φωτογραφία με μεγαλύτερο εύρος και υψηλότερη ανάλυση."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"* Αυτή η οθόνη θα απενεργοποιηθεί"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Εναλλαγή οθονών τώρα"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Ξεδιπλώστε το τηλέφωνο"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Αλλαγή οθονών;"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Για υψηλότερη ανάλυση, χρησιμοποιήστε την πίσω κάμερα"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Για υψηλότερη ανάλυση, αναστρέψτε το τηλέφωνο"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Αναδιπλούμενη συσκευή που ξεδιπλώνει"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Αναδιπλούμενη συσκευή που διπλώνει"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Απομένει το <xliff:g id="PERCENTAGE">%s</xliff:g> της μπαταρίας"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Εναλλαγή σε προφίλ εργασίας"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Κλείσιμο"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Ρυθμίσεις κλειδώματος οθόνης"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Δεν υπάρχει διαθέσιμο δίκτυο Wi-Fi"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Η κάμερα έχει αποκλειστεί"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Η κάμερα και το μικρόφωνο έχουν αποκλειστεί"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Το μικρόφωνο έχει αποκλειστεί"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Η λειτουργία προτεραιότητας είναι ενεργοποιημένη"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Ο Βοηθός βρίσκεται σε αναμονή"</string>
</resources>
diff --git a/packages/SystemUI/res/values-el/tiles_states_strings.xml b/packages/SystemUI/res/values-el/tiles_states_strings.xml
index 352af39bfe11..4d94515ac130 100644
--- a/packages/SystemUI/res/values-el/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-el/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Ανενεργό"</item>
<item msgid="5966994759929723339">"Ενεργό"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Μη διαθέσιμο"</item>
+ <item msgid="2478289035899842865">"Ανενεργό"</item>
+ <item msgid="5137565285664080143">"Ενεργό"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index b789da176c47..dc3c8e4ee47b 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Notification shade."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Quick settings."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Quick Settings and notification shade."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Lock screen."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Work lock screen"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Close"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Brightness"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Colour inversion"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Colour correction"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Font size"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Manage users"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Done"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Close"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notifications"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Keyboard shortcuts"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Switch keyboard layout"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Clear text"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Shortcuts"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Search shortcuts"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"No shortcuts found"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"System"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Input"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Open apps"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Current app"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Access notification shade"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Take a full screenshot"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Access list of system/apps shortcuts"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Back: Go back to previous state (back button)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Access home screen"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Overview of open apps"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Cycle through recent apps (forward)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Cycle through recent apps (back)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Access list of all apps and search (i.e. Search/Launcher)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Hide and (re)show taskbar"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Access system settings"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Access Google Assistant"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Lock screen"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Pull up Notes app for quick memo"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"System multitasking"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Enter split screen with current app to right-hand side"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Enter split screen with current app to left-hand screen"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Switch from split screen to full screen"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"During split screen: Replace an app from one to another"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Input"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Switch input language (next language)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Switch input language (previous language)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Access emoji"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Access voice typing"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Applications"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Assist"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Browser"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Browser (Chrome as default)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Contacts"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Email"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Email (Gmail as default)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Music"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculator"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Do Not Disturb"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Volume buttons shortcut"</string>
<string name="battery" msgid="769686279459897127">"Battery"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"screen recording"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"No title"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Standby"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Font size"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Make smaller"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Make larger"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Magnification window"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Magnification window controls"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Zoom in"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Can’t broadcast"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Can’t save. Try again."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Can’t save."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Use at least four characters"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Use fewer than 16 characters"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Build number copied to clipboard."</string>
<string name="basic_status" msgid="2315371112182658176">"Open conversation"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• At least one device is available"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Touch &amp; hold shortcut"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Cancel"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Flip now"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Unfold phone for a better selfie"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Flip to front display for a better selfie?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Use the rear-facing camera for a wider photo with higher resolution."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ This screen will turn off"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Switch screens now"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Unfold phone"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Switch screens?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"For higher resolution, use the rear camera"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"For higher resolution, flip the phone"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Foldable device being unfolded"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Foldable device being flipped around"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> battery remaining"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Switch to work profile"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Close"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Lock screen settings"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi not available"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Camera is blocked"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Camera and microphone blocked"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microphone is blocked"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Priority mode on"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant attention on"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml
index 56cdbef092f2..0cf28684aa48 100644
--- a/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Off"</item>
<item msgid="5966994759929723339">"On"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Unavailable"</item>
+ <item msgid="2478289035899842865">"Off"</item>
+ <item msgid="5137565285664080143">"On"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 4688869d5ac2..9c31722c4a7b 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Notification shade."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Quick settings."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Quick settings and Notification shade."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Lock screen."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Work lock screen"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Close"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Brightness"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Color inversion"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Color correction"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Font size"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Manage users"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Done"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Close"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notifications"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Keyboard Shortcuts"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Switch keyboard layout"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Clear text"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Shortcuts"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Search shortcuts"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"No shortcuts found"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"System"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Input"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Open apps"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Current app"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Access notification shade"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Take a full screenshot"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Access list of system / apps shortcuts"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Back: go back to previous state (back button)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Access home screen"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Overview of open apps"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Cycle through recent apps (forward)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Cycle through recent apps (back)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Access list of all apps and search (i.e. Search/Launcher)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Hide and (re)show taskbar"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Access system settings"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Access Google Assistant"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Lock screen"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Pull up Notes app for quick memo"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"System multitasking"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Enter Split screen with current app to RHS"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Enter Split screen with current app to LHS"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Switch from Split screen to full screen"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"During Split screen: replace an app from one to another"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Input"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Switch input language (next language)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Switch input language (previous language)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Access emoji"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Access voice typing"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Applications"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Assist"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Browser"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Browser (Chrome as default)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Contacts"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Email"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Email (Gmail as default)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Music"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculator"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Do Not Disturb"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Volume buttons shortcut"</string>
<string name="battery" msgid="769686279459897127">"Battery"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"screen recording"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"No title"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Standby"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Font Size"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Make smaller"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Make larger"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Magnification Window"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Magnification Window Controls"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Zoom in"</string>
@@ -1055,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• At least one device is available"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Touch &amp; hold shortcut"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Cancel"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Flip now"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Unfold phone for a better selfie"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Flip to front display for a better selfie?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Use the rear-facing camera for a wider photo with higher resolution."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ This screen will turn off"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Switch screens now"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Unfold phone"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Switch screens?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"For higher resolution, use the rear camera"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"For higher resolution, flip the phone"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Foldable device being unfolded"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Foldable device being flipped around"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> battery remaining"</string>
@@ -1071,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Switch to work profile"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Close"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Lock screen settings"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi not available"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Camera blocked"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Camera and microphone blocked"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microphone blocked"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Priority mode on"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant attention on"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml
index 56cdbef092f2..0cf28684aa48 100644
--- a/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Off"</item>
<item msgid="5966994759929723339">"On"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Unavailable"</item>
+ <item msgid="2478289035899842865">"Off"</item>
+ <item msgid="5137565285664080143">"On"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index b789da176c47..dc3c8e4ee47b 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Notification shade."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Quick settings."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Quick Settings and notification shade."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Lock screen."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Work lock screen"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Close"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Brightness"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Colour inversion"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Colour correction"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Font size"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Manage users"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Done"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Close"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notifications"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Keyboard shortcuts"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Switch keyboard layout"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Clear text"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Shortcuts"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Search shortcuts"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"No shortcuts found"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"System"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Input"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Open apps"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Current app"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Access notification shade"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Take a full screenshot"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Access list of system/apps shortcuts"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Back: Go back to previous state (back button)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Access home screen"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Overview of open apps"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Cycle through recent apps (forward)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Cycle through recent apps (back)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Access list of all apps and search (i.e. Search/Launcher)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Hide and (re)show taskbar"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Access system settings"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Access Google Assistant"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Lock screen"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Pull up Notes app for quick memo"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"System multitasking"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Enter split screen with current app to right-hand side"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Enter split screen with current app to left-hand screen"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Switch from split screen to full screen"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"During split screen: Replace an app from one to another"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Input"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Switch input language (next language)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Switch input language (previous language)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Access emoji"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Access voice typing"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Applications"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Assist"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Browser"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Browser (Chrome as default)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Contacts"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Email"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Email (Gmail as default)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Music"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculator"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Do Not Disturb"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Volume buttons shortcut"</string>
<string name="battery" msgid="769686279459897127">"Battery"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"screen recording"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"No title"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Standby"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Font size"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Make smaller"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Make larger"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Magnification window"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Magnification window controls"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Zoom in"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Can’t broadcast"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Can’t save. Try again."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Can’t save."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Use at least four characters"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Use fewer than 16 characters"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Build number copied to clipboard."</string>
<string name="basic_status" msgid="2315371112182658176">"Open conversation"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• At least one device is available"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Touch &amp; hold shortcut"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Cancel"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Flip now"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Unfold phone for a better selfie"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Flip to front display for a better selfie?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Use the rear-facing camera for a wider photo with higher resolution."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ This screen will turn off"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Switch screens now"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Unfold phone"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Switch screens?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"For higher resolution, use the rear camera"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"For higher resolution, flip the phone"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Foldable device being unfolded"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Foldable device being flipped around"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> battery remaining"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Switch to work profile"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Close"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Lock screen settings"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi not available"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Camera is blocked"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Camera and microphone blocked"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microphone is blocked"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Priority mode on"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant attention on"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml
index 56cdbef092f2..0cf28684aa48 100644
--- a/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Off"</item>
<item msgid="5966994759929723339">"On"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Unavailable"</item>
+ <item msgid="2478289035899842865">"Off"</item>
+ <item msgid="5137565285664080143">"On"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index b789da176c47..dc3c8e4ee47b 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Notification shade."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Quick settings."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Quick Settings and notification shade."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Lock screen."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Work lock screen"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Close"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Brightness"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Colour inversion"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Colour correction"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Font size"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Manage users"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Done"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Close"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notifications"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Keyboard shortcuts"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Switch keyboard layout"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Clear text"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Shortcuts"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Search shortcuts"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"No shortcuts found"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"System"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Input"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Open apps"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Current app"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Access notification shade"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Take a full screenshot"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Access list of system/apps shortcuts"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Back: Go back to previous state (back button)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Access home screen"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Overview of open apps"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Cycle through recent apps (forward)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Cycle through recent apps (back)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Access list of all apps and search (i.e. Search/Launcher)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Hide and (re)show taskbar"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Access system settings"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Access Google Assistant"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Lock screen"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Pull up Notes app for quick memo"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"System multitasking"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Enter split screen with current app to right-hand side"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Enter split screen with current app to left-hand screen"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Switch from split screen to full screen"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"During split screen: Replace an app from one to another"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Input"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Switch input language (next language)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Switch input language (previous language)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Access emoji"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Access voice typing"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Applications"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Assist"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Browser"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Browser (Chrome as default)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Contacts"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Email"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Email (Gmail as default)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Music"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculator"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Do Not Disturb"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Volume buttons shortcut"</string>
<string name="battery" msgid="769686279459897127">"Battery"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"screen recording"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"No title"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Standby"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Font size"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Make smaller"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Make larger"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Magnification window"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Magnification window controls"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Zoom in"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Can’t broadcast"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Can’t save. Try again."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Can’t save."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Use at least four characters"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Use fewer than 16 characters"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Build number copied to clipboard."</string>
<string name="basic_status" msgid="2315371112182658176">"Open conversation"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• At least one device is available"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Touch &amp; hold shortcut"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Cancel"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Flip now"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Unfold phone for a better selfie"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Flip to front display for a better selfie?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Use the rear-facing camera for a wider photo with higher resolution."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ This screen will turn off"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Switch screens now"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Unfold phone"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Switch screens?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"For higher resolution, use the rear camera"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"For higher resolution, flip the phone"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Foldable device being unfolded"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Foldable device being flipped around"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> battery remaining"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Switch to work profile"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Close"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Lock screen settings"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi not available"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Camera is blocked"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Camera and microphone blocked"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microphone is blocked"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Priority mode on"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant attention on"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml
index 56cdbef092f2..0cf28684aa48 100644
--- a/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Off"</item>
<item msgid="5966994759929723339">"On"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Unavailable"</item>
+ <item msgid="2478289035899842865">"Off"</item>
+ <item msgid="5137565285664080143">"On"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 0493b3834941..bc46af1586ed 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‏‎‏‎‎‎‏‏‎‎‏‏‎‎‎‏‎‎‎‎‏‎‏‎‎‎‏‏‏‏‎‎‏‏‎‏‏‎‎‏‏‏‏‎‏‎‏‏‎‏‏‎‏‎‏‎Notification shade.‎‏‎‎‏‎"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‎‏‏‎‎‏‎‎‏‎‏‏‎‏‎‏‏‎‏‎‏‏‎‏‎‎‏‎‎‏‎‏‎‎‎‏‏‎‎‏‏‏‎‎‎‏‎‎‏‎‏‏‎Quick settings.‎‏‎‎‏‎"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‎‎‎‎‎‏‎‎‎‎‎‎‏‏‎‎‏‎‏‏‎‏‎‏‎‏‎‏‏‏‏‏‎‏‎‎‏‏‏‎‏‎‏‏‏‏‎‏‏‎‎‎‎Quick settings and Notification shade.‎‏‎‎‏‎"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‎‎‏‎‎‎‎‏‎‏‎‏‎‎‏‎‎‏‎‎‏‎‏‏‏‏‏‎‎‏‎‎‎‎‎‎‎‎‎‎‎‏‎‏‏‎‏‎‎‎‎‏‏‏‎Lock screen.‎‏‎‎‏‎"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‎‏‏‏‎‎‏‎‎‏‎‎‎‏‎‏‏‎‏‎‏‏‎‎‎‎‏‎‏‎‎‏‏‎‎‎‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‏‏‏‏‎Work lock screen‎‏‎‎‏‎"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‏‏‎‎‏‎‎‏‎‏‎‏‏‏‎‏‎‏‏‎‏‏‎‎‏‏‏‎‎‏‏‏‏‎‏‎‎‏‏‎‏‏‎‎‏‎‏‏‎‏‎‏‏‎Close‎‏‎‎‏‎"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‎‏‏‏‏‎‏‏‏‎‎‏‎‎‏‏‏‏‎‎‏‎‎‎‏‎‏‏‎‏‏‎‎‏‏‎‏‎‏‏‎‎‏‏‎‏‎‎‎‏‎‏‎‎‎Brightness‎‏‎‎‏‎"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‎‎‏‎‏‏‏‏‏‏‎‏‏‎‎‏‏‏‎‏‏‏‏‏‎‏‎‏‏‏‏‏‏‎‎‏‏‏‎‏‏‎‏‎‎‎‏‎‏‏‎‏‎‎‎‎Color inversion‎‏‎‎‏‎"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‏‏‏‎‎‏‎‏‎‎‏‎‏‎‎‎‏‎‎‎‎‎‏‏‎‏‏‎‎‎‎‏‏‎‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‎‏‎‎‎‎Color correction‎‏‎‎‏‎"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‏‏‎‎‏‏‎‎‏‎‎‏‏‏‎‎‏‏‎‎‏‎‏‎‏‏‎‏‎‏‎‎‏‏‎‎‏‎‏‏‎‏‎‏‎‎‎‎‏‎‎‎‎‎‎‎Font size‎‏‎‎‏‎"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‏‏‎‎‏‏‏‎‏‏‏‏‎‎‏‎‏‏‏‎‏‏‏‏‏‎‎‎‏‏‏‎‎‎‎‏‎‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‎Manage users‎‏‎‎‏‎"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‎‎‎‎‎‎‏‏‎‏‏‎‎‏‏‎‎‎‏‎‎‏‏‎‎‏‏‏‎‎‏‏‎‎‎‏‎‎‏‎‎‏‏‎‏‎‎‏‎‏‏‏‏‎‎‎‏‎Done‎‏‎‎‏‎"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‎‏‏‎‏‏‎‎‎‏‏‎‏‏‏‏‏‎‎‏‏‎‏‎‏‏‏‎‏‏‎‎‏‏‎‎‏‎‎‎‏‎‎‎‏‏‎‎‎‎‏‎‎‎‏‎Close‎‏‎‎‏‎"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‎‎‎‎‏‏‎‎‎‎‏‏‏‎‏‏‎‏‎‏‎‏‏‎‏‎‏‎‎‎‏‏‏‎‏‏‏‎‎‏‏‏‎‏‏‎‎Notifications‎‏‎‎‏‎"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‏‏‎‎‏‏‎‏‏‎‏‏‎‎‏‎‏‏‏‎‎‎‏‎‏‎‎‎‎‎‏‎‏‏‏‎‎‏‏‎‏‎‎‏‎‏‏‏‏‏‏‎‏‎‏‎Keyboard Shortcuts‎‏‎‎‏‎"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‎‎‏‏‏‎‎‎‎‎‏‎‏‎‎‎‎‎‏‏‎‏‎‏‎‏‎‎‎‎‎‏‎‏‎‏‎‏‎‎‎‎‎‏‏‎‎‏‎‏‎‎‎‏‏‎‎Switch keyboard layout‎‏‎‎‏‎"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‏‎‎‏‎‎‏‏‏‎‎‎‎‏‏‏‎‏‏‏‎‏‎‏‏‎‎‎‎‏‎‏‎‎‎‎‏‏‏‎‎‏‏‎‎‎‎‎‏‏‎‎‏‎Clear text‎‏‎‎‏‎"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‎‎‎‎‏‎‏‏‏‎‎‏‎‎‎‏‏‏‎‏‏‏‎‎‏‎‏‏‏‏‏‎‎‎‎‎‏‎‏‎‎‎‎‏‏‏‎‎‎‎‎‏‏‏‎‏‎Shortcuts‎‏‎‎‏‎"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‎‎‎‏‏‎‏‎‎‎‏‏‎‎‎‎‏‎‏‎‎‏‎‎‎‎‏‏‏‎‏‎‎‏‎‎‏‎‏‎‏‏‎‏‏‏‏‏‎‏‏‎‏‎‎Search shortcuts‎‏‎‎‏‎"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‎‎‏‏‎‎‎‎‎‏‏‏‎‎‏‏‎‏‏‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‏‏‏‎‏‏‏‎‏‏‎‏‎No shortcuts found‎‏‎‎‏‎"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‎‏‎‎‎‎‎‏‎‏‎‎‎‏‎‎‎‏‏‏‎‎‎‎‎‎‏‎‏‎‎‎‏‎‎‏‏‏‏‏‏‎‏‎System‎‏‎‎‏‎"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‎‎‎‎‎‎‏‎‏‏‏‏‏‏‎‎‏‎‎‎‏‏‏‎‏‏‎‎‏‎‏‎‎‏‎‎‏‎‏‏‏‏‏‎‎‏‎‎‏‎‏‎‎‏‎Input‎‏‎‎‏‎"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‎‎‏‎‎‎‏‎‏‏‎‏‏‎‎‎‎‏‏‎‎‎‏‏‎‎‎‎‎‎‏‏‏‎‎‎‎‏‏‎‏‏‏‎‏‏‏‎‏‏‎‏‏‎‏‎‎Open apps‎‏‎‎‏‎"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‏‏‏‏‎‏‎‏‏‏‏‏‎‎‏‎‏‎‎‎‏‏‎‏‎‎‎‏‎‏‏‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‎‏‏‎‏‏‎Current app‎‏‎‎‏‎"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‎‎‎‏‎‎‎‏‎‎‏‏‎‏‎‎‏‎‏‎‎‏‎‏‏‎‏‏‎‏‏‏‏‎‏‎‏‏‏‎‎‏‏‏‏‎‏‎‎‎‎‎‏‏‎Access notification shade‎‏‎‎‏‎"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‎‎‏‎‏‏‎‎‏‎‎‏‎‏‏‎‎‎‎‎‎‏‏‏‏‏‏‎‎‏‎‏‏‏‏‎‏‎‏‏‏‏‎‎‎‎‎‎‏‎‏‎‏‏‎Take a full screenshot‎‏‎‎‏‎"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‏‏‏‎‎‎‏‎‏‎‎‎‎‏‎‎‏‏‏‏‏‎‏‎‎‏‎‎‎‎‎‎‏‎‏‏‎‏‎‎‏‎‎‏‏‎‏‎‎‏‎‎‏‎Access list of system / apps shortcuts‎‏‎‎‏‎"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‎‎‎‎‏‏‏‏‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‏‏‎‎‎‎‏‏‎Back: go back to previous state (back button)‎‏‎‎‏‎"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‏‎‎‎‏‏‎‏‎‎‏‏‏‎‎‏‏‎‏‎‎‎‎‏‏‎‎‏‏‎‎‎‎‎‏‏‏‎‎‎‎‏‏‏‏‏‎‎‎‏‏‎‏‎‏‎Access home screen‎‏‎‎‏‎"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‎‏‏‎‏‏‏‏‎‎‎‎‏‏‎‎‎‎‏‎‎‎‎‏‏‎‎‏‎‎‏‏‎‏‏‏‎‏‎‏‏‎‎‏‏‎‏‎‏‎‎‎‏‏‎‎Overview of open apps‎‏‎‎‏‎"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‎‏‎‎‏‏‎‏‏‎‏‎‏‎‏‏‏‎‎‏‏‏‏‎‏‎‏‎‏‎‏‎‏‏‏‎‏‏‎‎‎‏‎‎‏‏‎‎Cycle through recent apps (forward)‎‏‎‎‏‎"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‎‏‎‏‎‎‎‎‏‎‎‏‏‏‏‏‎‎‏‏‎‏‏‏‏‎‏‏‏‎‏‏‎‏‏‎‎‏‎‎‎‎‎‎‎‎‎‏‎‎‎‏‎‏‏‎Cycle through recent apps (back)‎‏‎‎‏‎"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‎‎‏‏‏‎‎‎‎‎‎‎‎‎‏‎‏‎‏‎‏‏‏‏‎‏‏‎‎‎‏‎‏‎‏‎‎‎‎‏‎‎‏‎Access list of all apps and search (i.e. Search/Launcher)‎‏‎‎‏‎"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‏‏‎‏‏‏‎‏‎‏‎‏‏‏‎‏‏‏‎‏‏‏‎‏‎‏‏‏‏‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‏‏‎‎‏‏‎‏‏‎Hide and (re)show taskbar‎‏‎‎‏‎"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‏‏‎‏‎‏‏‎‏‏‎‎‏‏‎‏‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‏‎‏‏‏‎‏‎‏‏‏‏‎‎‏‏‎‏‎‏‎Access system settings‎‏‎‎‏‎"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‎‏‏‏‎‏‏‎‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‎‎‏‏‏‎‏‎‎‏‏‎‏‏‎‎‏‎‏‎‎‎‏‎‎‏‎‏‏‎‎‎‎Access Google Assistant‎‏‎‎‏‎"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‎‏‎‎‏‎‏‏‎‎‏‎‎‏‎‏‎‏‎‎‏‏‏‏‎‏‎‏‎‏‎‎‎‏‏‏‏‎‎‏‏‏‎‎‏‏‏‏‎‏‏‏‏‏‎Lock screen‎‏‎‎‏‎"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‏‏‎‎‎‏‎‏‏‏‎‎‎‏‎‎‏‏‎‎‎‏‎‎‏‏‏‎‏‏‏‏‏‏‎‎‏‏‏‎‏‏‎‎‎‎‎‏‏‎‏‏‏‏‎Pull up Notes app for quick memo‎‏‎‎‏‎"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‏‎‎‏‎‎‎‎‏‏‏‎‏‏‏‏‎‏‏‏‎‎‏‎‏‎‎‎‏‏‎‏‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‎‎‎‎‎‎‏‎System multitasking‎‏‎‎‏‎"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‏‏‎‏‎‎‎‏‏‎‏‏‎‏‎‎‏‏‎‏‏‏‎‎‎‏‎‎‎‏‏‎Enter Split screen with current app to RHS‎‏‎‎‏‎"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‎‏‏‏‏‎‎‏‎‎‏‏‏‏‎‏‏‏‏‏‏‎‏‎‏‎‏‎‏‎‏‎‎‎‏‎‎‎‎‎‎‎‏‎‏‎‎‏‏‏‎‎Enter Split screen with current app to LHS‎‏‎‎‏‎"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‏‎‎‏‏‏‎‏‎‏‎‏‏‏‎‎‏‎‏‎‎‏‏‏‎‎‏‏‎‏‏‏‏‎‏‎‏‏‎‎‏‏‎‏‎‎‏‏‎‏‎‎‏‏‎‎‏‎Switch from Split screen to full screen‎‏‎‎‏‎"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‏‎‏‏‎‏‏‏‏‎‎‎‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‎‏‏‎‏‏‏‎‏‏‏‏‏‏‎‏‎‏‎‎‎‎‎‏‎‎During Split screen: replace an app from one to another‎‏‎‎‏‎"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‏‏‎‎‎‎‎‎‏‏‎‎‎‏‎‏‎‎‎‏‎‏‎‎‏‎‎‎‎‎‎‏‏‏‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‏‎‎Input‎‏‎‎‏‎"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‏‎‎‎‏‏‎‏‎‏‏‏‏‎‎‏‎‎‎‏‏‎‏‎‎‏‎‎‏‎‏‏‏‏‎‏‎‎‏‏‏‎‏‎‎‏‎‎‎‎‎‎‎‎‎‎‏‎Switch input language (next language)‎‏‎‎‏‎"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‏‏‏‎‎‏‏‏‏‎‏‎‏‎‎‏‏‎‏‎‏‏‎‎‏‎‏‎‏‎‎‎‎‎‎‎Switch input language (previous language)‎‏‎‎‏‎"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‏‏‎‏‎‎‎‎‎‏‏‏‎‎‏‏‏‏‎‎‎‎‎‏‎‎‎‎‏‏‏‏‎‎‎‎‏‏‎‎‎‎‎‎‎‏‎‎‏‏‏‏‎Access emoji‎‏‎‎‏‎"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‏‎‏‏‏‏‏‎‎‎‏‏‎‏‎‎‎‏‏‏‎‎‏‏‎‎‎‎‏‎‎‏‎‏‏‎‎‎‏‏‎‏‏‎‏‎‏‎‏‏‏‏‎‏‎Access voice typing‎‏‎‎‏‎"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‎‎‎‎‎‏‎‎‏‏‎‎‎‏‏‎‏‎‎‎‎‎‏‏‏‎‏‏‎‎‏‎‏‏‏‏‎‎‏‏‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎Applications‎‏‎‎‏‎"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‏‎‏‏‎‏‎‏‎‏‎‎‏‎‏‏‏‏‎‎‎‏‏‏‏‎‎‎‎‏‎‏‎‎‎‎‎‎‏‏‏‏‎‎‎‎‎‎‎‎‏‏‎‏‏‎‎Assist‎‏‎‎‏‎"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‏‎‎‎‎‏‏‏‎‎‎‏‎‏‎‏‎‏‎‏‎‎‏‎‎‎‏‎‎‏‏‎‎‎‏‏‎‏‏‎‏‎‎‎‎‏‏‎‎‏‏‎‎‎‏‏‎Browser‎‏‎‎‏‎"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‎‏‏‎‎‏‎‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‏‎‏‏‎‏‏‎‏‎‏‏‏‏‎‎‎‏‏‏‏‎‎‎‎‏‎‎‎‎‏‎‎‎Browser (Chrome as default)‎‏‎‎‏‎"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‏‏‏‏‎‏‎‏‎‏‏‎‏‎‏‏‎‏‏‏‎‎‏‏‎‏‏‏‎‏‏‎‎‏‎‏‎‏‏‏‎‎‎‏‎‎‎‏‏‏‏‎‎‏‎‎‎Contacts‎‏‎‎‏‎"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‏‎‎‏‎‎‏‏‏‏‏‏‎‎‎‏‎‏‎‏‏‏‏‏‏‎‎‎‏‎‎‏‏‎‏‏‏‎‎‎‎‏‎‎‏‏‎‏‏‎‎‎‎Email‎‏‎‎‏‎"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‎‎‏‏‏‏‏‎‎‏‎‎‏‏‏‏‎‎‎‎‎‏‎‎‎‎‏‏‏‎‎‏‎‏‎‎‎‎‎‏‏‎‎‎‏‎‎‏‏‏‎‏‏‏‎Email (Gmail as default)‎‏‎‎‏‎"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‏‏‎‏‏‏‏‎‏‏‎‎‎‎‏‏‎‎‎‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‎‎‏‎‎‏‎‏‏‏‎‎SMS‎‏‎‎‏‎"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‎‎‎‏‏‎‎‎‏‏‏‎‎‎‎‎‎‎‏‎‎‏‏‎‎‏‎‎‎‎‏‏‎‎‎‎‏‎‎‏‏‏‎‏‏‏‏‎‎‏‎Music‎‏‎‎‏‎"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‎‏‏‎‎‏‎‏‎‎‏‎‎‎‏‏‎‎‎‎‎‏‏‎‎‎‎‏‏‏‎‎‏‎‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‎‏‏‎‏‎Calendar‎‏‎‎‏‎"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‏‎‎‏‏‏‎‎‎‏‏‎‎‎‎‏‏‏‏‎‎‏‎‏‎‏‏‏‎‏‎‏‎‏‎‏‏‏‏‎‎‏‎‏‎‎‎‏‏‎‏‎‎‏‎Calculator‎‏‎‎‏‎"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‏‏‏‎‏‏‎‏‏‎‏‎‎‏‏‏‎‎‎‏‎‎‏‏‎‏‎‎‎‎‎‎‏‎‏‎‏‎‏‏‏‏‎‎‏‎‏‏‏‎‎‏‏‎‎Maps‎‏‎‎‏‎"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‏‏‏‏‎‏‏‏‏‎‎‏‏‏‏‎‎‏‏‏‎‎‎‏‎‏‎‎‎‎‎‏‎‏‎‏‎‎‎‎‎‏‏‎‏‏‏‎‎‎‏‏‎‎‎‎‎Do Not Disturb‎‏‎‎‏‎"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‎‏‎‎‎‎‎‎‏‏‎‎‎‎‎‏‏‎‏‏‏‎‎‏‎‏‎‏‎‎‎‏‎‎‎‎‎‎‎‎‏‏‏‎‎‏‏‏‎‏‏‎‏‎Volume buttons shortcut‎‏‎‎‏‎"</string>
<string name="battery" msgid="769686279459897127">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‏‎‏‎‏‏‏‎‎‏‏‏‏‎‎‏‏‎‎‏‎‏‏‏‏‏‎‏‏‎‏‏‏‎‏‏‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‏‎Battery‎‏‎‎‏‎"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‏‎‏‏‎‏‏‏‎‎‏‏‎‎‏‏‎‏‏‎‎‏‎‎‏‎‏‏‎‏‎‏‎‏‎‏‎‏‏‎‏‏‏‏‏‎‎‏‏‎‏‏‎screen recording‎‏‎‎‏‎"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‎‏‎‎‏‎‎‏‎‏‏‏‏‏‎‎‎‎‎‎‎‏‏‏‎‎‏‎‎‏‏‎‎‎‏‏‏‎‎‏‏‎‏‏‏‎‎‏‏‏‏‎‏‎‎No title‎‏‎‎‏‎"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‎‎‎‎‎‎‎‎‏‏‏‎‏‏‎‏‏‏‎‏‏‎‎‎‎‏‏‎‎‏‎‏‎‎‏‎‏‎‎‎‏‎‏‎‎‏‏‎‏‏‏‎‎‏‎‏‎Standby‎‏‎‎‏‎"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‎‎‎‏‏‎‏‏‏‎‏‏‎‏‏‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‎‎‎‏‎‎‎‏‎‏‏‎‏‏‏‎Font Size‎‏‎‎‏‎"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‎‎‎‎‏‎‏‏‎‏‏‏‎‏‎‏‏‏‏‏‎‎‎‎‏‎‏‎‎‎‎‎‏‎‎‏‏‏‎‎‎‏‎‏‎‎‎‏‏‎‏‎‏‎‎‎‎Make smaller‎‏‎‎‏‎"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‎‏‏‏‎‏‎‎‏‎‏‎‎‏‎‎‎‎‎‏‎‏‎‎‎‏‎‎‏‏‎‎‏‏‎‏‎‎‎‎Make larger‎‏‎‎‏‎"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‎‎‎‎‎‎‎‎‎‏‏‎‎‎‎‏‎‏‎‏‏‏‎‏‎‏‎‎‎‎‎‎‏‏‏‎‎‎‏‏‎‏‎‎‏‎‏‏‎‏‏‏‎‏‎Magnification Window‎‏‎‎‏‎"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‏‏‏‎‏‏‏‎‎‎‏‏‏‏‏‎‏‎‏‏‏‏‎‎‎‎‏‎‎‏‎‎‏‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‎Magnification Window Controls‎‏‎‎‏‎"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‏‎‎‎‎‎‎‏‎‎‏‎‎‏‎‎‏‏‎‏‏‏‏‎‏‎‏‏‎‎‎‏‎‏‏‎‎‏‎‏‏‏‎‎‎‎‏‎‏‎‎‎‏‎‎‏‎Zoom in‎‏‎‎‏‎"</string>
@@ -1055,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‎‏‏‎‏‏‏‎‎‏‏‏‏‏‏‎‏‎‎‎‏‎‏‏‎‏‎‎‏‎‎‏‏‏‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‎‎• At least one device is available‎‏‎‎‏‎"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‎‏‎‏‎‎‏‏‎‎‏‏‏‏‏‏‏‎‏‎‎‎‏‎‏‎‏‎‎‎‎‏‎‏‏‏‎‏‏‎‏‎‎‎‏‎‏‎‏‎‎‎‎‎Touch &amp; hold shortcut‎‏‎‎‏‎"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‎‎‏‎‎‏‏‎‎‏‏‎‏‏‏‎‎‏‎‏‎‏‏‎‎‏‏‏‎‎‏‏‎‎‎‎‏‎‎‏‏‎‏‏‏‎‏‏‎‎‎‎‎‎‎Cancel‎‏‎‎‏‎"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‏‎‏‎‏‎‎‏‏‎‎‏‏‏‏‏‎‎‎‏‏‎‏‏‎‏‎‏‎‎‎‎‏‏‎‏‏‎‏‎‏‏‏‏‏‎‎‏‎‎‏‎‏‏‎‎Flip now‎‏‎‎‏‎"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‎‎‏‎‏‏‏‏‏‏‎‏‎‎‏‏‏‏‎‏‎‏‏‏‎‏‎‎‎‎‎‏‏‏‎‎‎‏‏‏‎‏‏‎‎‎‎‎‎‏‏‎‎‎Unfold phone for a better selfie‎‏‎‎‏‎"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‏‏‎‏‎‏‎‎‏‏‎‎‏‎‏‎‏‎‏‏‎‏‏‏‏‎‎‏‏‎‎‎‏‎‎‎‎‎‏‏‎‎‎‎‎‎‎‎‎‎‏‎‎‎‏‎‏‎Flip to front display for a better selfie?‎‏‎‎‏‎"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‏‎‏‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‎‏‎‏‏‎‎‎‎‏‏‎‏‎‎‏‏‏‏‏‏‎‎‎‏‎‏‎‏‏‏‎‎‎‎‎Use the rear-facing camera for a wider photo with higher resolution.‎‏‎‎‏‎"</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‎‎‎‏‏‏‎‏‏‎‏‏‎‏‎‏‏‎‎‎‏‎‏‏‏‎‎‎‎‎‏‏‏‏‎‎‏‏‏‎‎‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‎‎‏‎‎‏‏‎"<b>"‎‏‎‎‏‏‏‎✱ This screen will turn off‎‏‎‎‏‏‎"</b>"‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‏‏‏‎‏‏‎‎‎‎‎‎‏‎‏‎‏‎‎‎‏‎‎‏‏‏‏‎‏‏‎‎‏‏‎‎‎‏‏‏‎‏‎‎‎‏‎‎‎‎‎‎‎‎‏‏‎Switch screens now‎‏‎‎‏‎"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‏‎‎‎‏‎‏‎‎‎‏‏‎‎‏‎‎‎‏‎‎‎‏‎‎‎‎‎‎‏‏‎‏‏‏‎‏‏‎‏‏‏‏‎‏‏‎‏‎‎‏‏‎‏‏‎‎Unfold phone‎‏‎‎‏‎"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‏‎‎‏‏‏‎‏‎‎‎‎‏‎‎‎‏‎‎‎‏‏‏‏‎‏‏‏‎‎‎‏‎‎‏‎‎‏‎‎‏‎‏‎‏‎‏‏‏‏‏‎‏‏‏‎Switch screens?‎‏‎‎‏‎"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‏‏‎‏‏‎‎‏‏‎‎‏‎‎‎‏‏‏‎‎‏‎‎‏‎‎‎‏‎‏‎‎‎‎‎‏‏‏‏‎‎‏‏‎‎‏‏‎‏‎‎‏‏‏‎For higher resolution, use the rear camera‎‏‎‎‏‎"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‎‏‎‏‎‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‏‏‏‎‎‎‎‏‏‎‏‎‎‏‎‎‎‎‎‏‎‎‏‏‏‎‎‎‎‎‏‎‎‏‎For higher resolution, flip the phone‎‏‎‎‏‎"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‎‏‎‏‏‎‎‎‏‎‎‎‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎Foldable device being unfolded‎‏‎‎‏‎"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‏‎‎‎‎‎‎‏‎‎‎‏‎‎‎‎‎‎‏‏‏‎‏‏‎‎‏‏‏‏‏‎‏‎‏‎‏‎‎‏‎‏‏‏‎‎‎‎‏‏‎‎‏‎‎‎‎‎Foldable device being flipped around‎‏‎‎‏‎"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‎‎‏‏‏‏‎‏‏‏‎‏‎‎‎‏‏‎‏‎‏‏‏‎‏‎‏‎‏‏‏‎‎‏‎‎‏‎‎‎‏‎‏‎‏‏‏‎‎‎‏‏‏‎‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ battery remaining‎‏‎‎‏‎"</string>
@@ -1071,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‎‎‎‏‎‎‏‏‎‎‏‏‏‏‏‏‎‎‎‏‎‎‎‎‎‏‏‎‏‏‎‏‏‎‏‏‎‎‎‎‎‎‏‎‎‏‎‎‏‎‎‏‎‎‎Switch to work profile‎‏‎‎‏‎"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‎‎‎‏‎‏‎‎‏‏‎‎‏‏‎‎‎‏‎‎‏‎‏‎‎‎‎‎‎‏‎‏‏‏‎‏‏‎‎‎‏‏‏‎‏‎‏‎‎‎‎‏‎‎Close‎‏‎‎‏‎"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‏‏‏‎‏‏‏‎‎‏‎‏‎‏‏‏‎‎‎‎‎‏‏‏‎‎‎‏‏‎‏‎‏‎‎‎‎‏‏‎‎‏‏‎‎‎‏‏‎Lock screen settings‎‏‎‎‏‎"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‎‎‎‏‎‏‏‏‎‏‎‎‏‎‎‎‎‏‏‏‎‎‏‎‎‎‎‎‏‏‎‎‎‎‏‏‎‏‎‏‏‎‏‎‎‎‎‎‏‏‏‎‎‏‎‎‎Wi-Fi not available‎‏‎‎‏‎"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎‏‎‎‎‏‏‎‎‎‏‏‏‎‏‎‎‎‎‏‎‏‎‏‏‏‎‎‏‏‏‏‎‏‏‎‎‎‎‏‎‎‏‏‏‏‏‎‏‎‎‎‏‎‎‏‎‎Camera blocked‎‏‎‎‏‎"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‎‎‎‏‎‏‎‏‏‏‏‎‏‏‎‏‏‎‏‏‏‏‎‎‏‏‏‎‎‏‏‏‏‎‎‎‏‎‎‏‏‏‎‎‏‏‎‏‎‎‏‎‎‎Camera and microphone blocked‎‏‎‎‏‎"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‎‏‏‏‏‎‎‏‎‏‎‎‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‏‎‎‎‏‎‏‎‏‎‏‏‏‏‏‏‏‎‎‏‎Microphone blocked‎‏‎‎‏‎"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‏‏‎‎‎‏‎‏‎‎‏‏‎‎‎‎‎‏‏‎‏‎‎‎‏‎‎‏‎‏‏‎‏‎‎‎‏‏‏‎‏‎‏‎‏‏‎‎‏‎‎‏‎‎‎‎Priority mode on‎‏‎‎‏‎"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‎‎‏‎‎‏‏‏‎‎‏‏‎‏‎‎‏‎‏‎‏‏‏‎‏‏‏‎‏‏‏‏‏‏‎‎‏‏‎‏‎‏‏‎‎‎‎‎‏‏‏‎‏‏‎Assistant attention on‎‏‎‎‏‎"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml
index 3a8e34c2ebdc..b9c8e5fcdd6a 100644
--- a/packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‏‏‏‎‏‎‏‏‏‏‎‎‏‏‎‏‏‎‎‏‎‏‏‎‎‎‏‏‎‏‏‏‎‎‎‏‏‏‎‎‎‏‎‎‎‎‎‏‏‏‏‎‎‎‎Off‎‏‎‎‏‎"</item>
<item msgid="5966994759929723339">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‎‎‏‏‏‏‎‎‎‎‎‏‏‎‎‎‎‏‏‏‏‎‏‎‏‎‎‎‏‎‎‎‏‏‏‎‏‎‎‏‏‏‏‎‎‏‏‏‎‎‏‎‏‏‎On‎‏‎‎‏‎"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‎‏‎‏‎‎‏‎‎‎‏‏‎‎‏‎‏‏‎‏‏‏‏‏‏‎‎‎‎‎‏‎Unavailable‎‏‎‎‏‎"</item>
+ <item msgid="2478289035899842865">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‎‎‏‏‎‎‏‎‎‏‎‏‎‎‏‏‎‏‎‏‏‏‏‏‏‎‏‏‎‎‎‏‏‏‎‎‎‏‏‏‎‎‎‏‏‎‎‎‏‎‎‏‏‎‎‎‏‎Off‎‏‎‎‏‎"</item>
+ <item msgid="5137565285664080143">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‏‎‎‏‏‎‎‎‏‎‎‏‏‎‎‎‏‏‎‏‎‎‎‎‏‎‎‎‏‏‎‎‏‏‎‎‎‏‎‏‏‎‎‎‎‎‏‎‎‎‎‏‏‏‏‎On‎‏‎‎‏‎"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 98ccea02164d..44b56de971f3 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Pantalla de notificaciones"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Configuración rápida"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Configuración rápida y panel de notificaciones."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Pantalla de bloqueo"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Pantalla bloqueada del perfil de trabajo"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Cerrar"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Brillo"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Invertir colores"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Corregir colores"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Tamaño de la fuente"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Administrar usuarios"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Listo"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Cerrar"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notificaciones"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Ver combinaciones de teclas"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Cambiar diseño del teclado"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Borrar texto"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Combinaciones de teclas"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Buscar comb. de teclas"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"No hay comb. de teclas"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistema"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Entrada"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Apps abiertas"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"App actual"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Acceder al panel de notificaciones"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Tomar una captura de pantalla completa"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Acceder a una lista de combinación de teclas del sistema/apps"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Atrás: Vuelve al estado anterior (botón Atrás)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Acceder a la pantalla principal"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Obtener una descripción general de las apps abiertas"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Desplazar por las apps recientes (adelante)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Desplazar por las apps recientes (atrás)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Acceder a lista de apps y búsquedas (p. ej. Búsqueda/Launcher)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Esconder y volver a mostrar la barra de tareas"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Acceder a la configuración del sistema"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Acceder a Asistente de Google"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Bloquear la pantalla"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Mostrar la app de Notas para crear un recordatorio rápido"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Tareas múltiples del sistema"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Activar pantalla dividida con la app actual en el lado derecho (RHS)"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Activar pantalla dividida con la app actual en el lado izquierdo (LHS)"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Cambiar de pantalla dividida a pantalla completa"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Durante pantalla dividida: Reemplaza una app con otra"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Entrada"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Cambiar el idioma de escritura (próximo idioma)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Cambiar el idioma de escritura (idioma anterior)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Acceder a los emojis"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Acceder al dictado por voz"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Aplicaciones"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Asistencia"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Navegador"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Navegador (Chrome como predeterminado)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Contactos"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Correo electrónico"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Correo electrónico (Gmail como predeterminado)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Música"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendario"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculadora"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"No interrumpir"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Combinación de teclas de botones de volumen"</string>
<string name="battery" msgid="769686279459897127">"Batería"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"Grabación de pant."</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sin título"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"En espera"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Tamaño de fuente"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Reducir tamaño"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Aumentar tamaño"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Ventana de ampliación"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Controles de ampliación de la ventana"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Acercar"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"Se produjo un error. Vuelve a intentarlo."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Cargando"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"tablet"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"Transmitiendo tu contenido multimedia"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"Transmitiendo <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactivo. Verifica la app"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"No se encontró"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"El control no está disponible"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Error al iniciar transmisión"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"No se puede guardar. Vuelve a intentarlo."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"No se puede guardar."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Usa al menos 4 caracteres"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Usa menos de 16 caracteres"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número de compilación"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Se copió el número de compilación en el portapapeles."</string>
<string name="basic_status" msgid="2315371112182658176">"Conversación abierta"</string>
@@ -1048,7 +1083,7 @@
<string name="log_access_confirmation_title" msgid="4843557604739943395">"¿Quieres permitir que <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> acceda a todos los registros del dispositivo?"</string>
<string name="log_access_confirmation_allow" msgid="752147861593202968">"Permitir acceso por única vez"</string>
<string name="log_access_confirmation_deny" msgid="2389461495803585795">"No permitir"</string>
- <string name="log_access_confirmation_body" msgid="6883031912003112634">"Los registros del dispositivo permiten documentar lo que sucede en él. Las apps pueden usar estos registros para encontrar y solucionar problemas.\n\nEs posible que algunos registros del dispositivo contengan información sensible, por lo que solo permitimos que accedan a todos ellos apps de tu confianza. \n\nSi no permites que esta app acceda a todos los registros del dispositivo, aún puede acceder a sus propios registros. Además, es posible que el fabricante del dispositivo acceda a algunos registros o información en tu dispositivo."</string>
+ <string name="log_access_confirmation_body" msgid="6883031912003112634">"Los registros del dispositivo permiten documentar lo que sucede en él. Las apps pueden usar estos registros para encontrar y solucionar problemas.\n\nEs posible que algunos registros del dispositivo contengan información sensible, por lo que solo debes permitir que accedan a ellos las apps que sean de tu confianza. \n\nSi no permites que esta app acceda a todos los registros del dispositivo, aún puede acceder a sus propios registros. Además, es posible que el fabricante del dispositivo acceda a algunos registros o información en tu dispositivo."</string>
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Más información"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Más información en <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Abrir <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Hay al menos un dispositivo disponible."</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Mantener presionado atajo"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Cancelar"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Girar ahora"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Despliega el teléfono para tomar una selfie mejor"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"¿Girar a pantalla frontal para mejores selfies?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Usa la cámara trasera para tomar una foto más amplia y con mejor resolución."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Esta pantalla se apagará"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Cambiar de pantalla ahora"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Desplegar teléfono"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"¿Quieres cambiar de pantalla?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Para obtener una resolución más alta, usa la cámara posterior"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Para obtener una resolución más alta, gira el teléfono"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo plegable siendo desplegado"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo plegable siendo girado"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> de batería restante"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Cambiar al perfil de trabajo"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Cerrar"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Config. de pantalla de bloqueo"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi no disponible"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"La cámara está bloqueada"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"La cámara y el micrófono están bloqueados"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"El micrófono está bloqueado"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"El modo de prioridad está activado"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Asistente está prestando atención"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml b/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml
index 89ee62d1cd87..bb3983b0bb09 100644
--- a/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"No"</item>
<item msgid="5966994759929723339">"Sí"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"No disponible"</item>
+ <item msgid="2478289035899842865">"Desactivado"</item>
+ <item msgid="5137565285664080143">"Activado"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index c385bd1bf124..9080c5869c53 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Pantalla de notificaciones"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Ajustes rápidos"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Ajustes rápidos y pantalla de notificaciones."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Pantalla de bloqueo."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Pantalla de bloqueo para el perfil de trabajo"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Cerrar"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Brillo"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Invertir colores"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Corrección de color"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Tamaño de fuente"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Gestionar usuarios"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Hecho"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Cerrar"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notificaciones"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Ver combinaciones de teclas"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Cambiar diseño del teclado"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Borrar texto"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Combinaciones de teclas"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Buscar combinaciones de teclas"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Ninguna encontrada"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistema"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Entrada"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Apps abiertas"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"App en uso"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Acceder a la pantalla de notificaciones"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Hacer una captura de pantalla completa"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Acceder a la lista de combinaciones de teclas de apps y del sistema"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Atrás: volver al estado anterior (botón para volver)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Acceder a la pantalla de inicio"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Vista general de aplicaciones abiertas"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Recorrer aplicaciones recientes (hacia delante)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Recorrer aplicaciones recientes (hacia atrás)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Acceder a la lista de todas las apps y a la búsqueda (Buscar/Launcher)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Ocultar y mostrar la barra de tareas"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Acceder a los ajustes del sistema"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Acceder al Asistente de Google"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Pantalla de bloqueo"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Abrir la aplicación de notas para tomar una nota rápida"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Función multitarea del sistema"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Iniciar pantalla dividida con esta aplicación en el lado derecho"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Iniciar pantalla dividida con esta aplicación en el lado izquierdo"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Cambiar de pantalla dividida a pantalla completa"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Con pantalla dividida: reemplazar una aplicación por otra"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Entrada"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Cambiar idioma de entrada (idioma siguiente)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Cambiar idioma de entrada (idioma anterior)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Acceder a los emojis"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Acceder a Escribir por voz"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Aplicaciones"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Asistencia"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Navegador"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Navegador (Chrome como predeterminado)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Contactos"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Correo electrónico"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Correo (Gmail como predeterminado)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Música"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendario"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculadora"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"No molestar"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Acceso directo de los botones de volumen"</string>
<string name="battery" msgid="769686279459897127">"Batería"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"grabación de pantalla"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sin título"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"En espera"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Tamaño de fuente"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Reducir tamaño"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Aumentar tamaño"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Ventana de ampliación"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Ventana de controles de ampliación"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Ampliar"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"Se ha producido un error. Inténtalo de nuevo."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Cargando"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"tablet"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"Enviando tu contenido multimedia"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"Enviando <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactivo, comprobar aplicación"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"No se ha encontrado"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Control no disponible"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"No se puede emitir"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"No se puede guardar. Inténtalo de nuevo."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"No se puede guardar."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Usa 4 caracteres como mínimo"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Usa menos de 16 caracteres"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número de compilación"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Número de compilación copiado en el portapapeles."</string>
<string name="basic_status" msgid="2315371112182658176">"Conversación abierta"</string>
@@ -983,7 +1018,7 @@
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Datos móviles"</string>
<string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Conectado"</string>
- <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Conectada temporalmente"</string>
+ <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Conectado temporalmente"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"Conexión inestable"</string>
<string name="mobile_data_off_summary" msgid="3663995422004150567">"Los datos móviles no se conectarán automáticamente"</string>
<string name="mobile_data_no_connection" msgid="1713872434869947377">"Sin conexión"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Al menos un dispositivo debe estar disponible"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Mantén pulsado el acceso directo"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Cancelar"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Usar ahora"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Despliega el teléfono para hacer un selfie mejor"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"¿Usar pantalla frontal para hacer mejores selfies?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Usa la cámara trasera para hacer fotos más amplias y con mayor resolución."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Esta pantalla se apagará"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Cambia de pantalla ahora"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Abre el teléfono"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"¿Cambiar de pantalla?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Para una mayor resolución, usa la cámara trasera"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Para una mayor resolución, gira el teléfono"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo plegable desplegándose"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo plegable mostrado desde varios ángulos"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Batería restante: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Cambiar al perfil de trabajo"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Cerrar"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Ajustes de pantalla de bloqueo"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Red Wi-Fi no disponible"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Cámara bloqueada"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Cámara y micrófono bloqueados"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Micrófono bloqueado"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Modo Prioridad activado"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"El Asistente está activado"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es/tiles_states_strings.xml b/packages/SystemUI/res/values-es/tiles_states_strings.xml
index fe4cbedb6b36..7451e6b9ada8 100644
--- a/packages/SystemUI/res/values-es/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-es/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Desactivado"</item>
<item msgid="5966994759929723339">"Activado"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"No disponible"</item>
+ <item msgid="2478289035899842865">"Desactivado"</item>
+ <item msgid="5137565285664080143">"Activado"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index dc6361d11946..9ce7dbf74354 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Märguande vari."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Kiirseaded."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Kiirseaded ja märguandeala."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Kuva lukustamine."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Töö lukustuskuva"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Sulgemine"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Heledus"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Värvide ümberpööramine"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Värviparandus"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Fondi suurus"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Kasutajate haldamine"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Valmis"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Sule"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Märguanded"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Klaviatuuri otseteed"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Klaviatuuripaigutuse vahetus"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Teksti kustutamine"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Otseteed"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Otseteede otsing"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Otseteid ei leitud"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Süsteem"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Sisend"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Rakenduste avamine"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Praegune rakendus"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Juurdepääs märguandealale"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Täisekraanipildi jäädvustamine"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Juurdepääs süsteemi/rakenduste otseteede loendile"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Tagasi: eelmisesse olekusse naasmine (tagasinupp)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Juurdepääs avakuvale"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Avatud rakenduste ülevaade"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Hiljutiste rakenduste sirvimine (edasi)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Hiljutiste rakenduste sirvimine (tagasi)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Juurdepääs kõigi rakenduste ja otsingute loendile (st Otsing/Käivitusprogramm)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Tegumiriba peitmine ja kuvamine"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Juurdepääs süsteemi seadetele"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Juurdepääs Google\'i assistendile"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Lukustuskuva"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Rakenduse Märkmed avamine kiirmemo jaoks"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Süsteemi multitegumtöö"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Ekraanikuva jagamine, nii et praegune rakendus on paremal"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Ekraanikuva jagamine, nii et praegune rakendus on vasakul"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Jagatud ekraanikuvalt täisekraanile lülitamine"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Ekraanikuva jagamise ajal: ühe rakenduse asendamine teisega"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Sisend"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Sisendkeele vahetamine (järgmine keel)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Sisendkeele vahetamine (eelmine keel)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Juurdepääs emotikonile"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Juurdepääs häälsisestusele"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Rakendused"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Abi"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Brauser"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Brauser (vaikimisi Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Kontaktid"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"E-post"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"E-post (vaikimisi Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Muusika"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalender"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kalkulaator"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Mitte segada"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Helitugevuse nuppude otsetee"</string>
<string name="battery" msgid="769686279459897127">"Aku"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ekraanikuva salvest."</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Pealkiri puudub"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Ooterežiim"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Fondi suurus"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Vähendamine"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Suurendamine"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Suurendamisaken"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Suurendamisakna juhtelemendid"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Suumi sisse"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"Midagi läks valesti. Proovige uuesti."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Laadimine"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"tahvelarvuti"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"Teie meedia ülekandmine"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"Rakenduse <xliff:g id="APP_LABEL">%1$s</xliff:g> ülekandmine"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Passiivne, vaadake rakendust"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ei leitud"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Juhtelement pole saadaval"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Ei saa üle kanda"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Ei saa salvestada. Proovige uuesti."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Ei saa salvestada."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Kasutage vähemalt 4 tähemärki"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Kasutage vähem kui 16 tähemärki"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Järgunumber"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Järgunumber kopeeriti lõikelauale."</string>
<string name="basic_status" msgid="2315371112182658176">"Avage vestlus"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Vähemalt üks seade on saadaval"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Pikalt puudutamise otsetee"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Tühista"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Pööra kohe ümber"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Voltige telefon parema selfi jaoks lahti"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Kas kasutada parema selfi jaoks esikaamerat?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Kasutage tagakülje kaamerat, et jäädvustada suurema eraldusvõimega laiem foto."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ See ekraan lülitatakse välja"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Vaheta ekraane kohe"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Telefoni lahtivoltimine"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Kas vahetada ekraane?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Suurema eraldusvõime saavutamiseks kasutage tagakaamerat"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Suurema eraldusvõime saavutamiseks pöörake telefon ümber"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Volditava seadme lahtivoltimine"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Volditava seadme ümberpööramine"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Akutase on <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Lülitu tööprofiilile"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Sule"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Lukustuskuva seaded"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"WiFi pole saadaval"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kaamera on blokeeritud"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kaamera ja mikrofon on blokeeritud"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon on blokeeritud"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioriteetne režiim on sisse lülitatud"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistent on aktiveeritud"</string>
</resources>
diff --git a/packages/SystemUI/res/values-et/tiles_states_strings.xml b/packages/SystemUI/res/values-et/tiles_states_strings.xml
index 07eddef9383e..6a9edbbe812a 100644
--- a/packages/SystemUI/res/values-et/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-et/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Väljas"</item>
<item msgid="5966994759929723339">"Sees"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Pole saadaval"</item>
+ <item msgid="2478289035899842865">"Väljas"</item>
+ <item msgid="5137565285664080143">"Sees"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 0bc82bdda184..d37afbabb58c 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -198,6 +198,8 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Jakinarazpenen panela."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Ezarpen bizkorrak."</string>
+ <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
+ <skip />
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Pantaila blokeatzeko aukera."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Laneko pantaila blokeatua"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Itxi"</string>
@@ -258,6 +260,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Distira"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Kolore-alderantzikatzea"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Koloreen zuzenketa"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Letra-tamaina"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Kudeatu erabiltzaileak"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Eginda"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Itxi"</string>
@@ -613,14 +616,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Jakinarazpenak"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Lasterbideak"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Aldatu tekl. diseinua"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Garbitu testua"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Lasterbideak"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Bilatu lasterbideak"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Ez da aurkitu lasterbiderik"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistema"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Sarrera"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Irekitako aplikazioak"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Uneko aplikazioa"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Atzitu jakinarazpenen panela"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Atera pantaila osoaren argazki bat"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Atzitu sistemaren edo aplikazioetarako lasterbideen zerrenda"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Atzera: itzuli aurreko egoerara (atzera egiteko botoia)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Atzitu hasierako pantaila"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Ikusi irekitako aplikazioen ikuspegi orokorra"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Joan azken aplikazioetako batetik bestera (aurrera)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Joan azken aplikazioetako batetik bestera (atzera)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Atzitu aplikazio guztien zerrenda eta bilatu (adibidez, bilatzeko aukeraren edo Exekutatzeko tresna aplikazioaren bidez)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Ezkutatu eta erakutsi (berriro) zereginen barra"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Atzitu sistemaren ezarpenak"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Atzitu Google-ren Laguntzailea"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Blokeatu pantaila"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Ireki Oharrak aplikazioa oharrak bizkor idazteko"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Zereginen aldibereko sistemaren exekuzioa"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Sartu pantaila zatituaren eskuineko aldean uneko aplikazioarekin"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Sartu pantaila zatituaren ezkerreko aldean uneko aplikazioarekin"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Aldatu pantaila zatitutik pantaila osora"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Pantaila zatituan zaudela: ordeztu aplikazio bat beste batekin"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Sarrera"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Aldatu idazteko hizkuntza (hurrengo hizkuntza)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Aldatu idazteko hizkuntza (aurreko hizkuntza)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Atzitu emojiak"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Atzitu ahozko idazketa"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Aplikazioak"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Laguntzailea"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Arakatzailea"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Ireki arakatzailea (Chrome, modu lehenetsian)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Kontaktuak"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Posta"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Ireki posta elektronikoa (Gmail, modu lehenetsian)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMSak"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Musika"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Ireki Kalkulagailua"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Ireki Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Ez molestatzeko modua"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Bolumen-botoietarako lasterbidea"</string>
<string name="battery" msgid="769686279459897127">"Bateria"</string>
@@ -783,6 +820,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"pantaila-grabaketa"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Ez du izenik"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Egonean"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Letraren tamaina"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Txikitu"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Handitu"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Lupa-leihoa"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Lupa-leihoaren aukerak"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Handitu"</string>
@@ -889,10 +929,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"Arazoren bat izan da. Saiatu berriro."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Kargatzen"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"tableta"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"Multimedia-edukia igortzen"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"<xliff:g id="APP_LABEL">%1$s</xliff:g> aplikazioa igortzen"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktibo; egiaztatu aplikazioa"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ez da aurkitu"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Ez dago erabilgarri kontrolatzeko aukera"</string>
@@ -929,10 +967,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Ezin da iragarri"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Ezin da gorde. Saiatu berriro."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Ezin da gorde."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Erabili lau karaktere gutxienez"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Erabili 16 karaktere baino gutxiago"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Konpilazio-zenbakia"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Kopiatu da konpilazio-zenbakia arbelean."</string>
<string name="basic_status" msgid="2315371112182658176">"Elkarrizketa irekia"</string>
@@ -1059,11 +1095,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Gutxienez gailu bat erabilgarri dago."</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Eduki sakatuta lasterbidea"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Utzi"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Irauli"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Ireki telefonoa autoargazki hobeak ateratzeko"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Telefonoa irauli nahi duzu autoargazki hobeak ateratzeko?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Erabili atzeko kamera kalitate handiagoko argazki zabalago bat ateratzeko."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Pantaila itzali egingo da"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Aldatu pantaila batetik bestera"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Ireki telefonoa"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Pantaila batetik bestera aldatu nahi duzu?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Erabili atzeko kamera bereizmen handiago a lortzeko"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Irauli telefonoa bereizmen handiago a lortzeko"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Gailu tolesgarria zabaltzen"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Gailu tolesgarria biratzen"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Bateriaren <xliff:g id="PERCENTAGE">%s</xliff:g> geratzen da"</string>
@@ -1075,4 +1111,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Aldatu laneko profilera"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Itxi"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Pantaila blokeatuaren ezarpenak"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wifi-konexioa ez dago erabilgarri"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera blokeatuta dago"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera eta mikrofonoa blokeatuta daude"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofonoa blokeatuta dago"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Lehentasun modua aktibatuta dago"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Laguntzailea zerbitzuak arreta jarrita dauka"</string>
</resources>
diff --git a/packages/SystemUI/res/values-eu/tiles_states_strings.xml b/packages/SystemUI/res/values-eu/tiles_states_strings.xml
index 3bf49c8e0c77..d023076ca2bf 100644
--- a/packages/SystemUI/res/values-eu/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-eu/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Desaktibatuta"</item>
<item msgid="5966994759929723339">"Aktibatuta"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Ez dago erabilgarri"</item>
+ <item msgid="2478289035899842865">"Desaktibatuta"</item>
+ <item msgid="5137565285664080143">"Aktibatuta"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index c5fba0b4c58a..9bc513e80856 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -93,7 +93,7 @@
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"مرز سمت راست <xliff:g id="PERCENT">%1$d</xliff:g> درصد"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"در برنامه <xliff:g id="APP">%1$s</xliff:g> در نمایه کاری ذخیره شد"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
- <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> این نماگرفت را تشخیص داد."</string>
+ <string name="screenshot_detected_template" msgid="7940376642921719915">"‫«<xliff:g id="APPNAME">%1$s</xliff:g>» این نماگرفت را تشخیص داد."</string>
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> و سایر برنامه‌های باز این نماگرفت را تشخیص دادند."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"افزودن به یادداشت"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"ضبط‌کننده صفحه‌نمایش"</string>
@@ -188,8 +188,8 @@
<string name="accessibility_battery_level" msgid="5143715405241138822">"باتری <xliff:g id="NUMBER">%d</xliff:g> درصد."</string>
<string name="accessibility_battery_level_with_estimate" msgid="6548654589315074529">"درصد شارژ باتری: <xliff:g id="PERCENTAGE">%1$d</xliff:g>، <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="accessibility_battery_level_charging" msgid="8892191177774027364">"در حال شارژ باتری، <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> درصد"</string>
- <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"درصد شارژ باتری: <xliff:g id="PERCENTAGE">%d</xliff:g>، شارژ شدن برای محافظت از باتری موقتاً متوقف شد."</string>
- <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"درصد شارژ باتری: <xliff:g id="PERCENTAGE">%1$d</xliff:g>، <xliff:g id="TIME">%2$s</xliff:g>، شارژ شدن برای محافظت از باتری موقتاً متوقف شد."</string>
+ <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"شارژ باتری <xliff:g id="PERCENTAGE">%d</xliff:g> درصد است. شارژ شدن برای محافظت از باتری موقتاً متوقف شد."</string>
+ <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"شارژ باتری <xliff:g id="PERCENTAGE">%1$d</xliff:g> درصد، <xliff:g id="TIME">%2$s</xliff:g>. شارژ شدن برای محافظت از باتری موقتاً متوقف شد."</string>
<string name="accessibility_overflow_action" msgid="8555835828182509104">"دیدن همه اعلان‌ها"</string>
<string name="accessibility_tty_enabled" msgid="1123180388823381118">"تله‌تایپ فعال شد."</string>
<string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"زنگ لرزشی."</string>
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"مجموعه اعلان."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"تنظیمات سریع."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"تنظیمات فوری و کشوی اعلانات."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"صفحه قفل."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"صفحه قفل کاری"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"بستن"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"روشنایی"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"وارونگی رنگ"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"تصحیح رنگ"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"اندازه قلم"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"مدیریت کاربران"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"تمام"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"بستن"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"اعلان‌ها"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"میان‌برهای صفحه‌کلید"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"تغییر جانمایی صفحه‌کلید"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"پاک کردن نوشتار"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"میان‌برها"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"جستجوی میان‌برها"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"میان‌بری پیدا نشد"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"سیستم"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"ورودی"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"باز کردن برنامه‌ها"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"برنامه فعلی"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"دسترسی به کشوی اعلانات"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"گرفتن نماگرفت کامل"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"دسترسی به فهرست میان‌برهای برنامه‌ها / سیستم"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"برگشت: برگشتن به وضعیت قبلی (دکمه برگشت)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"دسترسی به صفحه اصلی"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"نمای کلی برنامه‌های باز"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"چرخش میان برنامه‌های اخیر (جلو)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"چرخش میان برنامه‌های اخیر (عقب)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"دسترسی به فهرست همه برنامه‌ها و جستجو (یعنی «جستجو»/ «راه‌انداز»)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"پنهان کردن و نمایش مجدد نوار وظیفه"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"دسترسی به تنظیمات سیستم"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"‏دسترسی به «‏‫دستیار Google‬»"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"قفل صفحه"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"برای یادداشت سریع، برنامه «یادداشت‌ها» را بالا بکشید"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"چندوظیفگی سیستم"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"وارد شدن به صفحهٔ دونیمه با برنامه فعلی در سمت راست"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"وارد شدن به صفحهٔ دونیمه با برنامه فعلی در سمت چپ"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"جابه‌جایی از صفحهٔ دونیمه به تمام صفحه"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"درحین صفحهٔ دونیمه: برنامه‌ای را با دیگری جابه‌جا می‌کند"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"ورودی"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"تغییر زبان ورودی (زبان بعدی)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"تغییر زبان ورودی (زبان قبلی)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"دسترسی به اموجی"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"دسترسی به تایپ صوتی"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"برنامه‌ها"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"دستیار"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"مرورگر"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"‏مرورگر (Chrome به‌عنوان پیش‌فرض)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"مخاطبین"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"ایمیل"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"‏ایمیل (Gmail به‌عنوان پیش‌فرض)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"پیامک"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"موسیقی"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"تقویم"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"ماشین‌حساب"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"مزاحم نشوید"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"میان‌بر دکمه‌های صدا"</string>
<string name="battery" msgid="769686279459897127">"باتری"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ضبط صفحه‌نمایش"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"بدون عنوان"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"آماده‌به‌کار"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"اندازه قلم"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"کوچک‌تر کردن"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"بزرگ‌تر کردن"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"پنجره درشت‌نمایی"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"کنترل‌های پنجره درشت‌نمایی"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"زوم‌پیش کردن"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"مشکلی پیش آمد. دوباره امتحان کنید."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"درحال بار کردن"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"رایانه لوحی"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"پخش محتوای رسانه‌ها"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"پخش محتوای <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"غیرفعال، برنامه را بررسی کنید"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"پیدا نشد"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"کنترل دردسترس نیست"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"همه‌فرستی انجام نشد"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"ذخیره نشد. دوباره امتحان کنید."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"ذخیره نشد."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"حداقل از ۴ نویسه استفاده کنید"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"از کمتر از ۱۶ نویسه استفاده کنید"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"شماره ساخت"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"شماره ساخت در بریده‌دان کپی شد."</string>
<string name="basic_status" msgid="2315371112182658176">"باز کردن مکالمه"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• حداقل یک دستگاه دردسترس باشد"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"میان‌بر را لمس کنید و نگه دارید"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"لغو کردن"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"اکنون چرخانده شود"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"برای خویش‌گرفت بهتر، تلفن را باز کنید"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"برای خویش‌گرفت بهتر، از نمایشگر جلو استفاده شود؟"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"برای عکسی عریض‌تر با وضوح بالاتر، از دوربین عقب استفاده کنید."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ این صفحه‌نمایش خاموش خواهد شد"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"صفحه‌ها اکنون جابه‌جا می‌شود"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"باز کردن تلفن"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"صفحه‌ها جابه‌جا شود؟"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"برای وضوح بیشتر، از دوربین پشت استفاده کنید"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"برای وضوح بیشتر، تلفن را برگردانید"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"دستگاه تاشو درحال باز شدن"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"دستگاه تاشو درحال چرخش به اطراف"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> باتری باقی مانده است"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"رفتن به نمایه کاری"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"بستن"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"تنظیمات صفحه قفل"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"‏Wi-Fi دردسترس نیست"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"دوربین مسدود شده است"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"دوربین و میکروفون مسدود شده‌اند"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"میکروفون مسدود شده است"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"حالت اولویت روشن است"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"توجه «دستیار» روشن است"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fa/tiles_states_strings.xml b/packages/SystemUI/res/values-fa/tiles_states_strings.xml
index 85f0bfdf86dd..b341e9e64c7b 100644
--- a/packages/SystemUI/res/values-fa/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-fa/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"خاموش"</item>
<item msgid="5966994759929723339">"روشن"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"دردسترس نیست"</item>
+ <item msgid="2478289035899842865">"خاموش"</item>
+ <item msgid="5137565285664080143">"روشن"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index d5d2121e9b6f..4c3962e249bc 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -28,7 +28,7 @@
<string name="invalid_charger_text" msgid="2339310107232691577">"Käytä laitteesi mukana tullutta laturia"</string>
<string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Otetaanko virransäästö käyttöön?"</string>
<string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Tietoa virransäästöstä"</string>
- <string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Ota käyttöön"</string>
+ <string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Laita päälle"</string>
<string name="battery_saver_start_action" msgid="8353766979886287140">"Laita päälle"</string>
<string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Ei kiitos"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Näytön automaattinen kääntö"</string>
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Ilmoitusalue."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Pika-asetukset."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Pika-asetukset ja ilmoitusalue"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Lukitse näyttö."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Työlukitusnäyttö"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Sulje"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Kirkkaus"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Käänteiset värit"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Värinkorjaus"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Fonttikoko"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Ylläpidä käyttäjiä"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Valmis"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Sulje"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Ilmoitukset"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Pikanäppäimet"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Vaihda näppäimistöasettelu"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Tyhjennä teksti"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Pikanäppäimet"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Hae pikanäppäimiä"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Pikanäppäimiä ei löytynyt"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Järjestelmä"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Syöttötapa"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Avoimet"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Sovelluslista"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Käytä ilmoitusaluetta"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Ota kuvakaappaus"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Käytä järjestelmän ja sovellusten pikakuvakkeita"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Takaisin: siirry takaisin edelliseen tilaan (takaisin-painike)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Käytä aloitusnäyttöä"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Avointen sovellusten yleiskatsaus"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Selaa viimeaikaisia sovelluksia (eteenpäin)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Selaa viimeaikaisia sovelluksia (takaisin)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Sovellusten ja haun luettelon käyttö (esim. Haku/Käynnistysohjelma)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Piilota ja tuo tehtäväpalkki näkyviin"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Käytä järjestelmäasetuksia"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Käytä Google Assistantia"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Lukitusnäyttö"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Avaa muistiinpanosovellus pikaisia merkintöjä varten"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Järjestelmän monikäyttö"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Siirry jaettuun näyttöön (sovellus oikeanpuoleiseen näyttöön)"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Siirry jaettuun näyttöön (sovellus vasemmanpuoleiseen näyttöön)"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Vaihda jaetusta näytöstä koko näyttöön"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Jaetun näytön aikana: korvaa sovellus toisella"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Syöttötapa"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Vaihda syöttökieli (seuraava kieli)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Vaihda syöttökieli (edellinen kieli)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Emojin käyttö"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Puhekirjoituksen käyttö"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Sovellukset"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Apusovellus"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Selain"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Selain (oletuksena Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Yhteystiedot"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Sähköposti"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Sähköposti (oletuksena Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"Tekstiviesti"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Musiikki"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalenteri"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Laskin"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Älä häiritse"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Äänenvoimakkuuspainikkeiden pikanäppäin"</string>
<string name="battery" msgid="769686279459897127">"Akku"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"näytön tallennus"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Ei nimeä"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Virransäästötila"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Fonttikoko"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Pienennä"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Suurenna"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Suurennusikkuna"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Suurennusikkunan ohjaimet"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Lähennä"</string>
@@ -815,7 +854,7 @@
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Avaa esteettömyysominaisuudet napauttamalla. Yksilöi tai vaihda painike asetuksista.\n\n"<annotation id="link">"Avaa asetukset"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Piilota painike tilapäisesti siirtämällä se reunaan"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Kumoa"</string>
- <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> pikanäppäin poistettu"</string>
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Pikanäppäin (<xliff:g id="FEATURE_NAME">%s</xliff:g>) poistettu"</string>
<string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# pikanäppäin poistettu}other{# pikanäppäintä poistettu}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Siirrä vasempaan yläreunaan"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Siirrä oikeaan yläreunaan"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Ei voi lähettää"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Tallennus ei onnistu. Yritä uudelleen."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Tallennus ei onnistu."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Käytä vähintään 4 merkkiä"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Käytä alle 16 merkkiä"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Koontiversion numero"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Koontiversion numero kopioitu leikepöydälle"</string>
<string name="basic_status" msgid="2315371112182658176">"Avaa keskustelu"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Ainakin yksi laite on käytettävissä"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Kosketa pikakuvaketta pitkään"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Peru"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Käännä nyt"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Saat paremman selfien, kun levität puhelimen"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Käännä etunäytölle, jotta saat paremman selfien?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Voit ottaa laajemman kuvan korkeammalla resoluutiolla, kun käytät takakameraa."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Tämä näyttö sammutetaan"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Vaihda näyttöä nyt"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Taita puhelin auki"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Vaihdetaanko näyttöä?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Resoluutio on parempi, kun käytät takakameraa"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Resoluutio on parempi, kun käännät puhelimen"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Taitettava laite taitetaan"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Taitettava laite käännetään ympäri"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Akkua jäljellä <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Vaihda työprofiiliin"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Sulje"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Lukitusnäytön asetukset"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi-yhteys ei ole käytettävissä"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera estetty"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera ja mikrofoni estetty"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofoni estetty"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Tärkeät-tila on päällä"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant on aktiivinen"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fi/tiles_states_strings.xml b/packages/SystemUI/res/values-fi/tiles_states_strings.xml
index 1505dc5c06bb..bbd64fdb87da 100644
--- a/packages/SystemUI/res/values-fi/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-fi/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Poissa päältä"</item>
<item msgid="5966994759929723339">"Päällä"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Ei saatavilla"</item>
+ <item msgid="2478289035899842865">"Pois päältä"</item>
+ <item msgid="5137565285664080143">"Päällä"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 5d7b7f763a0d..05dec17d3b3b 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -198,6 +198,8 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Volet des notifications"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Paramètres rapides"</string>
+ <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
+ <skip />
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Écran de verrouillage"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Verrouillage de l\'écran du profil professionnel"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Fermer"</string>
@@ -258,6 +260,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Luminosité"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inversion des couleurs"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Correction des couleurs"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Taille de la police"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Gérer les utilisateurs"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Terminé"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Fermer"</string>
@@ -613,14 +616,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notifications"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Raccourcis clavier"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Changer la disposition du clavier"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Effacer le texte"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Raccourcis"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Recherchez des raccourcis"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Aucun raccourci trouvé"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Système"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Entrée"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Ouvrir applis"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Appli actuelle"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Accéder au volet de notification"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Prendre une capture d\'écran complète"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Accéder à la liste des raccourcis du système/des applications"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Retour : retour à l\'état précédent (bouton précédent)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Accéder à l\'écran d\'accueil"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Aperçu des applications ouvertes"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Parcourir les applications récentes (avancer)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Parcourir les applications récentes (retour)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Accéder à la liste des applis et à la recherche (recherche/lanceur)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Masquer et (ré)afficher la barre des tâches"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Accéder aux paramètres système"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Accéder à l\'Assistant Google"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Écran de verrouillage"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Ouvrir l\'application de prise de notes pour prendre des notes rapides"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitâche du système"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Passer à l\'écran partagé avec l\'application actuelle à droite"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Passer à l\'écran partagé avec l\'application actuelle à gauche"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Passer de l\'écran partagé au plein écran"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"En mode d\'écran partagé : remplacer une application par une autre"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Entrée"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Changer la langue d\'entrée (langue suivante)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Changer la langue d\'entrée (langue précédente)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Accéder aux émojis"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Accéder à l\'entrée vocale"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Applications"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Assistance"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Navigateur"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Navigateur (Chrome par défaut)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Contacts"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Courriel"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Courriel (Gmail par défaut)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"Messages texte"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Musique"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Agenda"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculatrice"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Ne pas déranger"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Raccourci des boutons de volume"</string>
<string name="battery" msgid="769686279459897127">"Pile"</string>
@@ -783,6 +820,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"enregistrement d\'écran"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sans titre"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Veille"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Taille de police"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Rapetisser"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Agrandir"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Fenêtre d\'agrandissement"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Commandes pour la fenêtre d\'agrandissement"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Effectuer un zoom avant"</string>
@@ -889,10 +929,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"Une erreur s\'est produite. Réessayez."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Chargement en cours…"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"tablette"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"Diffusion de votre contenu multimédia en cours…"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"Diffusion de <xliff:g id="APP_LABEL">%1$s</xliff:g> en cours…"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Délai expiré, vérifiez l\'appli"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Introuvable"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"La commande n\'est pas accessible"</string>
@@ -929,10 +967,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Impossible de diffuser"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Impossible d\'enregistrer. Réessayez."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Impossible d\'enregistrer."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Utilisez au moins 4 caractères"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Utilisez moins de 16 caractères"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numéro de version"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Le numéro de version a été copié dans le presse-papiers."</string>
<string name="basic_status" msgid="2315371112182658176">"Ouvrir la conversation"</string>
@@ -1059,11 +1095,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• qu\'au moins un appareil est utilisable;"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Maintenir le doigt sur raccourci"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Annuler"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Retourner maintenant"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Déplier le téléphone pour un meilleur égoportrait"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Retourner l\'écran pour un meilleur égoportrait?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Utilisez l\'appareil photo arrière pour une photo plus large avec une résolution supérieure."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"* Cet écran va s\'éteindre"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Changer d\'écran maintenant"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Déplier le téléphone"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Changer d\'écran?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Pour une meilleure résolution, utilisez l\'appareil photo arrière"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Pour une meilleure résolution, retournez le téléphone"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Appareil pliable en cours de dépliage"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Appareil pliable en train d\'être retourné"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Charge restante de la pile : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1075,4 +1111,16 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Passer au profil professionnel"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Fermer"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Paramètres écran de verrouillage"</string>
+ <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
+ <skip />
+ <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
+ <skip />
+ <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
+ <skip />
+ <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
+ <skip />
+ <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
+ <skip />
+ <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml b/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml
index c4088652fbdd..8df62113b674 100644
--- a/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Désactivé"</item>
<item msgid="5966994759929723339">"Activé"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Non accessible"</item>
+ <item msgid="2478289035899842865">"Désactivée"</item>
+ <item msgid="5137565285664080143">"Activée"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index ec9d7e9de0d4..0e089c893eaf 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Volet des notifications"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Réglages rapides"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Réglages rapides et volet des notifications."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Écran de verrouillage"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Écran de verrouillage du profil professionnel"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Fermer"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Luminosité"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inversion des couleurs"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Correction des couleurs"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Taille de la police"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Gérer les utilisateurs"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"OK"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Fermer"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notifications"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Raccourcis clavier"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Changer disposition du clavier"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Effacer le texte"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Raccourcis"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Raccourcis de recherche"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Aucun raccourci trouvé"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Système"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Saisie"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Applis ouvertes"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Appli actuelle"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Accéder au volet des notifications"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Prendre une capture d\'écran complète"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Accéder à la liste des raccourcis d\'applis/système"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Retour : revenir à l\'état précédent (bouton Retour)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Accéder à l\'écran d\'accueil"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Aperçu des applis ouvertes"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Parcourir les applis récentes (avancer)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Parcourir les applis récentes (reculer)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Accéder à la liste d\'applis et rechercher (Recherche/Lanceur d\'applis)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Masquer et (ré)afficher la barre des tâches"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Accéder aux paramètres système"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Accéder à l\'Assistant Google"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Verrouiller l\'écran"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Tirer l\'appli de notes vers le haut pour une note rapide"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitâche du système"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Passer en écran partagé avec l\'appli actuelle affichée à droite"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Passer en écran partagé avec l\'appli actuelle affichée à gauche"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Passer de l\'écran partagé au plein écran"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"En mode écran partagé : remplacer une appli par une autre"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Saisie"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Changer la langue de saisie (langue suivante)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Changer la langue de saisie (langue précédente)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Accéder aux emoji"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Accéder à la saisie vocale"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Applications"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Assistance"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Navigateur"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Parcourir (Chrome par défaut)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Contacts"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Messagerie"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"E-mail (Gmail par défaut)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Musique"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Agenda"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculatrice"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Ne pas déranger"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Raccourci des boutons de volume"</string>
<string name="battery" msgid="769686279459897127">"Batterie"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"enregistrement écran"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sans titre"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Mode Veille imminent"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Taille de police"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Réduire"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Agrandir"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Fenêtre d\'agrandissement"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Fenêtre des commandes d\'agrandissement"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Faire un zoom avant"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"Un problème est survenu. Réessayez."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Chargement…"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"tablette"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"Casting de vos contenus multimédias"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"Casting de <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Délai expiré, vérifier l\'appli"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Introuvable"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Commande indisponible"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Impossible de diffuser"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Impossible d\'enregistrer. Réessayez."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Impossible d\'enregistrer."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Utilisez au moins quatre caractères"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Utilisez moins de 16 caractères"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numéro de build"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Numéro de build copié dans le presse-papiers."</string>
<string name="basic_status" msgid="2315371112182658176">"Conversation ouverte"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Au moins un appareil est disponible"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Appuyez de manière prolongée sur raccourci"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Annuler"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Retourner"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Déplier le téléphone pour un meilleur selfie"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Passer à l\'écran frontal pour un meilleur selfie ?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Utilisez la caméra arrière pour prendre une photo plus large d\'une résolution supérieure."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Cet écran s\'éteindra"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Changer d\'écran maintenant"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Déplier le téléphone"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Changer d\'écran ?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Pour une résolution plus élevée, utilisez la caméra arrière"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Pour une résolution plus élevée, retournez le téléphone"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Appareil pliable qui est déplié"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Appareil pliable qui est retourné"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> de batterie restante"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Passer au profil professionnel"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Fermer"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Paramètres écran de verrouillage"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi non disponible"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Caméra bloquée"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Caméra et micro bloqués"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Micro bloqué"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Mode Prioritaire activé"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant à l\'écoute"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr/tiles_states_strings.xml b/packages/SystemUI/res/values-fr/tiles_states_strings.xml
index 8c6c4f555a5c..ce39cd2dc78d 100644
--- a/packages/SystemUI/res/values-fr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-fr/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Désactivé"</item>
<item msgid="5966994759929723339">"Activé"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Non disponible"</item>
+ <item msgid="2478289035899842865">"Désactivé"</item>
+ <item msgid="5137565285664080143">"Activé"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index e2633add983d..ea532f5f82af 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Panel despregable"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Configuración rápida"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Configuración rápida e panel despregable."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Pantalla de bloqueo."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Pantalla de bloqueo do perfil de traballo"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Pechar"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Brillo"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inversión da cor"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Corrección da cor"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Tamaño do tipo de letra"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Administrar usuarios"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Feito"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Pechar"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notificacións"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Atallos de teclado"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Cambiar deseño do teclado"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Borrar o texto"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Atallos"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Buscar atallos"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Non se atoparon atallos"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistema"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Entrada"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Abrir aplicacións"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"App actual"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Acceder ao panel despregable"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Facer captura de pantalla completa"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Acceder á lista de atallos do sistema ou das aplicacións"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Atrás: Volver ao estado anterior (botón Atrás)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Acceder á pantalla de inicio"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Visión xeral de aplicacións abertas"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Percorrer aplicacións recentes (adiante)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Percorrer aplicacións recentes (atrás)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Acceder á lista de apps e á busca (por exemplo, a Busca ou Launcher)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Ocultar e volver mostrar barra de tarefas"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Acceder á configuración do sistema"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Acceder ao Asistente de Google"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Pantalla de bloqueo"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Abrir aplicación Notas para facer unha nota rápida"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitarefa do sistema"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Activar pantalla dividida con esta aplicación no lado dereito"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Activar pantalla dividida con esta aplicación no lado esquerdo"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Cambiar de pantalla dividida a pantalla completa"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"En modo de pantalla dividida: Substituír unha aplicación por outra"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Entrada"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Cambiar idioma de escritura (seguinte idioma)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Cambiar idioma de escritura (idioma anterior)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Acceder aos emojis"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Acceder á escritura por voz"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Aplicacións"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Asistente"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Navegador"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Navegador (predeterminado: Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Contactos"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Correo electrónico"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Correo electrónico (predeterminado: Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Música"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculadora"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Non molestar"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Atallo dos botóns de volume"</string>
<string name="battery" msgid="769686279459897127">"Batería"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"gravación pantalla"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sen título"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Modo de espera"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Tamaño do tipo de letra"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Reducir o tamaño"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Aumentar o tamaño"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Ventá de superposición"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Controis de ampliación da ventá"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Achegar"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"Produciuse un erro. Téntao de novo."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Cargando"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"tableta"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"Emitindo contido multimedia"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"Emitindo <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactivo. Comproba a app"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Non se atopou"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"O control non está dispoñible"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Non se puido iniciar a emisión"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Non se puido gardar a información. Téntao de novo."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Non se pode gardar a información."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Utiliza como mínimo 4 caracteres"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Utiliza menos de 16 caracteres"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número de compilación"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Copiouse o número de compilación no portapapeis."</string>
<string name="basic_status" msgid="2315371112182658176">"Conversa aberta"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Ten que haber polo menos un dispositivo dispoñible"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Mantén premido o atallo"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Cancelar"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Voltear agora"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Desprega o teléfono para unha autofoto mellor"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Usar a cámara dianteira para unha autofoto mellor?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Usa a cámara traseira para sacar unha foto máis ampla e con maior resolución."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Desactivarase esta pantalla"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Cambiar de pantalla agora"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Desprega o teléfono"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Queres cambiar de pantalla?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Usa a cámara traseira para gozar dunha maior resolución"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Dálle a volta ao teléfono para gozar dunha maior resolución"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo pregable abríndose"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo pregable xirando"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Batería restante: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Cambiar ao perfil de traballo"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Pechar"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Configuración pantalla bloqueo"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wifi non dispoñible"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"A cámara está bloqueada"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"A cámara e o micrófono están bloqueados"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"O micrófono está bloqueado"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"O modo de prioridade está activado"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"A atención do Asistente está activada"</string>
</resources>
diff --git a/packages/SystemUI/res/values-gl/tiles_states_strings.xml b/packages/SystemUI/res/values-gl/tiles_states_strings.xml
index 590ec4ac515c..b03f31171e5c 100644
--- a/packages/SystemUI/res/values-gl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-gl/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Desactivado"</item>
<item msgid="5966994759929723339">"Activado"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Non dispoñible"</item>
+ <item msgid="2478289035899842865">"Desactivado"</item>
+ <item msgid="5137565285664080143">"Activado"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 45ed81bc77ab..3f2b494bc4b2 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"નોટિફિકેશન શેડ."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ઝડપી સેટિંગ."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ઝડપી સેટિંગ અને નોટિફિકેશન શેડ."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"લૉક સ્ક્રીન."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"કાર્ય લૉક સ્ક્રીન"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"બંધ કરો"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"તેજ"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"વિપરીત રંગમાં બદલવું"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"રંગ સુધારણા"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"ફૉન્ટનું કદ"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"વપરાશકર્તાઓને મેનેજ કરો"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"થઈ ગયું"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"બંધ કરો"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"નોટિફિકેશન"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"કીબોર્ડ શૉર્ટકટ"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"કીબોર્ડ લેઆઉટ સ્વિચ કરો"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"ટેક્સ્ટ સાફ કરો"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"શૉર્ટકટ"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"શૉર્ટકટ શોધો"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"કોઈ શૉર્ટકટ મળ્યો નથી"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"સિસ્ટમ"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"ઇનપુટ"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"ઍપ ખોલો"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"હાલની ઍપ"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"નોટિફિકેશન શેડ ઍક્સેસ કરો"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"કોઈ આખો સ્ક્રીનશૉટ લો"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"સિસ્ટમ / ઍપ્લિકેશન શૉર્ટકટની સૂચિ ઍક્સેસ કરો"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"પાછળ: પાછળની સ્થિતિ પર પાછા જાઓ (પાછળ બટન)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"હોમ સ્ક્રીન ઍક્સેસ કરો"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"ખુલ્લી ઍપનો ઓવરવ્યૂ"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"તાજેતરની ઍપ વચ્ચે સ્વિચ કરો (ફૉરવર્ડ)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"તાજેતરની ઍપ વચ્ચે સ્વિચ કરો (પાછળ)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"તમામ ઍપ અને શોધની સૂચિ (દા.ત. Search/Launcher) ઍક્સેસ કરો"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"ટાસ્કબાર છુપાવો અને (ફરી) બતાવો"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"સિસ્ટમ સેટિંગ ઍક્સેસ કરો"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Google Assistant ઍક્સેસ કરો"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"લૉક સ્ક્રીન"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"ઝડપી મેમો માટે Notes ઍપ ખોલો"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"સિસ્ટમ દ્વારા એકથી વધુ કાર્યો કરવા"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"જમણી બાજુ પર હાલની ઍપ વડે વિભાજિત સ્ક્રીન દાખલ કરો"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"ડાબી બાજુ પર હાલની ઍપ વડે વિભાજિત સ્ક્રીન દાખલ કરો"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"વિભાજિત સ્ક્રીનથી પૂર્ણ સ્ક્રીન પર સ્વિચ કરો"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"વિભાજિત સ્ક્રીન દરમિયાન: એક ઍપને બીજી ઍપમાં બદલો"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"ઇનપુટ"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"ઇનપુટની ભાષા સ્વિચ કરો (આગલી ભાષા)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"ઇનપુટની ભાષા સ્વિચ કરો (પાછલી ભાષા)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"ઇમોજી ઍક્સેસ કરો"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"વૉઇસ ટાઇપિંગ ઍક્સેસ કરો"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"ઍપ્લિકેશનો"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"સહાય"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"બ્રાઉઝર"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"બ્રાઉઝર (ડિફૉલ્ટ તરીકે Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"સંપર્કો"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"ઇમેઇલ"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"ઇમેઇલ (ડિફૉલ્ટ તરીકે Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"મ્યુઝિક"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"કેલ્ક્યુલેટર"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"ખલેલ પાડશો નહીં"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"વૉલ્યૂમ બટન્સ શૉર્ટકટ"</string>
<string name="battery" msgid="769686279459897127">"બૅટરી"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"સ્ક્રીન રેકોર્ડિંગ"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"કોઈ શીર્ષક નથી"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"સ્ટૅન્ડબાય"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"ફૉન્ટનું કદ"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"વધુ નાનું બનાવો"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"વધુ મોટું બનાવો"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"વિસ્તૃતીકરણ વિંડો"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"વિસ્તૃતીકરણ વિંડોના નિયંત્રણો"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"મોટું કરો"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"કંઈક ખોટું થયું. ફરી પ્રયાસ કરો."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"લોડ થઈ રહ્યું છે"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"ટૅબ્લેટ"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"તમારું મીડિયા કાસ્ટ કરી રહ્યાં છીએ"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"<xliff:g id="APP_LABEL">%1$s</xliff:g> કાસ્ટ કરી રહ્યાં છીએ"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"નિષ્ક્રિય, ઍપને ચેક કરો"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"મળ્યું નથી"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"નિયંત્રણ ઉપલબ્ધ નથી"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"બ્રોડકાસ્ટ કરી શકતા નથી"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"સાચવી શકતા નથી. ફરી પ્રયાસ કરો."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"સાચવી શકતા નથી."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ઓછામાં ઓછા 4 અક્ષરનો ઉપયોગ કરો"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16 કરતાં ઓછા અક્ષરનો ઉપયોગ કરો"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"બિલ્ડ નંબર"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"બિલ્ડ નંબર ક્લિપબૉર્ડ પર કૉપિ કર્યો."</string>
<string name="basic_status" msgid="2315371112182658176">"વાતચીત ખોલો"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• ઓછામાં ઓછું એક ડિવાઇસ ઉપલબ્ધ છે"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"શૉર્ટકટને ટચ વડે પળભર દબાવી રાખો"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"રદ કરો"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"હમણાં જ ફ્લિપ કરો"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"બહેતર સેલ્ફી લેવા માટે ફોન ખોલો"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"બહેતર સેલ્ફી લેવા ફ્રન્ટ ડિસ્પ્લે પર ફ્લિપ કરીએ?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"વધુ ઉચ્ચ રિઝોલ્યુશનવાળો વિશાળ ફોટો લેવા માટે પાછલા કૅમેરાનો ઉપયોગ કરો."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ આ સ્ક્રીન બંધ થઈ જશે"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"હમણાં સ્ક્રીન સ્વિચ કરો"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"ફોનને અનફોલ્ડ કરો"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"સ્ક્રીન સ્વિચ કરીએ?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"વધુ રિઝોલ્યુશન માટે, રીઅર કૅમેરાનો ઉપયોગ કરો"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"વધુ રિઝોલ્યુશન માટે, ફોનને ફ્લિપ કરો"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ફોલ્ડ કરી શકાય એવું ડિવાઇસ અનફોલ્ડ કરવામાં આવી રહ્યું છે"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ફોલ્ડ કરી શકાય એવું ડિવાઇસ ફ્લિપ કરવામાં આવી રહ્યું છે"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> બૅટરી બાકી છે"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"ઑફિસની પ્રોફાઇલ પર સ્વિચ કરો"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"બંધ કરો"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"લૉક સ્ક્રીનના સેટિંગ"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"વાઇ-ફાઇ ઉપલબ્ધ નથી"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"કૅમેરા બ્લૉક કરેલો છે"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"કૅમેરા અને માઇક્રોફોન બ્લૉક કરેલા છે"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"માઇક્રોફોન બ્લૉક કરેલો છે"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"પ્રાધાન્યતા મોડ ચાલુ છે"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant સક્રિય છે"</string>
</resources>
diff --git a/packages/SystemUI/res/values-gu/tiles_states_strings.xml b/packages/SystemUI/res/values-gu/tiles_states_strings.xml
index cc062a772149..5d1ad6ff0514 100644
--- a/packages/SystemUI/res/values-gu/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-gu/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"બંધ છે"</item>
<item msgid="5966994759929723339">"ચાલુ છે"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"અનુપલબ્ધ"</item>
+ <item msgid="2478289035899842865">"બંધ"</item>
+ <item msgid="5137565285664080143">"ચાલુ"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index f13ba41c6031..c49861bf4f70 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"सूचना शेड."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"त्वरित सेटिंग."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"क्विक सेटिंग और नोटिफ़िकेशन शेड."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"लॉक स्क्रीन."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"वर्क लॉक स्‍क्रीन"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"बंद करें"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"स्क्रीन की रोशनी"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"रंग बदलने की सुविधा"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"रंग में सुधार करने की सुविधा"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"फ़ॉन्ट का साइज़"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"उपयोगकर्ताओं को मैनेज करें"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"हो गया"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"रद्द करें"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"सूचनाएं"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"कीबोर्ड शॉर्टकट"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"कीबोर्ड लेआउट बदलें"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"टेक्स्ट मिटाएं"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"शॉर्टकट"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"शॉर्टकट खोजें"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"कोई शॉर्टकट नहीं मिला"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"सिस्टम"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"इनपुट"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"खुले हुए ऐप्लिकेशन"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"मौजूदा ऐप्लिकेशन"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"नोटिफ़िकेशन शेड को ऐक्सेस करें"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"पूरा स्क्रीनशॉट लें"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"सिस्टम / ऐप्लिकेशन के शॉर्टकट की सूची ऐक्सेस करें"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"वापस जाएं: पिछली स्क्रीन पर वापस जाएं (\'वापस जाएं\' बटन)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"होम स्क्रीन को ऐक्सेस करें"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"खुले हुए ऐप्लिकेशन की जानकारी"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"हाल ही में इस्तेमाल किए गए ऐप्लिकेशन पर जाएं (सबसे पहले इस्तेमाल किए गए ऐप्लिकेशन सबसे पहले)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"हाल ही में इस्तेमाल किए गए ऐप्लिकेशन पर जाएं (सबसे हाल के ऐप्लिकेशन सबसे पहले)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"सभी ऐप्लिकेशन और की गई खोजों की सूची ऐक्सेस करें (जैसे, Search/लॉन्चर)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"टास्कबार छिपाएं और (फिर से) दिखाएं"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"सिस्टम की सेटिंग ऐक्सेस करें"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Google Assistant को ऐक्सेस करें"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"लॉक स्क्रीन"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"तेज़ी से मेमो बनाने के लिए Notes ऐप्लिकेशन का इस्तेमाल करें"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"सिस्टम मल्टीटास्किंग"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"मौजूदा ऐप्लिकेशन को स्प्लिट स्क्रीन की मदद से दाईं ओर ले जाएं"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"मौजूदा ऐप्लिकेशन को स्प्लिट स्क्रीन की मदद से बाईं ओर ले जाएं"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"स्प्लिट स्क्रीन से फ़ुल स्क्रीन मोड पर जाएं"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"स्प्लिट स्क्रीन के दौरान: एक ऐप्लिकेशन को दूसरे से बदलें"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"इनपुट"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"इनपुट भाषा बदलें (अगली भाषा)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"इनपुट भाषा बदलें (पिछली भाषा)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"इमोजी ऐक्सेस करें"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"बोली को लिखाई में बदलने की सुविधा ऐक्सेस करें"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"ऐप्लिकेशन"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"सहायक"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"ब्राउज़र"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"ब्राउज़र (डिफ़ॉल्ट के तौर पर Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"संपर्क"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"ईमेल"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"ईमेल (डिफ़ॉल्ट के तौर पर Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"मैसेज (एसएमएस) करें"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"संगीत"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"कैलकुलेटर"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"मैप"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"परेशान न करें"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"वॉल्यूम बटन का शॉर्टकट"</string>
<string name="battery" msgid="769686279459897127">"बैटरी"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"स्क्रीन रिकॉर्डिंग"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"कोई शीर्षक नहीं"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"स्टैंडबाई"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"फ़ॉन्ट का साइज़"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"छोटा करें"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"बड़ा करें"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"स्क्रीन को बड़ा करके दिखाने वाली विंडो"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"स्क्रीन को बड़ा करके दिखाने वाली विंडो के नियंत्रण"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"ज़ूम इन करें"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"कोई गड़बड़ी हुई. फिर से कोशिश करें."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"लोड हो रहा है"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"टैबलेट"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"आपका मीडिया कास्ट किया जा रहा है"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"<xliff:g id="APP_LABEL">%1$s</xliff:g> को कास्ट किया जा रहा है"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"काम नहीं कर रहा, ऐप जांचें"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"कंट्रोल नहीं है"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"कंट्रोल मौजूद नहीं है"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"ब्रॉडकास्ट नहीं किया जा सकता"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"सेव नहीं किया जा सका. फिर से कोशिश करें."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"सेव नहीं किया जा सका."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"कम से कम चार वर्ण इस्तेमाल करें"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16 वर्ण से कम इस्तेमाल करें"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"बिल्ड नंबर"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"बिल्ड नंबर को क्लिपबोर्ड पर कॉपी किया गया."</string>
<string name="basic_status" msgid="2315371112182658176">"ऐसी बातचीत जिसमें इंटरैक्शन डेटा मौजूद नहीं है"</string>
@@ -1048,7 +1083,7 @@
<string name="log_access_confirmation_title" msgid="4843557604739943395">"क्या <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> को डिवाइस लॉग का ऐक्सेस देना है?"</string>
<string name="log_access_confirmation_allow" msgid="752147861593202968">"एक बार ऐक्सेस करने की अनुमति दें"</string>
<string name="log_access_confirmation_deny" msgid="2389461495803585795">"अनुमति न दें"</string>
- <string name="log_access_confirmation_body" msgid="6883031912003112634">"डिवाइस लॉग में आपके डिवाइस पर की गई कार्रवाइयां रिकॉर्ड होती हैं. ऐप्लिकेशन, इन लॉग का इस्तेमाल गड़बड़ियां ढूंढने और उन्हें सही करने के लिए करता है.\n\nकुछ लॉग में संवेदनशील जानकारी हो सकती है. इसलिए, सिर्फ़ भरोसेमंद ऐप्लिकेशन को डिवाइस के सभी लॉग का ऐक्सेस दें. \n\nअगर इस ऐप्लिकेशन को डिवाइस के सभी लॉग का ऐक्सेस नहीं दिया जाता है, तब भी यह डिवाइस पर मौजूद अपने लॉग ऐक्सेस कर सकता है. डिवाइस को बनाने वाली कंपनी अब भी डिवाइस के कुछ लॉग या जानकारी को ऐक्सेस कर सकती है."</string>
+ <string name="log_access_confirmation_body" msgid="6883031912003112634">"डिवाइस लॉग में आपके डिवाइस पर की गई कार्रवाइयां रिकॉर्ड होती हैं. ऐप्लिकेशन, इन लॉग का इस्तेमाल गड़बड़ियां ढूंढने और उन्हें ठीक करने के लिए कर सकते हैं.\n\nकुछ लॉग में संवेदनशील जानकारी हो सकती है. इसलिए, सिर्फ़ भरोसेमंद ऐप्लिकेशन को डिवाइस के सभी लॉग का ऐक्सेस दें. \n\nअगर इस ऐप्लिकेशन को डिवाइस के सभी लॉग का ऐक्सेस नहीं दिया जाता है, तब भी यह डिवाइस पर मौजूद अपने लॉग ऐक्सेस कर सकता है. डिवाइस को बनाने वाली कंपनी फिर भी डिवाइस के कुछ लॉग या जानकारी ऐक्सेस कर सकती है."</string>
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"ज़्यादा जानें"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"ज़्यादा जानने के लिए <xliff:g id="URL">%s</xliff:g> पर जाएं"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> खोलें"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• कम से कम एक डिवाइस उपलब्ध है"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"शॉर्टकट को दबाकर रखें"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"रद्द करें"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"अभी स्विच करें"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"बेहतर सेल्फ़ी के लिए फ़ोन को अनफ़ोल्ड करें"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"बेहतर सेल्फ़ी के लिए फ़्रंट डिसप्ले पर स्विच करें?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"वाइड ऐंगल में हाई रिज़ॉल्यूशन वाली फ़ोटो लेने के लिए, पीछे का कैमरा इस्तेमाल करें."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ यह स्क्रीन बंद हो जाएगी"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"अब स्क्रीन स्विच करें"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"अपना फ़ोन अनफ़ोल्ड करें"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"स्क्रीन स्विच करनी है?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"बेहतर रिज़ॉल्यूशन वाली फ़ोटो खींचने के लिए, पीछे का कैमरा इस्तेमाल करें"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"बेहतर रिज़ॉल्यूशन वाली फ़ोटो खींचने के लिए, फ़ोन को फ़्लिप करें"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"फ़ोल्ड किया जा सकने वाला डिवाइस अनफ़ोल्ड किया जा रहा है"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"फ़ोल्ड किया जा सकने वाला डिवाइस पलटा जा रहा है"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> बैटरी बची है"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"वर्क प्रोफ़ाइल पर स्विच करें"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"बंद करें"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"लॉक स्क्रीन की सेटिंग"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"वाई-फ़ाई उपलब्ध नहीं है"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"कैमरे का ऐक्सेस नहीं है"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"कैमरे और माइक्रोफ़ोन का ऐक्सेस नहीं है"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"माइक्रोफ़ोन का ऐक्सेस नहीं है"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"प्राथमिकता मोड चालू है"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant आपकी बातें सुन रही है"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hi/tiles_states_strings.xml b/packages/SystemUI/res/values-hi/tiles_states_strings.xml
index a156b0c43ca6..cd29fb92063f 100644
--- a/packages/SystemUI/res/values-hi/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-hi/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"बंद है"</item>
<item msgid="5966994759929723339">"चालू है"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"अभी उपलब्ध नहीं है"</item>
+ <item msgid="2478289035899842865">"बंद है"</item>
+ <item msgid="5137565285664080143">"चालू है"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 8f6e95cc15f2..9c94f7bdb13a 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Zaslon obavijesti."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Brze postavke."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Brze postavke i zaslon obavijesti."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Zaključavanje zaslona."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Zaključan zaslon radnog profila"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Zatvaranje"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Svjetlina"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inverzija boja"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Korekcija boja"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Veličina fonta"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Upravljajte korisnicima"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Gotovo"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Zatvori"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Obavijesti"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Tipkovni prečaci"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Promjena rasporeda tipkovnice"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Ukloni tekst"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Prečaci"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Pretražite prečace"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nema nađenih prečaca"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sustav"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Unos"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Otvaranje aplikacija"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Trenutačna aplikacija"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Pristupanje zaslonu obavijesti"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Izrada snimke cijelog zaslona"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Pristupanje popisu prečaca sustava/aplikacija"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Natrag: povratak na prethodno stanje (gumb za natrag)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Pristupanje početnom zaslonu"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Pregled otvorenih aplikacija"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Pregledavanje nedavnih aplikacija (unaprijed)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Pregledavanje nedavnih aplikacija (unatrag)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Pristupanje popisu svih aplikacija i pretraživanja (npr. Pretraživanje/Pokretač)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Sakrivanje i (ponovno) prikazivanje trake sa zadacima"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Pristupanje postavkama sustava"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Pristupanje Google asistentu"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Zaključavanje zaslona"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Izvlačenje aplikacije Bilješke za brzu bilješku"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Obavljanje više zadataka sustava"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Otvorite podijeljeni zaslon s trenutačnom aplikacijom s desne strane"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Otvorite podijeljeni zaslon s trenutačnom aplikacijom s lijeve strane"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Prijelaz s podijeljenog zaslona na cijeli zaslon"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Tijekom podijeljenog zaslona: zamijenite aplikaciju drugom"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Unos"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Prebacivanje jezika unosa (sljedeći jezik)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Prebacivanje jezika unosa (prethodni jezik)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Pristupanje emojijima"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Pristupanje unosu teksta govorom"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Aplikacije"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Pomoć"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Preglednik"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Preglednik (Chrome kao zadani)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Kontakti"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"E-pošta"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"E-pošta (Gmail kao zadani)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Glazba"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalendar"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kalkulator"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Karte"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Ne uznemiravaj"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Prečac tipki za glasnoću"</string>
<string name="battery" msgid="769686279459897127">"Baterija"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"snimanje zaslona"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Bez naslova"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Stanje mirovanja"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Veličina fonta"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Smanji"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Povećaj"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Prozor za povećavanje"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kontrole prozora za povećavanje"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Povećaj"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Emitiranje nije uspjelo"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Spremanje nije uspjelo. Pokušajte ponovo."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Spremanje nije uspjelo."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Upotrijebite barem četiri znaka"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Upotrijebite manje od 16 znakova"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Broj međuverzije"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Broj međuverzije kopiran je u međuspremnik."</string>
<string name="basic_status" msgid="2315371112182658176">"Otvoreni razgovor"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Dostupan je najmanje jedan uređaj"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Prečac za dodirnuti i zadržati"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Odustani"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Prebaci"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Otvorite telefon da biste snimili bolji selfie"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Prebaciti na prednji zaslon za bolji selfie?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Upotrijebite stražnji fotoaparat za širu fotografiju s višom razlučivošću."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Ovaj će se zaslon isključiti"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Promijenite zaslon odmah"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Otklopite telefon"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Želite li promijeniti zaslon?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Za višu razlučivost upotrijebite stražnju kameru"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Za višu razlučivost okrenite telefon"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Rasklopljen sklopivi uređaj"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Okretanje sklopivog uređaja sa svih strana"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Preostalo je <xliff:g id="PERCENTAGE">%s</xliff:g> baterije"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Prijeđite na poslovni profil"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Zatvori"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Postavke zaključanog zaslona"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi nije dostupan"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera je blokirana"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Blokirani su kamera i mikrofon"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon je blokiran"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Uključen je prioritetni način rada"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Pažnja Asistenta je aktivirana"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hr/tiles_states_strings.xml b/packages/SystemUI/res/values-hr/tiles_states_strings.xml
index b69b06419281..32051ef19743 100644
--- a/packages/SystemUI/res/values-hr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-hr/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Isključeno"</item>
<item msgid="5966994759929723339">"Uključeno"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Nedostupno"</item>
+ <item msgid="2478289035899842865">"Isključeno"</item>
+ <item msgid="5137565285664080143">"Uključeno"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 74765ccf4445..b9c606724ccf 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Értesítési felület."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Gyorsbeállítások."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Gyorsbeállítások és értesítési terület"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Lezárási képernyő."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Munka lezárási képernyővel"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Bezárás"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Fényerő"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Színek invertálása"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Színjavítás"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Betűméret"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Felhasználók kezelése"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Kész"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Bezárás"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Értesítések"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Billentyűkódok"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Billentyűzetkiosztás váltása"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Szöveg törlése"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Billentyűparancsok"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Billentyűparancs keresése"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nincs billentyűparancs"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Rendszer"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Bevitel"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Futó appok"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Aktuális app"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Ugrás az értesítési felületre"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Teljes képernyőkép készítése"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Ugrás a rendszer-/alkalmazás-parancsikonok listájához"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Vissza: visszaváltás az előző állapotra (vissza gomb)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Ugrás a kezdőképernyőre"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Megnyitott alkalmazások áttekintése"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Lépegetés a legutóbbi appok között (előre)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Lépegetés a legutóbbi appok között (visszafelé)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Ugrás az összes app listájához és a kereséshez (pl. Kereső/Indító)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Elrejtés és a feladatsáv (újbóli) megjelenítése"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Ugrás a rendszerbeállításokhoz"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Ugrás a Google Segédhez"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Lezárási képernyő"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"A jegyzetkészítő app megnyitása gyors feljegyzés készítéséhez"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Rendszermultitasking"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Osztott képernyő aktiválása, az aktuális app kerüljön jobbra"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Osztott képernyő aktiválása, az aktuális app kerüljön balra"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Váltás osztott képernyőről teljes képernyőre"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Osztott képernyőn: az egyik app lecserélése egy másikra"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Bevitel"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Beviteli nyelv váltása (következő nyelv)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Beviteli nyelv váltása (előző nyelv)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Ugrás az emojikhoz"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Ugrás a hangvezérelt íráshoz"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Alkalmazások"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Segédalkalmazás"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Böngésző"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Böngésző (alapértelmezés szerint: Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Névjegyek"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"E-mail"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"E-mail-alkalmazás (alapértelmezés szerint: Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS-üzenetek"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Zene"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Naptár"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Számológép"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Térkép"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Ne zavarjanak"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"A hangerőgombok gyorsbillentyűk"</string>
<string name="battery" msgid="769686279459897127">"Akkumulátor"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"képernyőrögzítés"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Nincs cím"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Készenléti mód"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Betűméret"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Kisebb"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Nagyobb"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Nagyítás ablaka"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Nagyítási vezérlők ablaka"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Nagyítás"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Nem sikerült a közvetítés"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"A mentés nem sikerült. Próbálja újra."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"A mentés nem sikerült."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Legalább négy karaktert használjon"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Legfeljebb 16 karaktert használhat"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Buildszám"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Buildszám a vágólapra másolva."</string>
<string name="basic_status" msgid="2315371112182658176">"Beszélgetés megnyitása"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Legalább egy eszköz rendelkezésre áll"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Tartsa nyomva a parancsikont"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Mégse"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Átfordítás most"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Hajtsa ki a telefont jobb szelfi készítéséhez"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Átfordítja az előlapi kijelzőre a jobb szelfiért?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Használja az előlapi kamerát, hogy nagyobb felbontású, szélesebb fotót készíthessen"</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ A képernyő kikapcsol"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Váltson képernyőt most"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Hajtsa ki a telefont"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Szeretne képernyőt váltani?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"A nagyobb felbontás érdekében használja a hátlapi kamerát."</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"A nagyobb felbontás érdekében fordítsa meg a telefont"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Összehajtható eszköz kihajtása"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Összehajtható eszköz körbeforgatása"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Akkumulátor töltöttségi szintje: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Váltás munkaprofilra"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Bezárás"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Lezárási képernyő beállításai"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Nem áll rendelkezésre Wi-Fi"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera letiltva"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera és mikrofon letiltva"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon letiltva"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioritás mód bekapcsolva"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"A Segéd figyel"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hu/tiles_states_strings.xml b/packages/SystemUI/res/values-hu/tiles_states_strings.xml
index 050bc14d54ff..157c552b31a6 100644
--- a/packages/SystemUI/res/values-hu/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-hu/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Ki"</item>
<item msgid="5966994759929723339">"Be"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Nem áll rendelkezésre"</item>
+ <item msgid="2478289035899842865">"Ki"</item>
+ <item msgid="5137565285664080143">"Be"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 7cad53b7b744..018120a7f28a 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -188,7 +188,7 @@
<string name="accessibility_battery_level" msgid="5143715405241138822">"Մարտկոցը <xliff:g id="NUMBER">%d</xliff:g> տոկոս է:"</string>
<string name="accessibility_battery_level_with_estimate" msgid="6548654589315074529">"Մարտկոցի լիցքը <xliff:g id="PERCENTAGE">%1$d</xliff:g> տոկոս է։ Այն կաշխատի <xliff:g id="TIME">%2$s</xliff:g>։"</string>
<string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Մարտկոցը լիցքավորվում է: Լիցքը <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> տոկոս է:"</string>
- <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"Մարտկոցի լիցքը <xliff:g id="PERCENTAGE">%d</xliff:g> է։ Լիցքավորումը դադարեցվել է՝ մարտկոցը պաշտպանելու համար։"</string>
+ <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"Մարտկոցի լիցքը <xliff:g id="PERCENTAGE">%d</xliff:g> տոկոս է։ Լիցքավորումը դադարեցվել է՝ մարտկոցը պաշտպանելու համար։"</string>
<string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"Մարտկոցի լիցքը <xliff:g id="PERCENTAGE">%1$d</xliff:g> է։ Այն կաշխատի <xliff:g id="TIME">%2$s</xliff:g>։ Լիցքավորումը դադարեցվել է՝ մարտկոցը պաշտպանելու նպատակով։"</string>
<string name="accessibility_overflow_action" msgid="8555835828182509104">"Տեսնել բոլոր ծանուցումները"</string>
<string name="accessibility_tty_enabled" msgid="1123180388823381118">"Հեռատիպը միացված է:"</string>
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Ծանուցումների վահանակ:"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Արագ կարգավորումներ:"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Արագ կարգավորումներ և ծանուցումների վահանակ։"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Էկրանի կողպում:"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Աշխատանքային պրոֆիլի կողպէկրան"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Փակել"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Պայծառություն"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Գունաշրջում"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Գունաշտկում"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Տառաչափ"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Կառավարել օգտատերերին"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Պատրաստ է"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Փակել"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Ծանուցումներ"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Ստեղնային դյուրանցումներ"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Դասավորության փոխարկում"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Ջնջել տեքստը"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Դյուրանցումներ"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Դյուրանցումների որոնում"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Դյուրանցումներ չեն գտնվել"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Համակարգ"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Ներածում"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Բաց հավելվածներ"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Այս հավելվածը"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Բացել ծանուցումների վահանակը"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Ստեղծել ամբողջ էկրանի սքրինշոթ"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Բացել համակարգի/հավելվածների դյուրանցումների ցանկը"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Վերադառնալ նախկին վիճակին («Հետ» կոճակ)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Բացել հիմնական էկրանը"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Բաց հավելվածների համատեսք"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Դիտել վերջին հավելվածները (սովորական հերթականությամբ)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Դիտել վերջին հավելվածները (հակառակ հերթականությամբ)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Բացել բոլոր հավելվածների և որոնումների (օր.՝ Որոնում/Գործարկիչ) ցանկը"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Թաքցնել և (նորից) ցուցադրել հավելվածների վահանակը"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Բացել համակարգի կարգավորումները"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Գործարկել Google Օգնականը"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Կողպէկրան"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Բացել «Նշումներ» հավելվածը՝ արագ նշում ստեղծելու համար"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Համակարգի բազմախնդրության ռեժիմ"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Միացնել էկրանի տրոհումը՝ ընթացիկ հավելվածն աջ կողմում"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Միացնել էկրանի տրոհումը՝ ընթացիկ հավելվածը ձախ կողմում"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Տրոհված էկրանից անցնել լիաէկրան ռեժիմ"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Տրոհված էկրանի ռեժիմում մեկ հավելվածը փոխարինել մյուսով"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Ներածում"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Անցնել ներածման հաջորդ լեզվին"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Անցնել ներածման նախորդ լեզվին"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Բացել էմոջիները"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Ակտիվացնել ձայնային մուտքագրումը"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Հավելվածներ"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Օգնություն"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Դիտարկիչ"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Դիտարկիչ (Chrome-ը որպես կանխադրված)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Կոնտակտներ"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Էլփոստ"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Էլփոստ (Gmail-ը որպես կանխադրված)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Երաժշտություն"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Օրացույց"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Հաշվիչ"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Քարտեզներ"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Չանհանգստացնել"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Ձայնի կոճակների դյուրանցում"</string>
<string name="battery" msgid="769686279459897127">"Մարտկոց"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"էկրանի տեսագրում"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Անանուն"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Սպասման ռեժիմ"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Տառաչափ"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Փոքրացնել"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Մեծացնել"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Խոշորացման պատուհան"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Խոշորացման պատուհանի կառավարման տարրեր"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Մեծացնել"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Չհաջողվեց հեռարձակել"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Չհաջողվեց պահել։ Նորից փորձեք։"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Չհաջողվեց պահել։"</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Օգտագործեք առնվազն 4 նիշ"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Օգտագործեք ոչ ավել քան 16 նիշ"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Կառուցման համարը"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Կառուցման համարը պատճենվեց սեղմատախտակին։"</string>
<string name="basic_status" msgid="2315371112182658176">"Բաց զրույց"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Հասանելի է առնվազն մեկ սարք"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Հպեք դյուրանցմանը և պահեք"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Չեղարկել"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Շրջել հիմա"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Բացեք հեռախոսի փեղկը՝ ավելի լավ սելֆի անելու համար"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Հեռախոսը էկրանով դեպի ձե՞զ շրջեցիք"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Օգտագործեք հետևի տեսախցիկը՝ ավելի բարձր լուծաչափով և ավելի լայն լուսանկար ստանալու համար։"</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Այս էկրանը կանջատվի"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Փոխել էկրանը հիմա"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Բացեք հեռախոսի փեղկը"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Փոխե՞լ էկրանը"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Ավելի մեծ լուծաչափի համար օգտագործեք հիմնական տեսախցիկը"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Ավելի մեծ լուծաչափի համար շրջեք հեռախոսը"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Ծալովի սարք՝ բացված վիճակում"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Ծալովի սարք՝ շրջված վիճակում"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Մարտկոցի լիցքը՝ <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Անցնել աշխատանքային պրոֆիլ"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Փակել"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Կողպէկրանի կարգավորումներ"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi ցանց հասանելի չէ"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Տեսախցիկն արգելափակված է"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Տեսախցիկն ու խոսափողը արգելափակված են"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Խոսափողն արգելափակված է"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Առաջնահերթության ռեժիմը միացված է"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Օգնականը լսում է"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hy/tiles_states_strings.xml b/packages/SystemUI/res/values-hy/tiles_states_strings.xml
index 6015fbd75b3c..089716fa51d6 100644
--- a/packages/SystemUI/res/values-hy/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-hy/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Անջատված է"</item>
<item msgid="5966994759929723339">"Միացված է"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Հասանելի չէ"</item>
+ <item msgid="2478289035899842865">"Անջատված է"</item>
+ <item msgid="5137565285664080143">"Միացված է"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index f03dc0f83264..d76d2ffcfc0d 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Bayangan pemberitahuan."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Setelan cepat."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Setelan cepat dan Menu notifikasi."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Layar kunci."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Layar kunci kantor"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Tutup"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Kecerahan"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inversi warna"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Koreksi warna"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Ukuran font"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Kelola pengguna"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Selesai"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Tutup"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notifikasi"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Pintasan keyboard"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Ganti tata letak keyboard"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Hapus teks"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Pintasan"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Pintasan penelusuran"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Tidak ditemukan pintasan"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistem"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Input"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Aplikasi yang terbuka"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Aplikasi saat ini"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Akses menu notifikasi"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Ambil screenshot penuh"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Akses daftar sistem/pintasan aplikasi"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Kembali: kembali ke status sebelumnya (tombol kembali)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Akses layar utama"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Ringkasan aplikasi yang terbuka"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Berpindah-pindah antara aplikasi terbaru (maju)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Berpindah-pindah antara aplikasi terbaru (mundur)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Akses daftar semua aplikasi dan penelusuran (yaitu Penelusuran/Peluncur)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Sembunyikan dan tampilkan (kembali) taskbar"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Akses setelan sistem"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Akses Asisten Google"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Kunci layar"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Buka aplikasi Catatan untuk memo cepat"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitasking sistem"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Masuk ke Layar terpisah dengan aplikasi saat ini ke RHS"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Masuk ke Layar terpisah dengan aplikasi saat ini ke LHS"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Beralih dari Layar terpisah ke layar penuh"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Dalam Layar terpisah: ganti dari satu aplikasi ke aplikasi lainnya"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Input"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Beralih bahasa input (bahasa berikutnya)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Beralih bahasa input (bahasa sebelumnya)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Akses emoji"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Akses dikte"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Aplikasi"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Bantuan"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Browser"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Browser (Chrome sebagai default)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Kontak"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Email"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Email (Gmail sebagai default)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Musik"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalender"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kalkulator"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Jangan Ganggu"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Pintasan tombol volume"</string>
<string name="battery" msgid="769686279459897127">"Baterai"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"perekaman layar"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Tanpa judul"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Siaga"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Ukuran Font"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Buat lebih kecil"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Buat lebih besar"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Jendela Pembesaran"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kontrol Jendela Pembesaran"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Perbesar"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"Terjadi error. Coba lagi."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Memuat"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"tablet"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"Mentransmisikan media"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"Mentransmisikan <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Nonaktif, periksa aplikasi"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Tidak ditemukan"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Kontrol tidak tersedia"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Tidak dapat menyiarkan"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Tidak dapat menyimpan. Coba lagi."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Tidak dapat menyimpan."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Gunakan minimal 4 karakter"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Gunakan kurang dari 16 karakter"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Nomor build"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Nomor versi disalin ke papan klip."</string>
<string name="basic_status" msgid="2315371112182658176">"Membuka percakapan"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Tersedia minimal satu perangkat"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Sentuh lama pintasan"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Batal"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Balik sekarang"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Bentangkan ponsel untuk selfie yang lebih baik"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Balik ke layar depan untuk selfie yang lebih bagus?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Gunakan kamera belakang untuk foto dengan resolusi lebih tinggi dan lebih lebar."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Layar ini akan dinonaktifkan"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Beralih layar sekarang"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Bentangkan ponsel"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Beralih layar?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Untuk resolusi lebih tinggi, gunakan kamera belakang"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Untuk resolusi lebih tinggi, balik ponsel"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Perangkat foldable sedang dibentangkan"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Perangkat foldable sedang dibalik"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Baterai tersisa <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Beralih ke profil kerja"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Tutup"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Setelan layar kunci"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi tidak tersedia"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera diblokir"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera dan mikrofon diblokir"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon diblokir"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Mode prioritas diaktifkan"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Asisten sedang memerhatikan"</string>
</resources>
diff --git a/packages/SystemUI/res/values-in/tiles_states_strings.xml b/packages/SystemUI/res/values-in/tiles_states_strings.xml
index 5416c8f77ca6..71460a71b414 100644
--- a/packages/SystemUI/res/values-in/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-in/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Nonaktif"</item>
<item msgid="5966994759929723339">"Aktif"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Tidak tersedia"</item>
+ <item msgid="2478289035899842865">"Nonaktif"</item>
+ <item msgid="5137565285664080143">"Aktif"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 24c5e977c1e1..228052440538 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -188,8 +188,8 @@
<string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> prósent á rafhlöðu."</string>
<string name="accessibility_battery_level_with_estimate" msgid="6548654589315074529">"Hleðsla rafhlöðu er <xliff:g id="PERCENTAGE">%1$d</xliff:g> prósent, <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Rafhlaða í hleðslu, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%."</string>
- <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"Hleðsla rafhlöðu er <xliff:g id="PERCENTAGE">%d</xliff:g> prósent, hlé gert á hleðslu til að vernda rafhlöðuna."</string>
- <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"Hleðsla rafhlöðu er <xliff:g id="PERCENTAGE">%1$d</xliff:g> prósent, <xliff:g id="TIME">%2$s</xliff:g>, hlé gert á hleðslu til að vernda rafhlöðuna."</string>
+ <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"Rafhleðsla er <xliff:g id="PERCENTAGE">%d</xliff:g> prósent, hlé gert á hleðslu til að vernda rafhlöðuna."</string>
+ <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"Rafhleðsla er <xliff:g id="PERCENTAGE">%1$d</xliff:g> prósent, <xliff:g id="TIME">%2$s</xliff:g>, hlé gert á hleðslu til að vernda rafhlöðuna."</string>
<string name="accessibility_overflow_action" msgid="8555835828182509104">"Sjá allar tilkynningar"</string>
<string name="accessibility_tty_enabled" msgid="1123180388823381118">"Fjarriti virkur."</string>
<string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Titrar við hringingu."</string>
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Tilkynningasvæði."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Flýtistillingar."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Flýtistillingar og tilkynningagluggi."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Lásskjár."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Vinnulásskjár"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Loka"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Birtustig"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Umsnúningur lita"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Litaleiðrétting"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Leturstærð"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Stjórna notendum"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Lokið"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Loka"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Tilkynningar"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Flýtilyklar"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Skipta um lyklaskipan"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Hreinsa texta"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Flýtileiðir"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Leita að flýtileiðum"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Engar flýtileiðir fundust"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Kerfi"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Innsláttur"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Opna forrit"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Gildandi forrit"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Opna tilkynningaglugga"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Taka heildarskjámynd"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Opna lista yfir flýtileiðir fyrir kerfi/forrit"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Til baka: Fara til baka í fyrri stöðu (bakkhnappur)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Opna heimaskjá"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Yfirlit yfir opin forrit"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Fletta í gegnum nýleg forrit (áfram)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Fletta í gegnum nýleg forrit (til baka)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Opna lista yfir öll forrit og leit (þ.e. Leit/Ræsiforrit)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Fela og sýna (aftur) forritastiku"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Opna kerfisstillingar"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Opna Google-hjálpara"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Lásskjár"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Opna glósuforrit til að skrá minnispunkt á fljótlegan hátt"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Fjölvinnsla kerfis"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Opna skjáskiptingu hægra megin með núverandi forriti"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Opna skjáskiptingu vinstra megin með núverandi forriti"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Skipta úr skjáskiptingu yfir í allan skjáinn"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Í skjáskiptingu: Skipta forriti út fyrir annað forrit"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Innsláttur"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Breyta innsláttartungumáli (næsta tungumál)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Breyta innsláttartungumáli (fyrra tungumál)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Opna emoji-tákn"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Opna raddinnslátt"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Forrit"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Aðstoð"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Vafri"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Vafri (Chrome sem sjálfgefinn)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Tengiliðir"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Tölvupóstur"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Tölvupóstur (Gmail sem sjálfgefinn)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS-skilaboð"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Tónlist"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Dagatal"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Reiknivél"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Kort"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Ónáðið ekki"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Flýtihnappar fyrir hljóðstyrk"</string>
<string name="battery" msgid="769686279459897127">"Rafhlaða"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"skjáupptaka"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Enginn titill"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Biðstaða"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Leturstærð"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Minnka"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Stækka"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Stækkunargluggi"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Stækkunarstillingar glugga"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Auka aðdrátt"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"Eitthvað fór úrskeiðis. Reyndu aftur."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Hleður"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"spjaldtölva"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"Sendir út efni frá þér"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"Sendir út <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Óvirkt, athugaðu forrit"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Fannst ekki"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Stýring er ekki tiltæk"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Ekki hægt að senda út"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Ekki hægt að vista. Reyndu aftur."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Ekki hægt að vista."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Notaðu að minnsta kosti 4 stafi"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Notaðu færri en 16 stafi"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Útgáfunúmer smíðar"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Útgáfunúmer smíðar afritað á klippiborð."</string>
<string name="basic_status" msgid="2315371112182658176">"Opna samtal"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Að minnsta kosti eitt tæki er tiltækt"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Haltu flýtilyklinum inni"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Hætta við"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Snúa núna"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Opnaðu símann til að taka betri sjálfsmynd"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Snúa á framskjá til að ná betri sjálfsmynd?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Notaðu aftari myndavélina til að ná víðara sjónarhorni með meiri upplausn."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Slökkt verður á þessum skjá"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Skipta um skjá núna"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Opnaðu símann"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Skipta um skjá?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Notaðu aftari myndavélina til að fá betri upplausn"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Snúðu símanum til að fá betri upplausn"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Samanbrjótanlegt tæki opnað"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Samanbrjótanlegu tæki snúið við"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> hleðsla eftir á rafhlöðu"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Skipta yfir í vinnusnið"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Loka"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Stillingar fyrir lásskjá"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi er ekki til staðar"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Lokað fyrir myndavél"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Lokað fyrir myndavél og hljóðnema"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Lokað fyrir hljóðnema"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Kveikt er á forgangsstillingu"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Hjálparinn er að hlusta"</string>
</resources>
diff --git a/packages/SystemUI/res/values-is/tiles_states_strings.xml b/packages/SystemUI/res/values-is/tiles_states_strings.xml
index 12dd776a357c..17aaf6c2a877 100644
--- a/packages/SystemUI/res/values-is/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-is/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Slökkt"</item>
<item msgid="5966994759929723339">"Kveikt"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Ekki tiltækt"</item>
+ <item msgid="2478289035899842865">"Slökkt"</item>
+ <item msgid="5137565285664080143">"Kveikt"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index bd34e749086e..873138209b9d 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Area notifiche."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Impostazioni rapide."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Area notifiche e Impostazioni rapide."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Schermata di blocco."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Schermata di blocco del profilo di lavoro"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Chiudi"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Luminosità"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inversione dei colori"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Correzione del colore"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Dimensioni carattere"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Gestisci utenti"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Fine"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Chiudi"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notifiche"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Scorciatoie da tastiera"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Cambia layout della tastiera"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Cancella testo"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Scorciatoie"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Cerca scorciatoie"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Scorciatoie non trovate"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistema"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Inserimento"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Aprire app"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"App corrente"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Accedi all\'area notifiche"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Acquisisci uno screenshot completo"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Accedi all\'elenco di scorciatoie app/di sistema"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Indietro: torna allo stato precedente (pulsante Indietro)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Accedi alla schermata Home"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Panoramica delle app aperte"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Scorri le app recenti (in avanti)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Scorri le app recenti (a ritroso)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Accedi all\'elenco di tutte le app e alla ricerca (Ricerca/Avvio app)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Nascondi e mostra di nuovo la barra delle app"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Accedi alle impostazioni di sistema"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Accedi all\'Assistente Google"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Blocca lo schermo"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Visualizza l\'app Note per rapidi appunti"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitasking di sistema"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Attiva lo schermo diviso con l\'app corrente a destra"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Attiva lo schermo diviso con l\'app corrente a sinistra"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Passa da schermo diviso a schermo intero"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Con lo schermo diviso: sostituisci un\'app con un\'altra"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Inserimento"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Cambia lingua di inserimento (lingua successiva)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Cambia lingua di inserimento (lingua precedente)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Accedi all\'emoji"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Accedi alla digitazione vocale"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Applicazioni"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Assistenza"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Browser"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Browser (quello predefinito è Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Contatti"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Email"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Email (l\'app predefinita è Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Musica"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendario"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calcolatrice"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Non disturbare"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Pulsanti del volume come scorciatoia"</string>
<string name="battery" msgid="769686279459897127">"Batteria"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"Registraz. schermo"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Senza titolo"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Standby"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Dimensioni carattere"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Rimpicciolisci"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Ingrandisci"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Finestra ingrandimento"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Finestra controlli di ingrandimento"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Aumenta lo zoom"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Impossibile trasmettere"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Impossibile salvare. Riprova."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Impossibile salvare."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Usa almeno 4 caratteri"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Usa meno di 16 caratteri"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numero build"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Numero build copiato negli appunti."</string>
<string name="basic_status" msgid="2315371112182658176">"Apri conversazione"</string>
@@ -1046,7 +1083,7 @@
<string name="log_access_confirmation_title" msgid="4843557604739943395">"Vuoi consentire all\'app <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> di accedere a tutti i log del dispositivo?"</string>
<string name="log_access_confirmation_allow" msgid="752147861593202968">"Consenti accesso una tantum"</string>
<string name="log_access_confirmation_deny" msgid="2389461495803585795">"Non consentire"</string>
- <string name="log_access_confirmation_body" msgid="6883031912003112634">"I log del dispositivo registrano tutto ciò che succede sul tuo dispositivo. Le app possono usare questi log per individuare problemi e correggerli.\n\nAlcuni log potrebbero contenere informazioni sensibili, quindi concedi l\'accesso a tutti i log del dispositivo soltanto alle app attendibili. \n\nSe le neghi l\'accesso a tutti i log del dispositivo, questa app può comunque accedere ai propri log. Il produttore del tuo dispositivo potrebbe essere comunque in grado di accedere ad alcuni log o informazioni sul dispositivo."</string>
+ <string name="log_access_confirmation_body" msgid="6883031912003112634">"I log del dispositivo registrano tutto ciò che succede sul tuo dispositivo. Le app possono usare questi log per individuare problemi e correggerli.\n\nAlcuni log potrebbero contenere informazioni sensibili, quindi concedi l\'accesso a tutti i log del dispositivo soltanto alle app attendibili. \n\nSe neghi l\'accesso a tutti i log del dispositivo, questa app può comunque accedere ai propri log. Il produttore del tuo dispositivo potrebbe essere comunque in grado di accedere ad alcuni log o informazioni sul dispositivo."</string>
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Scopri di più"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Scopri di più all\'indirizzo <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Apri <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Ci sia almeno un dispositivo disponibile"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Tocca scorciatoia/tieni premuto"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Annulla"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Gira ora"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Apri il telefono per un selfie migliore"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Passare al display frontale per un selfie migliore?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Utilizza la fotocamera posteriore per una foto più ampia con maggiore risoluzione."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Questo schermo verrà spento"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Cambia schermo ora"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Apri il telefono"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Vuoi cambiare schermo?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Usa la fotocamera posteriore per una maggiore risoluzione"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Gira il telefono per una maggiore risoluzione"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo pieghevole che viene aperto"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo pieghevole che viene capovolto"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> batteria rimanente"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Passa a profilo di lavoro"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Chiudi"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Impostazioni schermata di blocco"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi non disponibile"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Videocamera bloccata"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Videocamera e microfono bloccati"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microfono bloccato"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Modalità priorità attivata"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"L\'assistente è attivo"</string>
</resources>
diff --git a/packages/SystemUI/res/values-it/tiles_states_strings.xml b/packages/SystemUI/res/values-it/tiles_states_strings.xml
index 5ec557bbaf7d..7aa09d420f87 100644
--- a/packages/SystemUI/res/values-it/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-it/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Off"</item>
<item msgid="5966994759929723339">"On"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Non disponibile"</item>
+ <item msgid="2478289035899842865">"Off"</item>
+ <item msgid="5137565285664080143">"On"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index ff9e93f295a0..8946db2bea31 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"לוח התראות."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"הגדרות מהירות."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"הגדרות מהירות ולוח ההתראות."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"מסך נעילה."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"מסך נעילה של עבודה"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"סגירה"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"בהירות"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"היפוך צבעים"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"תיקון צבע"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"גודל הגופן"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"ניהול משתמשים"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"סיום"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"סגירה"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"התראות"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"מקשי קיצור במקלדת"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"החלפה של פריסת מקלדת"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"מחיקת הטקסט"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"מקשי קיצור"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"חיפוש מקשי קיצור"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"לא נמצאו מקשי קיצור"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"מערכת"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"קלט"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"פתיחת אפליקציות"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"האפליקציה הנוכחית"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"גישה ללוח ההתראות"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"ביצוע צילום מסך מלא"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"גישה לרשימת מקשי קיצור של המערכת/אפליקציות"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"חזרה: חזרה למצב הקודם (לחצן \'הקודם\')"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"גישה למסך הבית"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"סקירה כללית של האפליקציות הפתוחות"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"דפדוף בין האפליקציות האחרונות (קדימה)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"דפדוף בין האפליקציות האחרונות (לאחור)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"גישה לרשימת כל האפליקציות ולחיפוש (כלומר חיפוש/מרכז האפליקציות)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"הסתרה והצגה (מחדש) של סרגל האפליקציות"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"גישה להגדרות המערכת"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"‏גישה ל-Google Assistant"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"מסך הנעילה"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"אפשר למשוך למעלה את אפליקציית הפתקים לשימוש מהיר"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"ריבוי משימות מערכת"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"‏כניסה למסך מפוצל עם האפליקציה הנוכחית ל-RHS"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"‏כניסה למסך מפוצל עם האפליקציה הנוכחית ל-LHS"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"החלפה ממסך מפוצל למסך מלא"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"כשהמסך מפוצל: החלפה בין אפליקציה אחת לאחרת"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"קלט"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"החלפת שפת הקלט (השפה הבאה)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"החלפת שפת הקלט (השפה הקודמת)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"גישה לאמוג\'י"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"גישה להכתבה בקול"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"אפליקציות"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"אסיסטנט"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"דפדפן"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"‏דפדפן (Chrome כברירת מחדל)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"אנשי קשר"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"אימייל"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"‏אימייל (Gmail כברירת מחדל)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"מוזיקה"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"יומן"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"מחשבון"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"מפות"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"נא לא להפריע"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"קיצור דרך ללחצני עוצמת קול"</string>
<string name="battery" msgid="769686279459897127">"סוללה"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"הקלטת המסך"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"ללא שם"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"המתנה"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"גודל גופן"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"הקטנה"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"הגדלה"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"חלון הגדלה"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"בקרות של חלון ההגדלה"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"התקרבות"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"לא ניתן לשדר"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"לא ניתן לשמור. כדאי לנסות שוב."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"לא ניתן לשמור."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"יש להזין 4 תווים לפחות"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"אפשר להזין עד 16 תווים"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"‏מספר Build"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"‏מספר ה-Build הועתק ללוח."</string>
<string name="basic_status" msgid="2315371112182658176">"פתיחת שיחה"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• יש לפחות מכשיר אחד זמין"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"מקש קיצור ללחיצה ארוכה"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"ביטול"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"אני רוצה להפוך"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"כדי לצלם תמונת סלפי טובה יותר, פותחים את הטלפון"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"להפוך למסך הקדמי כדי לצלם תמונת סלפי טובה יותר?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"במצלמה האחורית אפשר לצלם תמונה רחבה יותר ברזולוציה גבוהה יותר."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ המסך יכבה"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"כן, אני רוצה להחליף בין המסכים"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"פתיחת הטלפון"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"להחליף בין המסכים?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"כדי לצלם תמונה ברזולוציה גבוהה יותר, כדאי להשתמש במצלמה האחורית"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"כדי לצלם תמונה ברזולוציה גבוהה יותר, כדאי להפוך את הטלפון"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"מכשיר מתקפל עובר למצב לא מקופל"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"מכשיר מתקפל עובר למצב מהופך"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"רמת הטעינה שנותרה בסוללה: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"מעבר לפרופיל עבודה"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"סגירה"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"הגדרות מסך הנעילה"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"‏ה-Wi-Fi לא זמין"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"המצלמה חסומה"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"המצלמה והמיקרופון חסומים"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"המיקרופון חסום"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"מצב \'עדיפות\' מופעל"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"‏Assistant מאזינה"</string>
</resources>
diff --git a/packages/SystemUI/res/values-iw/tiles_states_strings.xml b/packages/SystemUI/res/values-iw/tiles_states_strings.xml
index 91577b81a5d3..d5a0e7236f55 100644
--- a/packages/SystemUI/res/values-iw/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-iw/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"כבוי"</item>
<item msgid="5966994759929723339">"מופעל"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"לא זמין"</item>
+ <item msgid="2478289035899842865">"מושבת"</item>
+ <item msgid="5137565285664080143">"מופעל"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index c05e8b066c26..d5b96d5f5fea 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"通知シェード"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"クイック設定"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"クイック設定と通知シェード。"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ロック画面"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"仕事用プロファイルのロック画面"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"閉じる"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"画面の明るさ"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"色反転"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"色補正"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"フォントサイズ"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"ユーザーを管理"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"完了"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"閉じる"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"通知"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"キーボード ショートカット"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"キーボード レイアウトの切り替え"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"テキストを消去"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ショートカット"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"ショートカットの検索"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"ショートカットがないです"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"システム"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"入力"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"開いているアプリ"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"現在のアプリ"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"通知シェードにアクセス"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"フル スクリーンショットを撮影"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"システム / アプリのショートカットの一覧にアクセス"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"戻る: 前の状態に戻る([戻る] ボタン)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"ホーム画面にアクセス"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"開いているアプリの概要"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"最近使ったアプリを切り替え(進)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"最近使ったアプリを切り替え(戻る)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"すべてのアプリの一覧にアクセスして検索(検索 / ランチャー)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"タスクバーを非表示 /(再)表示"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"システム設定にアクセス"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Google アシスタントにアクセス"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"画面をロック"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"クイックメモのためにメモアプリを表示"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"システム マルチタスク"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"分割画面にして現在のアプリを右側に設定"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"分割画面にして現在のアプリを左側に設定"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"分割画面から全画面に切り替え"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"分割画面中: アプリを順に置換"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"入力"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"入力言語を切り替え(次の言語)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"入力言語を切り替え(前の言語)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"絵文字にアクセス"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"音声入力にアクセス"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"アプリ"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"アシスト"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"ブラウザ"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"ブラウザ(デフォルト: Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"連絡先"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"メール"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"メール(デフォルト: Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"音楽"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"カレンダー"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"電卓"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"マップ"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"サイレント モード"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"音量ボタンのショートカット"</string>
<string name="battery" msgid="769686279459897127">"バッテリー"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"画面の録画"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"タイトルなし"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"スタンバイ"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"フォントサイズ"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"縮小"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"拡大"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"拡大ウィンドウ"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"拡大ウィンドウ コントロール"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"拡大"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"エラーが発生しました。もう一度お試しください。"</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"読み込んでいます"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"タブレット"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"メディアをキャストしています"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"<xliff:g id="APP_LABEL">%1$s</xliff:g> をキャストしています"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"無効: アプリをご確認ください"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"見つかりませんでした"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"コントロールを使用できません"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"ブロードキャストできません"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"保存できません。もう一度お試しください。"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"保存できません。"</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"4 文字以上にしてください"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"使用できる文字数は 16 文字未満です"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ビルド番号"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"ビルド番号をクリップボードにコピーしました。"</string>
<string name="basic_status" msgid="2315371112182658176">"空の会話"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• 利用できるデバイスが 1 台以上ある"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"ショートカットの長押しが必要です"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"キャンセル"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"切り替える"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"高画質で撮るにはスマートフォンを開いてください"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"前面ディスプレイに切り替えて綺麗に撮りましょう"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"高解像度で広い範囲を撮影するには、背面カメラを使用してください。"</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱この画面は OFF になります"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"画面を切り替えましょう"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"スマートフォンを開いてください"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"画面を切り替えますか?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"高解像度で撮るには背面カメラを使用してください"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"高解像度で撮るにはスマートフォンを裏返してください"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"折りたたみ式デバイスが広げられている"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"折りたたみ式デバイスがひっくり返されている"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"バッテリー残量 <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"仕事用プロファイルに切り替える"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"閉じる"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"ロック画面の設定"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi は利用できません"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"カメラはブロックされています"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"カメラとマイクはブロックされています"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"マイクはブロックされています"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"優先モードは ON です"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"アシスタントは起動済みです"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ja/tiles_states_strings.xml b/packages/SystemUI/res/values-ja/tiles_states_strings.xml
index c2a3321dc19f..31158ca59882 100644
--- a/packages/SystemUI/res/values-ja/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ja/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"OFF"</item>
<item msgid="5966994759929723339">"ON"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"使用不可"</item>
+ <item msgid="2478289035899842865">"OFF"</item>
+ <item msgid="5137565285664080143">"ON"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 72d0e1a29250..54101b13de95 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"შეტყობინებების ფარდა"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"სწრაფი პარამეტრები"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"სწრაფი პარამეტრები და შეტყობინებების ფარდა"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ეკრანის დაბლოკვა."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"სამსახურის ჩაკეტილი ეკრანი"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"დახურვა"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"განათება"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"ფერთა ინვერსია"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"ფერთა კორექცია"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"შრიფტის ზომა"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"მომხმარებლების მართვა"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"დასრულდა"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"დახურვა"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"შეტყობინებები"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"კლავიატურის მალსახმობები"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"კლავიატურის განლაგების გადართვა"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"ტექსტის გასუფთავება"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"მალსახმობები"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"მალსახმობების ძიება"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"მალსახმობები ვერ მოიძებნა"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"სისტემა"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"შეყვანა"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"ღია აპები"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"მიმდინარე აპი"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"შეტყობინებების ფარდაზე წვდომა"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"სრული ეკრანის ანაბეჭდის გადაღება"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"სისტემის / აპების მალსახმობებზე წვდომის სია"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"უკან: წინა მდგომარეობაში დაბრუნება (უკან გადასვლის ღილაკი)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"მთავარ ეკრანზე წვდომა"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"ღია აპების მიმოხილვა"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"ბოლო აპების გადახედვა (წინ)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"ბოლო აპების გადახედვა (უკან)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"ყველა აპსა და ძიებაზე წვდომის სია (ე.ი. Search/გამშვები)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"ამოცანათა ზოლის დამალვა და ჩვენება (განმეორებით ჩვენება)"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"სისტემის პარამეტრებზე წვდომა"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Google ასისტენტზე წვდომა"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"ჩაკეტილი ეკრანი"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"ჩანიშვნების აპის ამოწევა სწრაფი ჩანაწერისთვის"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"სისტემის მრავალამოცანიანი რეჟიმი"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"ეკრანის გაყოფის შეყვანა მიმდინარე აპით RHS-ში"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"ეკრანის გაყოფის შეყვანა მიმდინარე აპით LHS-ში"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"გადართვა ეკრანის გაყოფიდან სრულ ეკრანზე"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"ეკრანის გაყოფის დროს: ერთი აპის მეორით ჩანაცვლება"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"შეყვანა"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"შეყვანის ენის შეცვლა (შემდეგი ენა)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"შეყვანის ენის შეცვლა (წინა ენა)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"emoji-ზე წვდომა"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"ხმოვან აკრეფაზე წვდომა"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"აპლიკაციები"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"დახმარება"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"ბრაუზერი"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"ბრაუზერი (Chrome ნაგულისხმევად)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"კონტაქტები"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"ელფოსტა"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"ელფოსტა (Gmail ნაგულისხმევად)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"მუსიკა"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"კალენდარი"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"კალკულატორი"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"არ შემაწუხოთ"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"ხმის ღილაკების მალსახმობი"</string>
<string name="battery" msgid="769686279459897127">"ბატარეა"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ეკრანის ჩაწერა"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"უსათაურო"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"მოლოდინის რეჟიმი"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"შრიფტის ზომა"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"დაპატარავება"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"გადიდება"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"გადიდების ფანჯარა"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"გადიდების კონტროლის ფანჯარა"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"მასშტაბის გადიდება"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"ტრანსლაცია შეუძლებელია"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"შენახვა ვერ ხერხდება. ცადეთ ხელახლა."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"შენახვა ვერ ხერხდება."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"გამოიყენეთ მინიმუმ 4 სიმბოლო."</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"გამოიყენეთ 16-ზე ნაკლები სიმბოლო"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ანაწყობის ნომერი"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"ანაწყობის ნომერი დაკოპირებულია გაცვლის ბუფერში."</string>
<string name="basic_status" msgid="2315371112182658176">"მიმოწერის გახსნა"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• ხელმისაწვდომია მინიმუმ ერთი მოწყობილობა"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"შეხების დაamp; მოცდის მალსახმობი"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"გაუქმება"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"ახლა გადატრიალება"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"გაშალეთ ტელეფონი უკეთესი სელფისთვის"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"გამოვიყენოთ წინა ეკრანი უკეთესი სელფის მისაღებად?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"გამოიყენეთ უკანა კამერა უფრო ფართო ფოტოს გადასაღებად მაღალი გარჩევადობით."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ეს ეკრანი გამოირთვება"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"ეკრანების ახლა გადართვა"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"გაშალეთ ტელეფონი"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"გადაირთოს ეკრანები?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"მაღალი გარჩევადობისთვის გამოიყენეთ უკანა კამერა"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"მაღალი გარჩევადობისთვის ამოაბრუნეთ ტელეფონი"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"დასაკეცი მოწყობილობა იხსნება"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"დასაკეცი მოწყობილობა ტრიალებს"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"დარჩენილია ბატარეის <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"სამსახურის პროფილზე გადართვა"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"დახურვა"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"ჩაკეტილი ეკრანის პარამეტრები"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi მიუწვდომელია"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"კამერა დაბლოკილია"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"კამერა და მიკროფონი დაბლოკილია"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"მიკროფონი დაბლოკილია"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"პრიორიტეტული რეჟიმი ჩართულია"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"ასისტენტის ყურადღების ფუნქცია ჩართულია"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ka/tiles_states_strings.xml b/packages/SystemUI/res/values-ka/tiles_states_strings.xml
index c95187404d48..366030a2231f 100644
--- a/packages/SystemUI/res/values-ka/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ka/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"გამორთულია"</item>
<item msgid="5966994759929723339">"ჩართულია"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"მიუწვდომელია"</item>
+ <item msgid="2478289035899842865">"გამორთული"</item>
+ <item msgid="5137565285664080143">"ჩართული"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index fa1af45e41c5..dce96820cbd2 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Хабарландыру тақтасы"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Жылдам параметрлер."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Жылдам параметрлер мен хабарландыру тақтасы."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Бекіту экраны."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Әрекетті құлыптау экраны"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Жабу"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Жарықтығы"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Түс инверсиясы"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Түсті түзету"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Қаріп өлшемі"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Пайдаланушыларды басқару"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Дайын"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Жабу"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Хабарландырулар"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Перне тіркесімдері"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Пернетақта форматын ауыстыру"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Мәтінді өшіру"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Перне тіркесімдері"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Перне тіркесімдерін іздеу"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Перне тіркесімдері табылмады."</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Жүйе"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Енгізу"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Ашылған қолданбалар"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Ағымдағы қолданба"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Хабарландыру тақтасына кіру"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Толық экранның скриншотын жасау"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Жүйе / қолданба таңбашаларының тізімін пайдалану"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Артқа: алдыңғы күйге қайтару (артқа түймесі)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Негізгі экранға кіру"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Ашылған қолданбаларға шолу"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Соңғы пайдаланылған қолданбаларды қарап шығу (алға)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Соңғы пайдаланылған қолданбаларды қарап шығу (артқа)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Барлық қолданба мен іздеу нәтижесі тізімін (яғни Search/Launcher) пайдалану"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Тапсырмалар жолағын жасыру және (қайта)көрсету"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Жүйе параметрлеріне кіру"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Google Assistant-ке кіру"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Экранды құлыптау"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Жылдам ескертпе жасау үшін ескертпелер қолданбасын ашу"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Жүйе мультитаскингі"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Ағымдағы қолданбамен оң жаққа қарай экранды бөлу режиміне кіру"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Ағымдағы қолданбамен сол жаққа қарай экранды бөлу режиміне кіру"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Экранды бөлу режимінен толық экран режиміне ауысу"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Экранды бөлу кезінде: бір қолданбаны басқасына ауыстыру"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Енгізу"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Енгізу тілін (келесі тіл) ауыстыру"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Енгізу тілін (алдыңғы тіл) ауыстыру"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Эмоджи пайдалану"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Дауыспен теру функциясын пайдалану"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Қолданбалар"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Көмекші"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Браузер"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Браузер (әдепкісінше Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Контактілер"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Электрондық пошта"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Электрондық пошта (әдепкісінше Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"Мәтіндік хабар"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Mузыка"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Күнтізбе"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculator"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Мазаламау"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Дыбыс деңгейі түймелерінің төте жолы"</string>
<string name="battery" msgid="769686279459897127">"Батарея"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"экранды бейнеге жазу"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Атауы жоқ"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Күту режимі"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Қаріп өлшемі"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Кішірейту"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Үлкейту"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Ұлғайту терезесі"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Ұлғайту терезесінің басқару элементтері"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Ұлғайту"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"Бірдеңе дұрыс болмады. Қайталап көріңіз."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Жүктеліп жатыр"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"планшет"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"Медиаконтентті трансляциялау"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"Трансляция: <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Өшірулі. Қолданба тексеріңіз."</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Табылмады"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Басқару виджеті қолжетімсіз"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Тарату мүмкін емес"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Сақталмайды. Қайталап көріңіз."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Сақталмайды."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Кемінде 4 таңба пайдаланыңыз."</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Ең көбі 16 таңба пайдаланыңыз."</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Құрама нөмірі"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Құрама нөмірі буферге көшірілді."</string>
<string name="basic_status" msgid="2315371112182658176">"Ашық әңгіме"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Кемінде бір құрылғы қолжетімді"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Таңбашаны басып тұрыңыз."</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Бас тарту"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Айналдыру"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Жақсырақ селфи түсіру үшін телефонды жазыңыз"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Жақсырақ селфи үшін алдыңғы экранға ауысасыз ба?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Ажыратымдылығы жоғары кеңірек фотосурет түсіру үшін артқы камераны пайдаланыңыз."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Бұл экран өшіріледі."</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Экрандарды қазір ауыстыру"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Телефонды ашу"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Экрандарды ауыстыру керек пе?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Жоғары ажыратымдылық үшін артқы камераны пайдаланыңыз."</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Жоғары ажыратымдылық үшін телефонды айналдырыңыз."</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Бүктемелі құрылғы ашылып жатыр."</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Бүктемелі құрылғы аударылып жатыр."</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Қалған батарея заряды: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Жұмыс профиліне ауысу"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Жабу"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Экран құлпының параметрлері"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi қолжетімсіз."</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камера бөгелген."</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камера мен микрофон бөгелген."</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Микрофон бөгелген."</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"\"Маңызды\" режимі қосулы."</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant қосулы."</string>
</resources>
diff --git a/packages/SystemUI/res/values-kk/tiles_states_strings.xml b/packages/SystemUI/res/values-kk/tiles_states_strings.xml
index c312b4957615..b8089e44a5ce 100644
--- a/packages/SystemUI/res/values-kk/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-kk/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Өшірулі."</item>
<item msgid="5966994759929723339">"Қосулы."</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Қолжетімсіз"</item>
+ <item msgid="2478289035899842865">"Өшірулі"</item>
+ <item msgid="5137565285664080143">"Қосулы"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index c5545a80b47b..ef20217fee53 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"ពណ៌​ការ​ជូន​ដំណឹង"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ការ​កំណត់​រហ័ស។"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ការកំណត់រហ័ស និងផ្ទាំងជូនដំណឹង។"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ចាក់​សោ​អេក្រង់។"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"អេក្រង់​ចាក់​សោ​លក្ខណៈ​ការងារ"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"បិទ"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"ពន្លឺ"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"ការបញ្ច្រាស​ពណ៌"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"ការ​កែតម្រូវ​ពណ៌"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"ទំហំ​ពុម្ព​អក្សរ"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"គ្រប់គ្រង​អ្នក​ប្រើប្រាស់"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"រួចរាល់"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"បិទ"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"ការជូនដំណឹង"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"ផ្លូវកាត់ក្ដារចុច"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"ប្ដូរប្លង់ក្ដារចុច"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"សម្អាតអក្សរ"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ផ្លូវកាត់"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"ផ្លូវកាត់ម៉ាស៊ីនស្វែងរក"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"រកផ្លូវកាត់មិនឃើញទេ"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"ប្រព័ន្ធ"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"បញ្ចូល"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"កម្មវិធីដែលបើក"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"កម្មវិធីបច្ចុប្បន្ន"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"ចូលប្រើប្រាស់ផ្ទាំងជូនដំណឹង"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"ថតរូបថតអេក្រង់ពេញ"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"ចូលប្រើប្រាស់បញ្ជីប្រព័ន្ធ/ផ្លូវកាត់​កម្មវិធី"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"ថយក្រោយ៖ ត្រឡប់ទៅស្ថានភាពពីមុនវិញ (ប៊ូតុងថយក្រោយ)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"ចូលប្រើប្រាស់អេក្រង់ដើម"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"ទិដ្ឋភាពរួមអំពីកម្មវិធីដែលបើក"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"រុករកកម្មវិធីថ្មីៗ (ទៅមុខ)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"រុករកកម្មវិធីថ្មីៗ (ថយក្រោយ)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"ចូលប្រើប្រាស់បញ្ជីកម្មវិធី និងម៉ាស៊ីនស្វែងរកទាំងអស់ (ឧ. ម៉ាស៊ីនស្វែងរក/កម្មវិធីចាប់ផ្ដើម)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"លាក់ រួចបង្ហាញរបារកិច្ចការ (ឡើងវិញ)"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"ចូលប្រើប្រាស់ការ​កំណត់​ប្រព័ន្ធ"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"ចូលប្រើប្រាស់ Google Assistant"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"ចាក់​សោ​អេក្រង់"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"ទាញកម្មវិធីកំណត់ចំណាំឡើងលើ ដើម្បីប្រើកំណត់ហេតុរហ័ស"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"ការដំណើរការបានច្រើននៃប្រព័ន្ធ"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"ចូលក្នុងមុខងារ​បំបែកអេក្រង់ដោយប្រើកម្មវិធីបច្ចុប្បន្ននៅចំហៀងខាងស្ដាំ"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"ចូលក្នុងមុខងារ​បំបែកអេក្រង់ដោយប្រើកម្មវិធីបច្ចុប្បន្ននៅចំហៀងខាងឆ្វេង"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"ប្ដូរពីមុខងារ​បំបែកអេក្រង់ទៅជាអេក្រង់ពេញ"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"អំឡុងពេលប្រើមុខងារ​បំបែកអេក្រង់៖ ជំនួសកម្មវិធីពីកម្មវិធីមួយទៅមួយទៀត"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"បញ្ចូល"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"ប្ដូរភាសាបញ្ចូល (ភាសាបន្ទាប់)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"ប្ដូរភាសាបញ្ចូល (ភាសាមុន)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"ចូលប្រើប្រាស់រូបអារម្មណ៍"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"ចូលប្រើប្រាស់ការវាយបញ្ចូលដោយប្រើសំឡេង"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"កម្មវិធី"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"ជំនួយ"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"កម្មវិធីរុករក"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"កម្មវិធីរុករកតាមអ៊ីនធឺណិត (Chrome តាមលំនាំដើម)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"ទំនាក់ទំនង"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"អ៊ីមែល"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"អ៊ីមែល (Gmail តាមលំនាំដើម)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"សារ SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"តន្ត្រី"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"ប្រតិទិន"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"ម៉ាស៊ីនគិតលេខ"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"ផែនទី"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"កុំ​រំខាន"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"ផ្លូវកាត់ប៊ូតុងកម្រិតសំឡេង"</string>
<string name="battery" msgid="769686279459897127">"ថ្ម"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ការថតវីដេអូអេក្រង់"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"គ្មាន​ចំណងជើង"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"ផ្អាក​ដំណើរការ"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"ទំហំពុម្ពអក្សរ"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"កំណត់ឱ្យតូចជាងមុន"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"កំណត់ឱ្យធំជាងមុន"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"វិនដូ​ការពង្រីក"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"វិនដូគ្រប់គ្រង​​ការពង្រីក"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"ពង្រីក"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"មានអ្វីមួយខុសប្រក្រតី។ សូមព្យាយាមម្ដងទៀត។"</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"កំពុងផ្ទុក"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"ថេប្លេត"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"កំពុងភ្ជាប់មេឌៀ​របស់អ្នក"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"កំពុង​ភ្ជាប់ <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"អសកម្ម ពិនិត្យមើល​កម្មវិធី"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"រកមិន​ឃើញទេ"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"មិនអាច​គ្រប់គ្រង​បានទេ"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"មិនអាចផ្សាយបានទេ"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"មិនអាច​រក្សាទុក​បានទេ។ សូមព្យាយាមម្ដងទៀត។"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"មិនអាច​រក្សាទុក​បានទេ។"</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ប្រើយ៉ាងហោចណាស់ 4 តួអក្សរ"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"ប្រើតិចជាង 16 តួអក្សរ"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"លេខ​កំណែបង្កើត"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"បានចម្លងលេខ​កំណែបង្កើតទៅឃ្លីបបត។"</string>
<string name="basic_status" msgid="2315371112182658176">"បើកការសន្ទនា"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• ឧបករណ៍យ៉ាងតិចមួយអាចប្រើបាន"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"ចុចឱ្យជាប់លើផ្លូវកាត់"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"បោះបង់"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"ត្រឡប់ឥឡូវនេះ"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"លាតទូរសព្ទ ដើម្បីសែលហ្វីកាន់តែប្រសើរ"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"ត្រឡប់ទៅផ្ទាំងអេក្រង់ខាងមុខ​ ដើម្បី​ថត​សែលហ្វីកាន់តែបានល្អឬ?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"ប្រើកាមេរ៉ាខាងក្រោយ ដើម្បីទទួលបានរូបថតកាន់តែធំជាមួយនឹងកម្រិតគុណភាពកាន់តែខ្ពស់។"</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ អេក្រង់នេះនឹងបិទ"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"ប្ដូរអេក្រង់ឥឡូវនេះ"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"លាតទូរសព្ទ"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"ប្ដូរអេក្រង់ឬ?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"សម្រាប់កម្រិតគុណភាពកាន់តែខ្ពស់ សូមប្រើប្រាស់កាមេរ៉ាខាងក្រោយ"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"សម្រាប់កម្រិតគុណភាពកាន់តែខ្ពស់ សូមត្រឡប់ទូរសព្ទ"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ឧបករណ៍អាច​បត់បានកំពុងត្រូវបានលា"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ឧបករណ៍អាច​បត់បានកំពុងត្រូវបានលា"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"ថ្មនៅសល់ <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"ប្ដូរ​ទៅ​កម្រង​ព័ត៌មាន​ការងារ"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"បិទ"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"ការកំណត់​អេក្រង់ចាក់សោ"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"មិនមាន Wi-Fi ទេ"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"បាន​ទប់ស្កាត់​កាមេរ៉ា"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"បានទប់ស្កាត់​កាមេរ៉ា និង​មីក្រូហ្វូន"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"បាន​ទប់ស្កាត់​មីក្រូហ្វូន"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"មុខងារ​អាទិភាពត្រូវបានបើក"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"ភាពប្រុងប្រៀប​របស់ Google Assistant ត្រូវបានបើក"</string>
</resources>
diff --git a/packages/SystemUI/res/values-km/tiles_states_strings.xml b/packages/SystemUI/res/values-km/tiles_states_strings.xml
index ec748cfac142..8c5c8d1ce088 100644
--- a/packages/SystemUI/res/values-km/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-km/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"បិទ"</item>
<item msgid="5966994759929723339">"បើក"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"មិនមានទេ"</item>
+ <item msgid="2478289035899842865">"បិទ"</item>
+ <item msgid="5137565285664080143">"បើក"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index d468e6e212c6..c830e847923a 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"ಅಧಿಸೂಚನೆಯ ಛಾಯೆ."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್‍ಗಳು."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್‍ಗಳು ಮತ್ತು ಅಧಿಸೂಚನೆಯ ಪರದೆ."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ಲಾಕ್‌ ಸ್ಕ್ರೀನ್."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"ಕೆಲಸದ ಲಾಕ್ ಪರದೆ"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"ಮುಚ್ಚು"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"ಪ್ರಕಾಶಮಾನ"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"ಕಲರ್ ಇನ್‍ವರ್ಶನ್"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"ಬಣ್ಣದ ತಿದ್ದುಪಡಿ"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"ಫಾಂಟ್ ಗಾತ್ರ"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"ಬಳಕೆದಾರರನ್ನು ನಿರ್ವಹಿಸಿ"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"ಮುಗಿದಿದೆ"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"ಮುಚ್ಚಿರಿ"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"ಅಧಿಸೂಚನೆಗಳು"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"ಕೀಬೋರ್ಡ್ ಶಾರ್ಟ್‌ಕಟ್‌ಗಳು"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"ಕೀಬೋರ್ಡ್‌ ಲೇಔಟ್‌ ಬದಲಾಯಿಸಿ"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"ಪಠ್ಯ ತೆರವುಗೊಳಿಸಿ"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ಶಾರ್ಟ್‌ಕಟ್‌ಗಳು"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"ಶಾರ್ಟ್‌ಕಟ್‌ಗಳನ್ನು ಹುಡುಕಿ"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"ಯಾವುದೇ ಶಾರ್ಟ್‌ಕಟ್‌ಗಳಿಲ್ಲ"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"ಸಿಸ್ಟಂ"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"ಇನ್‌ಪುಟ್"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"ಆ್ಯಪ್ಸ್ ತೆರೆ"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"ಪ್ರಸ್ತುತ ಆ್ಯಪ್"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"ಅಧಿಸೂಚನೆಯ ಪರದೆಯನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಿ"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"ಪೂರ್ಣ ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ತೆಗೆದುಕೊಳ್ಳಿ"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"ಸಿಸ್ಟಂ / ಅಪ್ಲಿಕೇಶನ್ ಶಾರ್ಟ್‌ಕಟ್‌ಗಳ ಆ್ಯಕ್ಸೆಸ್ ಪಟ್ಟಿ"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"ಹಿಂದೆ: ಹಿಂದಿನ ಸ್ಥಿತಿಗೆ ಹಿಂತಿರುಗಿ (ಹಿಂತಿರುಗುವ ಬಟನ್)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"ಹೋಮ್ ಸ್ಕ್ರೀನ್ ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಿ"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"ತೆರೆದ ಆ್ಯಪ್‌ಗಳ ಅವಲೋಕನ"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"ಇತ್ತೀಚೆಗೆ ಬಳಸಿದ ಆ್ಯಪ್‌ಗಳ ನಡುವೆ ಬದಲಿಸಿ (ಮುಂದೆ)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"ಇತ್ತೀಚೆಗೆ ಬಳಸಿದ ಆ್ಯಪ್‌ಗಳ ನಡುವೆ ಬದಲಿಸಿ (ಹಿಂದೆ)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"ಎಲ್ಲಾ ಆ್ಯಪ್‌ಗಳ ಮತ್ತು ಹುಡುಕಾಟದ ಆ್ಯಕ್ಸೆಸ್ ಪಟ್ಟಿ (ಅಂದರೆ ಹುಡುಕಾಟ/ಲಾಂಚರ್)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"ಟಾಸ್ಕ್‌ಬಾರ್ ಅನ್ನು ಮರೆಮಾಡಿ ಹಾಗೂ (ಪುನಃ)ತೋರಿಸಿ"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"ಸಿಸ್ಟಂ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಿ"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Access Google Assistant ಅನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಿ"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಮಾಡಿ"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"ತ್ವರಿತ ಮೆಮೊಗಾಗಿ ಟಿಪ್ಪಣಿಗಳ ಆ್ಯಪ್ ಅನ್ನು ಮೇಲಕ್ಕೆ ಎಳೆಯಿರಿ"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"ಸಿಸ್ಟಂ ಮಲ್ಟಿಟಾಸ್ಕಿಂಗ್"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"RHS ಗೆ ಪ್ರಸ್ತುತ ಆ್ಯಪ್ ಜೊತೆಗೆ ಪರದೆ ಬೇರ್ಪಡಿಸಿ ಮೋಡ್ ಅನ್ನು ನಮೂದಿಸಿ"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"LHS ಗೆ ಪ್ರಸ್ತುತ ಆ್ಯಪ್ ಜೊತೆಗೆ ಪರದೆ ಬೇರ್ಪಡಿಸಿ ಮೋಡ್ ಅನ್ನು ನಮೂದಿಸಿ"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"ಪರದೆ ಬೇರ್ಪಡಿಸಿ ಮೋಡ್‌ನಿಂದ ಪೂರ್ಣ ಸ್ಕ್ರೀನ್‌ಗೆ ಬದಲಿಸಿ"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"ಪರದೆ ಬೇರ್ಪಡಿಸುವ ಸಮಯದಲ್ಲಿ: ಒಂದು ಆ್ಯಪ್‌ನಿಂದ ಮತ್ತೊಂದು ಆ್ಯಪ್‌ಗೆ ಬದಲಾಯಿಸಿ"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"ಇನ್‌ಪುಟ್"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"ಇನ್‌ಪುಟ್ ಭಾಷೆಯನ್ನು ಬದಲಿಸಿ (ಮುಂದಿನ ಭಾಷೆ)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"ಇನ್‌ಪುಟ್ ಭಾಷೆಯನ್ನು ಬದಲಿಸಿ (ಹಿಂದಿನ ಭಾಷೆ)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"ಎಮೋಜಿಯನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಿ"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"ಧ್ವನಿ ಟೈಪಿಂಗ್ ಅನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಿ"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"ಅಪ್ಲಿಕೇಶನ್‌ಗಳು"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"ಸಹಾಯ ಮಾಡು"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"ಬ್ರೌಸರ್"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"ಬ್ರೌಸರ್ (ಡೀಫಾಲ್ಟ್ ಆಗಿ Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"ಸಂಪರ್ಕಗಳು"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"ಇಮೇಲ್"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"ಇಮೇಲ್ (ಡೀಫಾಲ್ಟ್ ಆಗಿ Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"ಎಸ್ಎಂಎಸ್"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"ಸಂಗೀತ"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"ಕ್ಯಾಲ್ಕ್ಯುಲೇಟರ್"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"ಅಡಚಣೆ ಮಾಡಬೇಡ"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"ವಾಲ್ಯೂಮ್ ಬಟನ್‌ಗಳ ಶಾರ್ಟ್‌ಕಟ್‌"</string>
<string name="battery" msgid="769686279459897127">"ಬ್ಯಾಟರಿ"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"ಯಾವುದೇ ಶೀರ್ಷಿಕೆಯಿಲ್ಲ"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"ಸ್ಟ್ಯಾಂಡ್‌ಬೈ"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"ಫಾಂಟ್ ಗಾತ್ರ"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"ಚಿಕ್ಕದಾಗಿಸಿ"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"ದೊಡ್ಡದಾಗಿಸಿ"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"ವರ್ಧನೆಯ ವಿಂಡೋ"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"ವರ್ಧನೆಯ ವಿಂಡೋ ನಿಯಂತ್ರಣಗಳು"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"ಝೂಮ್ ಇನ್ ಮಾಡಿ"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"ಪ್ರಸಾರ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"ಉಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"ಉಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ಕನಿಷ್ಠ 4 ಅಕ್ಷರಗಳನ್ನು ಬಳಸಿ"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16 ಕ್ಕಿಂತ ಕಡಿಮೆ ಅಕ್ಷರಗಳನ್ನು ಬಳಸಿ"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ಬಿಲ್ಡ್ ಸಂಖ್ಯೆ"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"ಬಿಲ್ಡ್ ಸಂಖ್ಯೆಯನ್ನು ಕ್ಲಿಪ್‌ಬೋರ್ಡ್‌ನಲ್ಲಿ ನಕಲಿಸಲಾಗಿದೆ."</string>
<string name="basic_status" msgid="2315371112182658176">"ಸಂಭಾಷಣೆಯನ್ನು ತೆರೆಯಿರಿ"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• ಕನಿಷ್ಠ ಒಂದು ಸಾಧನ ಲಭ್ಯವಿದೆ"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"ಸ್ಪರ್ಶಿಸಿ ಹೋಲ್ಡ್ ಮಾಡಿ ಶಾರ್ಟ್‌ಕಟ್"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"ರದ್ದುಗೊಳಿಸಿ"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"ಈಗ ಫ್ಲಿಪ್ ಮಾಡಿ"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"ಉತ್ತಮ ಸೆಲ್ಫೀಗಾಗಿ ಫೋನ್ ಅನ್ನು ಅನ್‌ಫೋಲ್ಡ್ ಮಾಡಿ"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"ಉತ್ತಮ ಸೆಲ್ಫೀಗಾಗಿ ಮುಂಭಾಗದ ಕ್ಯಾಮರಾಗೆ ಫ್ಲಿಪ್ ಮಾಡಬೇಕೆ?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"ಹೆಚ್ಚಿನ ರೆಸಲ್ಯೂಷನ್ ಹೊಂದಿರುವ ವಿಶಾಲವಾದ ಫೋಟೋಗಾಗಿ ಹಿಂಭಾಗದ ಕ್ಯಾಮರಾವನ್ನು ಬಳಸಿ."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ಈ ಸ್ಕ್ರೀನ್ ಆಫ್ ಆಗುತ್ತದೆ"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"ಈಗ ಸ್ಕ್ರೀನ್‌ಗಳನ್ನು ಬದಲಿಸಿ"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"ಫೋನ್ ಅನ್ನು ಅನ್‌ಫೋಲ್ಡ್ ಮಾಡಿ"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"ಸ್ಕ್ರೀನ್‌ಗಳನ್ನು ಬದಲಿಸಬೇಕೆ?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"ಅಧಿಕ ರೆಸಲ್ಯೂಷನ್‌ಗಾಗಿ, ಹಿಂಬದಿಯ ಕ್ಯಾಮರಾವನ್ನು ಬಳಸಿ"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"ಅಧಿಕ ರೆಸಲ್ಯೂಷನ್‌ಗಾಗಿ, ಫೋನ್ ಅನ್ನು ಫ್ಲಿಪ್ ಮಾಡಿ"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ಫೋಲ್ಡ್ ಮಾಡಬಹುದಾದ ಸಾಧನವನ್ನು ಅನ್‌ಫೋಲ್ಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ಫೋಲ್ಡ್ ಮಾಡಬಹುದಾದ ಸಾಧನವನ್ನು ಸುತ್ತಲೂ ತಿರುಗಿಸಲಾಗುತ್ತಿದೆ"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> ಬ್ಯಾಟರಿ ಉಳಿದಿದೆ"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್‌ಗೆ ಬದಲಿಸಿ"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"ಮುಚ್ಚಿರಿ"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"ಲಾಕ್ ಸ್ಕ್ರೀನ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"ವೈ-ಫೈ ಲಭ್ಯವಿಲ್ಲ"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"ಕ್ಯಾಮರಾವನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"ಕ್ಯಾಮರಾ ಮತ್ತು ಮೈಕ್ರೊಫೋನ್‌ ಅನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"ಮೈಕ್ರೋಫೋನ್ ಅನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"ಆದ್ಯತೆಯ ಮೋಡ್‌ ಆನ್‌ ಆಗಿದೆ"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant ನಿಮ್ಮ ಮಾತನ್ನು ಆಲಿಸುತ್ತಿದೆ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-kn/tiles_states_strings.xml b/packages/SystemUI/res/values-kn/tiles_states_strings.xml
index 864a607c8a39..16e82eacdd63 100644
--- a/packages/SystemUI/res/values-kn/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-kn/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"ಆಫ್ ಮಾಡಿ"</item>
<item msgid="5966994759929723339">"ಆನ್ ಮಾಡಿ"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"ಲಭ್ಯವಿಲ್ಲ"</item>
+ <item msgid="2478289035899842865">"ಆಫ್ ಆಗಿದೆ"</item>
+ <item msgid="5137565285664080143">"ಆನ್ ಆಗಿದೆ"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 864bfdab4f1f..b33168f9e0ea 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"알림 세부정보"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"빠른 설정"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"빠른 설정 및 알림 창입니다."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"화면을 잠급니다."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"업무용 잠금 화면"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"닫기"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"밝기"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"색상 반전"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"색상 보정"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"글꼴 크기"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"사용자 관리"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"완료"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"닫기"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"알림"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"단축키"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"키보드 레이아웃 전환"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"텍스트 삭제"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"단축키"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"단축키 검색"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"단축키 없음"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"시스템"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"입력"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"열린 앱"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"현재 앱"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"알림 창에 액세스"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"전체 스크린샷 촬영"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"시스템/앱 단축키 목록에 액세스"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"뒤로: 이전 상태로 되돌아가기(뒤로 버튼)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"홈 화면에 액세스"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"열린 앱 개요"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"최근 앱 간 순환(앞으로)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"최근 앱 간 순환(뒤로)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"모든 앱 및 검색 목록(예: 검색/런처)에 액세스"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"태스크 바 숨김 및 다시 표시"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"시스템 설정에 액세스"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Google 어시스턴트에 액세스"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"잠금 화면"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"빠른 메모를 위해 노트 앱 불러오기"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"시스템 멀티태스킹"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"현재 앱을 오른쪽으로 보내는 화면 분할 입력"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"현재 앱을 왼쪽으로 보내는 화면 분할 입력"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"화면 분할에서 전체 화면으로 전환"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"화면 분할 중: 다른 앱으로 바꾸기"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"입력"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"입력 언어 전환(다음 언어)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"입력 언어 전환(이전 언어)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"이모티콘에 액세스"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"음성 입력에 액세스"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"애플리케이션"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"지원"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"브라우저"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"브라우저(Chrome을 기본값으로 설정)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"연락처"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"이메일"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"이메일(Gmail을 기본값으로 설정)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"음악"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"캘린더"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"계산기"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"지도"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"방해 금지 모드"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"볼륨 버튼 단축키"</string>
<string name="battery" msgid="769686279459897127">"배터리"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"화면 녹화"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"제목 없음"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"대기"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"글꼴 크기"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"축소"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"확대"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"확대 창"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"확대 창 컨트롤"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"확대"</string>
@@ -815,7 +854,7 @@
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"접근성 기능을 열려면 탭하세요. 설정에서 이 버튼을 맞춤설정하거나 교체할 수 있습니다.\n\n"<annotation id="link">"설정 보기"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"버튼을 가장자리로 옮겨서 일시적으로 숨기세요."</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"실행취소"</string>
- <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"바로가기 <xliff:g id="FEATURE_NAME">%s</xliff:g>개 삭제됨"</string>
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> 바로가기 삭제됨"</string>
<string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{바로가기 #개 삭제됨}other{바로가기 #개 삭제됨}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"왼쪽 상단으로 이동"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"오른쪽 상단으로 이동"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"방송할 수 없음"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"저장할 수 없습니다. 다시 시도해 주세요."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"저장할 수 없습니다."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"4자 이상 입력하세요."</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16자 미만이어야 합니다."</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"빌드 번호"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"빌드 번호가 클립보드에 복사되었습니다."</string>
<string name="basic_status" msgid="2315371112182658176">"대화 열기"</string>
@@ -1043,12 +1080,12 @@
<string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"알 수 없음"</string>
<string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string>
<string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string>
- <string name="log_access_confirmation_title" msgid="4843557604739943395">"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g>에서 모든 기기 로그에 액세스하도록 허용하시겠습니까?"</string>
+ <string name="log_access_confirmation_title" msgid="4843557604739943395">"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g>에서 전체 기기 로그에 액세스하도록 허용하시겠습니까?"</string>
<string name="log_access_confirmation_allow" msgid="752147861593202968">"일회성 액세스 허용"</string>
<string name="log_access_confirmation_deny" msgid="2389461495803585795">"허용 안함"</string>
- <string name="log_access_confirmation_body" msgid="6883031912003112634">"기기 로그에 기기에서 발생한 상황이 기록됩니다. 앱은 문제를 찾고 해결하는 데 이 로그를 사용할 수 있습니다.\n\n일부 로그는 민감한 정보를 포함할 수 있으므로 신뢰할 수 있는 앱만 모든 기기 로그에 액세스하도록 허용하세요. \n\n앱에 전체 기기 로그에 대한 액세스 권한을 부여하지 않아도 앱이 자체 로그에는 액세스할 수 있습니다. 기기 제조업체에서 일부 로그 또는 기기 내 정보에 액세스할 수도 있습니다."</string>
+ <string name="log_access_confirmation_body" msgid="6883031912003112634">"기기 로그에는 기기에서 발생한 상황이 기록됩니다. 앱은 문제를 찾고 해결하는 데 이 로그를 사용할 수 있습니다.\n\n일부 로그는 민감한 정보를 포함할 수 있으므로 신뢰할 수 있는 앱만 전체 기기 로그에 액세스하도록 허용하세요. \n\n앱에 전체 기기 로그에 대한 액세스 권한을 부여하지 않아도 앱이 자체 로그에는 액세스할 수 있습니다. 기기 제조업체에서 일부 로그 또는 기기 내 정보에 액세스할 수도 있습니다."</string>
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"자세히 알아보기"</string>
- <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"<xliff:g id="URL">%s</xliff:g>에서 자세히 알아보기"</string>
+ <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"<xliff:g id="URL">%s</xliff:g>에서 자세히 알아보세요."</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> 열기"</string>
<string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• 앱이 설정되어 있습니다."</string>
<string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• 1개 이상의 카드가 월렛에 추가되어 있습니다."</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• 1대 이상의 기기를 사용할 수 있습니다."</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"바로가기를 길게 터치하세요."</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"취소"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"지금 뒤집기"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"휴대전화를 열어서 더 나은 셀카를 찍어보세요"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"전면 디스플레이가 보이도록 뒤집어서 더 나은 셀카를 찍어보세요"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"후면 카메라를 통해 넓은 각도로 해상도가 높은 사진을 찍어보세요."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ 이 화면이 꺼집니다."</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"지금 화면 전환"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"휴대전화 펼치기"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"화면을 전환할까요?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"해상도를 높이려면 후면 카메라를 사용하세요."</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"해상도를 높이려면 후면 카메라를 사용하세요."</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"폴더블 기기를 펼치는 모습"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"폴더블 기기를 뒤집는 모습"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"배터리 <xliff:g id="PERCENTAGE">%s</xliff:g> 남음"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"직장 프로필로 전환"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"닫기"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"잠금 화면 설정"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi를 사용할 수 없음"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"카메라 차단됨"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"카메라 및 마이크 차단됨"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"마이크 차단됨"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"우선순위 모드 설정됨"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"어시스턴트가 대기 중임"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ko/tiles_states_strings.xml b/packages/SystemUI/res/values-ko/tiles_states_strings.xml
index c52c17cedc32..7981d285946c 100644
--- a/packages/SystemUI/res/values-ko/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ko/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"꺼짐"</item>
<item msgid="5966994759929723339">"켜짐"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"사용 불가"</item>
+ <item msgid="2478289035899842865">"사용 안함"</item>
+ <item msgid="5137565285664080143">"사용"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 63e415132e0d..d50e19743e05 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Билдирмелер тактасы."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Тез тууралоолор."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Ыкчам параметрлер жана билдирмелер тактасы."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Кулпуланган экран."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Жумуштун кулпуланган экраны"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Жабуу"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Жарыктыгы"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Түстөрдү инверсиялоо"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Түстөрдү тууралоо"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Ариптин өлчөмү"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Колдонуучуларды тескөө"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Бүттү"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Жабуу"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Билдирмелер"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Ыкчам баскычтар"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Баскычтоп калыбын которуштуруу"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Текстти тазалоо"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Ыкчам баскычтар"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Ыкчам баскычтарды издөө"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Ыкчам баскычтар жок"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Тутум"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Киргизүү"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Ачык колдон-лор"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Учурдагы кол-мо"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Билдирмелер тактасына кирүү"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Толук скриншот тартуу"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Системанын / колдонмолордун ыкчам баскычтарынын тизмесине кирүү"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Артка: мурунку абалга кайтуу (артка баскычы)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Башкы экранга кирүү"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Ачылып турган колдонмолордун тизмесин көрүү"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Соңку колдонмолорду көрүү (кадимки тартипте)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Соңку колдонмолорду көрүү (тескери тартипте)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Бардык колдонмолордун тизмесин ачуу жана издөө (Издөө/Жүргүзгүч)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Тапшырмалар панелин жашыруу жана көрсөтүү"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Тутум параметрлерине кирүү"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Google Жардамчыны иштетүү"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Экранды кулпулоо"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Ыкчам кыска жазууну түзүү"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Тутумдун бир нече тапшырма аткаруусу"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Оң жакта жайгашкан учурдагы колдонмо менен экранды бөлүүнү иштетүү"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Сол жакта жайгашкан учурдагы колдонмо менен экранды бөлүүнү иштетүү"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Экранды бөлүү режиминен толук экранга которулуу"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Экранды бөлүү режиминде бир колдонмону экинчисине алмаштыруу"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Киргизүү"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Кийинки киргизүү тилине которулуу"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Мурунку киргизүү тилине которулуу"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Быйтыкчаларды көрүү"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Айтып терүүнү иштетүү"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Колдонмолор"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Көмөкчү"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Серепчи"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Серепчи (демейки шартта Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Байланыштар"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Электрондук почта"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Электрондук почта (демейки шартта Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Музыка"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Жылнаама"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Эсептегич"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Карталар"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Тынчымды алба"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Үндү көзөмөлдөөчү баскычтардын кыска жолдору"</string>
<string name="battery" msgid="769686279459897127">"Батарея"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"экранды жаздыруу"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Аталышы жок"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Көшүү режими"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Арип өлчөмү"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Кичирейтүү"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Чоңойтуу"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Чоңойтуу терезеси"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Чоңойтуу терезесин башкаруу каражаттары"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Жакындатуу"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Кабарлоого болбойт"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Сакталган жок. Кайталап көрүңүз."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Сакталган жок."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Кеминде 4 символдон турушу керек"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16 символдон ашпашы керек"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Курама номери"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Курама номери алмашуу буферине көчүрүлдү."</string>
<string name="basic_status" msgid="2315371112182658176">"Ачык сүйлөшүү"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Кеминде бир түзмөк жеткиликтүү"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Ыкчам баскычты басып туруңуз"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Токтотуу"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Азыр которуу"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Жакшы селфи тартуу үчүн негизги камерага которуңуз"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Жакшы селфи тартуу үчүн маңдайкы экранга которосузбу?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Кең жана жогорку дааналыктагы сүрөттү тартуу үчүн негизги камераны колдонуңуз."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Бул экран өчөт"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Экрандарды азыр которуштуруу"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Телефонду жайып алыңыз"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Экрандар которуштурулсунбу?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Жогорку дааналык үчүн арткы камераны колдонуңуз"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Жогорку дааналык үчүн телефондун арткы камерасын колдонуңуз"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Ачылып турган бүктөлмө түзмөк"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Оодарылып жаткан бүктөлмө түзмөк"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Батареянын кубаты: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Жумуш профилине которулуу"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Жабуу"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Кулпуланган экран параметрлери"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi жеткиликтүү эмес"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камера бөгөттөлдү"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камера менен микрофон бөгөттөлдү"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Микрофон бөгөттөлдү"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Маанилүү сүйлөшүүлөр режими күйүк"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Жардамчы иштетилди"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ky/tiles_states_strings.xml b/packages/SystemUI/res/values-ky/tiles_states_strings.xml
index f872926aa945..0f277f9de292 100644
--- a/packages/SystemUI/res/values-ky/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ky/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Өчүк"</item>
<item msgid="5966994759929723339">"Күйүк"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Жеткиликсиз"</item>
+ <item msgid="2478289035899842865">"Өчүк"</item>
+ <item msgid="5137565285664080143">"Күйүк"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index ac81dccecc0a..4f38e6058723 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -63,7 +63,7 @@
<dimen name="large_dialog_width">348dp</dimen>
<dimen name="qs_panel_padding_top">@dimen/qqs_layout_margin_top</dimen>
- <dimen name="qs_panel_padding_top_combined_headers">@dimen/qs_panel_padding_top</dimen>
- <dimen name="controls_padding_horizontal">16dp</dimen>
+ <dimen name="controls_header_horizontal_padding">12dp</dimen>
+ <dimen name="controls_content_margin_horizontal">16dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 43caaebb69c1..41610493d10e 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"ໜ້າຈໍແຈ້ງເຕືອນ."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ການຕັ້ງຄ່າດ່ວນ."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ການຕັ້ງຄ່າດ່ວນ ແລະ ເງົາການແຈ້ງເຕືອນ."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ລັອກ​ໜ້າ​ຈໍ."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"ໜ້າຈໍລັອກວຽກ"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"ປິດ"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"ຄວາມແຈ້ງ"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"ການປີ້ນສີ"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"ການແກ້ໄຂສີ"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"ຂະໜາດຟອນ"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"ຈັດການຜູ້ໃຊ້"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"ແລ້ວໆ"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"ປິດ"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"ການແຈ້ງເຕືອນ"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"ປຸ່ມລັດແປ້ນພິມ"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"ສະຫຼັບແປ້ນພິມ"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"ລຶບລ້າງຂໍ້ຄວາມ"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ທາງລັດ"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"ທາງລັດການຊອກຫາ"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"ບໍ່ພົບທາງລັດ"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"ລະບົບ"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"ການປ້ອນຂໍ້ມູນ"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"ແອັບທີ່ເປີດຢູ່"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"ແອັບປັດຈຸບັນ"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"ເຂົ້າເຖິງເງົາການແຈ້ງເຕືອນ"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"ຖ່າຍຮູບໜ້າຈໍແບບເຕັມ"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"ເຂົ້າເຖິງລາຍຊື່ຂອງລະບົບ / ທາງລັດແອັບ"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"ກັບຄືນ: ກັບຄືນຫາສະຖານະກ່ອນໜ້າ (ປຸ່ມກັບຄືນ)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"ເຂົ້າເຖິງໂຮມສະກຣີນ"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"ພາບຮວມຂອງແອັບທີ່ເປີດຢູ່"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"ໝູນວຽນຜ່ານແອັບຫຼ້າສຸດ (ໄປໜ້າ)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"ໝູນວຽນຜ່ານແອັບຫຼ້າສຸດ (ກັບຄືນ)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"ເຂົ້າເຖິງລາຍຊື່ຂອງແອັບທັງໝົດ ແລະ ການຊອກຫາ (ຕົວຢ່າງ: ຊອກຫາ/ລັນເຊີ)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"ເຊື່ອງ ແລະ ສະແດງ(ຄືນ) ແຖບໜ້າວຽກ"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"ເຂົ້າເຖິງການຕັ້ງຄ່າລະບົບ"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"ເຂົ້າເຖິງຜູ້ຊ່ວຍ Google"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"ໜ້າຈໍລັອກ"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"ດຶງແອັບ Notes ຂຶ້ນມາເພື່ອບັນທຶກຢ່າງວ່ອງໄວ"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"ການເຮັດຫຼາຍໜ້າວຽກພ້ອມກັນຂອງລະບົບ"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"ເຂົ້າສູ່ແບ່ງໜ້າຈໍດ້ວຍແອັບປັດຈຸບັນໄປຫາ RHS"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"ເຂົ້າສູ່ແບ່ງໜ້າຈໍດ້ວຍແອັບປັດຈຸບັນໄປຫາ LHS"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"ສະຫຼັບຈາກແບ່ງໜ້າຈໍໄປເປັນເຕັມຈໍ"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"ໃນລະຫວ່າງແບ່ງໜ້າຈໍ: ປ່ຽນແທນຈາກແອັບໜຶ່ງໄປຫາແອັບອື່ນ"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"ການປ້ອນຂໍ້ມູນ"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"ສະຫຼັບການປ້ອນພາສາ (ພາສາຕໍ່ໄປ)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"ສະຫຼັບການປ້ອນພາສາ (ພາສາກ່ອນໜ້າ)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"ເຂົ້າເຖິງອີໂມຈິ"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"ເຂົ້າເຖິງການພິມດ້ວຍສຽງ"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"ແອັບພລິເຄຊັນ"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"ຕົວຊ່ວຍ"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"ໂປຣແກຣມທ່ອງເວັບ"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"ໂປຣແກຣມທ່ອງເວັບ (Chrome ເປັນຄ່າເລີ່ມຕົ້ນ)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"ລາຍຊື່ຜູ້ຕິດຕໍ່"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"ອີເມວ"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"ອີເມວ (Gmail ເປັນຄ່າເລີ່ມຕົ້ນ)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"ຂໍ້ຄວາມສັ້ນ(SMS)"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"ດົນຕີ"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"ປະຕິທິນ"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"ຈັກຄິດໄລ່"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"ແຜນທີ່"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"ຫ້າມລົບກວນ"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"ທາງລັດປຸ່ມສຽງ"</string>
<string name="battery" msgid="769686279459897127">"ແບັດເຕີຣີ"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ການບັນທຶກໜ້າຈໍ"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"ບໍ່ມີຊື່"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"ສະແຕນບາຍ"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"ຂະໜາດຟອນ"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"ເຮັດໃຫ້ນ້ອຍລົງ"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"ເຮັດໃຫ້ໃຫຍ່ຂຶ້ນ"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"ໜ້າຈໍການຂະຫຍາຍ"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"ການຄວບຄຸມໜ້າຈໍການຂະຫຍາຍ"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"ຊູມເຂົ້າ"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"ບໍ່ສາມາດອອກອາກາດໄດ້"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"ບໍ່ສາມາດບັນທຶກໄດ້. ກະລຸນາລອງໃໝ່."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"ບໍ່ສາມາດບັນທຶກໄດ້."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ໃຊ້ຢ່າງໜ້ອຍ 4 ຕົວອັກສອນ"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"ໃຊ້ໜ້ອຍກວ່າ 16 ຕົວອັກສອນ"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ໝາຍເລກສ້າງ"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"ສຳເນົາໝາຍເລກສ້າງໄປໃສ່ຄລິບບອດແລ້ວ."</string>
<string name="basic_status" msgid="2315371112182658176">"ເປີດການສົນທະນາ"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• ມີຢ່າງໜ້ອຍ 1 ອຸປະກອນພ້ອມໃຫ້ນຳໃຊ້"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"ແຕະທາງລັດຄ້າງໄວ້"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"ຍົກເລີກ"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"ປີ້ນດຽວນີ້"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"ກາງໂທລະສັບອອກເພື່ອການຖ່າຍເຊວຟີທີ່ດີຂຶ້ນ"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"ປີ້ນເປັນຈໍສະແດງຜົນດ້ານໜ້າເພື່ອການຖ່າຍເຊວຟີທີ່ດີຂຶ້ນບໍ?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"ໃຊ້ກ້ອງຫຼັງເພື່ອການຖ່າຍຮູບທີ່ກວ້າງຂຶ້ນດ້ວຍຄວາມລະອຽດສູງຂຶ້ນ."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ໜ້າຈໍນີ້ຈະປິດ"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"ສະຫຼັບໜ້າຈໍດຽວນີ້"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"ພືໂທລະສັບອອກ"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"ສະຫຼັບໜ້າຈໍບໍ?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"ເພື່ອຄວາມລະອຽດທີ່ສູງຂຶ້ນ, ໃຫ້ໃຊ້ກ້ອງຖ່າຍຮູບຫຼັງ"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"ເພື່ອຄວາມລະອຽດທີ່ສູງຂຶ້ນ, ໃຫ້ປີ້ນໂທລະສັບ"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ອຸປະກອນທີ່ພັບໄດ້ກຳລັງກາງອອກ"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ອຸປະກອນທີ່ພັກໄດ້ກຳລັງປີ້ນໄປມາ"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"ແບັດເຕີຣີເຫຼືອ <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"ສະຫຼັບໄປໃຊ້ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກ"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"ປິດ"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"ການຕັ້ງຄ່າໜ້າຈໍລັອກ"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi ບໍ່ພ້ອມໃຫ້ນຳໃຊ້"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"ກ້ອງຖ່າຍຮູບຖືກບລັອກຢູ່"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"ກ້ອງຖ່າຍຮູບ ແລະ ໄມໂຄຣໂຟນຖືກບລັອກຢູ່"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"ໄມໂຄຣໂຟນຖືກບລັອກຢູ່"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"ໂໝດຄວາມສຳຄັນເປີດຢູ່"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"ການເອີ້ນໃຊ້ຜູ້ຊ່ວຍເປີດຢູ່"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lo/tiles_states_strings.xml b/packages/SystemUI/res/values-lo/tiles_states_strings.xml
index 6ae37e472b0c..d54cf4d24181 100644
--- a/packages/SystemUI/res/values-lo/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-lo/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"ປິດ"</item>
<item msgid="5966994759929723339">"ເປີດ"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"ບໍ່ສາມາດເບິ່ງໄດ້"</item>
+ <item msgid="2478289035899842865">"ປິດ"</item>
+ <item msgid="5137565285664080143">"ເປີດ"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index a24eb500bcf4..b37478943665 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Pranešimų gaubtas."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Spartieji nustatymai."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Spartieji nustatymai ir pranešimų skydelis."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Užrakinimo ekranas."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Darbo profilio užrakinimo ekranas"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Uždaryti"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Šviesumas"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Spalvų inversija"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Spalvų taisymas"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Šrifto dydis"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Tvarkyti naudotojus"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Atlikta"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Uždaryti"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Pranešimai"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Spartieji klavišai"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Perjungti klaviat. išdėstymą"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Išvalyti tekstą"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Spartieji klavišai"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Ieškoti sparčiųjų klavišų"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Sparčiųjų klavišų nerasta"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistema"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Įvestis"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Atidar. progr."</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Esama programa"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Pasiekti pranešimų skydelį"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Padaryti viso ekrano kopiją"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Pasiekti sistemos sąrašą / programų šaukinius"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Atgal: grįžti prie ankstesnės būsenos (mygtukas „Atgal“)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Pasiekti pagrindinį ekraną"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Peržiūrėti atidarytas programas"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Pereiti prie naujausių programų (į priekį)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Pereiti prie naujausių programų (atgal)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Visų progr. ir paiešk. prieig. sąrašas (t. y. Paieška, paleid. priem.)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Slėpti ir (iš naujo) parodyti užduočių juostą"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Pasiekti sistemos nustatymus"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Pasiekti „Google“ padėjėją"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Užrakinti ekraną"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Gauti pastabų programą trumpiems užrašams"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Kelių užduočių atlikimas sistemoje"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Eiti į išskaidyto ekrano režimą su dabartine programa dešinėje"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Eiti į išskaidyto ekrano režimą su dabartine programa kairėje"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Perjungti iš išskaidyto ekrano režimo į viso ekrano režimą"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Išskaidyto ekrano režimu: pakeisti iš vienos programos į kitą"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Įvestis"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Perjungti įvesties kalbą (kita kalba)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Perjungti įvesties kalbą (ankstesnė kalba)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Pasiekti jaustuką"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Pasiekti rašymą balsu"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Programos"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Pagalbinė programa"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Naršyklė"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Naršyti („Chrome“ kaip numatytoji naršyklė)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Kontaktai"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"El. paštas"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"El. paštas („Gmail“ kaip numatytasis el. paštas)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Muzika"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalendorius"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Skaičiuotuvas"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Žemėlapiai"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Netrukdymo režimas"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Garsumo mygtukų spartusis klavišas"</string>
<string name="battery" msgid="769686279459897127">"Akumuliatorius"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ekrano įrašymas"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Nėra pavadinimo"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Budėjimo laikas"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Šrifto dydis"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Padaryti mažesnius"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Padaryti didesnius"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Didinimo langas"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Didinimo lango valdikliai"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Artinti"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Nepavyko transliuoti"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Nepavyko išsaugoti. Bandykite dar kartą."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Nepavyko išsaugoti."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Naudokite bent 4 simbolius"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Naudokite daugiausia 16 simbolių"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Versijos numeris"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Versijos numeris nukopijuotas į iškarpinę."</string>
<string name="basic_status" msgid="2315371112182658176">"Atidaryti pokalbį"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Pasiekiamas bent vienas įrenginys"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Paliesk. ir palaik. spart. klav."</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Atšaukti"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Apversti dabar"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Užfiksuokite geresnę asmenukę atlenkę telefoną"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Užfiksuoti geresnę asmenukę įjungus priekinį rodinį?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Naudokite galinį fotoaparatą, kad nuotrauka būtų platesnė ir didesnės skyros."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Šis ekranas išsijungs"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Perjungti ekranus dabar"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Atlenkite telefoną"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Perjungti ekranus?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Didesnei raiškai naudokite galinį fotoaparatą"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Kad raiška būtų geresnė, apverskite telefoną"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Lankstomasis įrenginys išlankstomas"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Lankstomasis įrenginys apverčiamas"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Liko akumuliatoriaus įkrovos: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Perjungti į darbo profilį"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Uždaryti"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Užrakinimo ekrano nustatymai"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"„Wi-Fi“ ryšys nepasiekiamas"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Fotoaparatas užblokuotas"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Fotoaparatas ir mikrofonas užblokuoti"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofonas užblokuotas"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioriteto režimas įjungtas"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Padėjėjas klauso"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lt/tiles_states_strings.xml b/packages/SystemUI/res/values-lt/tiles_states_strings.xml
index 03d98c42ff19..e66f590364dd 100644
--- a/packages/SystemUI/res/values-lt/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-lt/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Išjungta"</item>
<item msgid="5966994759929723339">"Įjungta"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Nepasiekiama"</item>
+ <item msgid="2478289035899842865">"Išjungta"</item>
+ <item msgid="5137565285664080143">"Įjungta"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index f1486c4b477f..f82bcd64b22e 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -188,8 +188,8 @@
<string name="accessibility_battery_level" msgid="5143715405241138822">"Akumulators: <xliff:g id="NUMBER">%d</xliff:g> procenti"</string>
<string name="accessibility_battery_level_with_estimate" msgid="6548654589315074529">"Akumulatora uzlādes līmenis: <xliff:g id="PERCENTAGE">%1$d</xliff:g>%%, <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Notiek akumulatora uzlāde, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%."</string>
- <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"Akumulatora uzlādes līmenis: <xliff:g id="PERCENTAGE">%d</xliff:g>%%, uzlāde ir apturēta, lai aizsargātu akumulatoru."</string>
- <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"Akumulatora uzlādes līmenis: <xliff:g id="PERCENTAGE">%1$d</xliff:g>%%, <xliff:g id="TIME">%2$s</xliff:g>, uzlāde ir apturēta, lai aizsargātu akumulatoru."</string>
+ <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"Akumulatora uzlādes līmenis: <xliff:g id="PERCENTAGE">%d</xliff:g>, uzlāde ir apturēta, lai aizsargātu akumulatoru."</string>
+ <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"Akumulatora uzlādes līmenis: <xliff:g id="PERCENTAGE">%1$d</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>, uzlāde ir apturēta, lai aizsargātu akumulatoru."</string>
<string name="accessibility_overflow_action" msgid="8555835828182509104">"Skatīt visus paziņojumus"</string>
<string name="accessibility_tty_enabled" msgid="1123180388823381118">"Teletaips ir iespējots."</string>
<string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Zvana signāls — vibrācija."</string>
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Paziņojumu panelis"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Ātrie iestatījumi"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Ātrie iestatījumi un paziņojumu panelis."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Bloķēšanas ekrāns."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Darba profila bloķēšanas ekrāns"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Aizvērt"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Spilgtums"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Krāsu inversija"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Krāsu korekcija"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Fonta lielums"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Pārvaldīt lietotājus"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Gatavs"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Aizvērt"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Paziņojumi"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Īsinājumtaustiņi"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Mainīt tastatūras izkārtojumu"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Notīrīt tekstu"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Īsinājumtaustiņi"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Meklēt īsinājumtaustiņus"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nav atrasti"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistēma"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Ievade"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Atvērtās"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Pašreizējā"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Piekļūt paziņojumu panelim"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Izveidot visa ekrāna ekrānuzņēmumu"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Piekļūt sistēmas/lietotnes saīšņu sarakstam"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Atpakaļ: atgriezties iepriekšējā stāvoklī (poga Atpakaļ)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Piekļūt sākuma ekrānam"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Atvērto lietotņu kopsavilkums"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Secīgi pārlūkot nesen izmantotās lietotnes (pāriet uz nākamo)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Secīgi pārlūkot nesen izmantotās lietotnes (pāriet uz iepriekšējo)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Visu lietotņu saraksts un meklēšana (meklēšana / Palaišanas programma)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Paslēpt vai (atkārtoti) parādīt uzdevumu joslu"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Piekļūt sistēmas iestatījumiem"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Piekļūt Google asistentam"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Bloķēt ekrānu"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Atvērt piezīmju lietotni, lai izveidotu piezīmi"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Sistēmas vairākuzdevumu režīms"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Pāriet ekrāna sadalīšanas režīmā ar pašreizējo lietotni pa labi"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Pāriet ekrāna sadalīšanas režīmā ar pašreizējo lietotni pa kreisi"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Pārslēgties no ekrāna sadalīšanas režīma uz pilnekrāna režīmu"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Ekrāna sadalīšanas režīmā: pārvietot lietotni no viena uz otru"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Ievade"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Pārslēgt ievades valodu (uz nākamo valodu)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Pārslēgt ievades valodu (uz iepriekšējo valodu)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Piekļūt emocijzīmēm"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Piekļūt rakstīšanai ar balsi"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Lietojumprogrammas"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Palīgs"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Pārlūkprogramma"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Pārlūks (pēc noklusējuma Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Kontaktpersonas"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"E-pasts"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"E-pasts (pēc noklusējuma Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"Īsziņas"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Mūzika"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalendārs"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kalkulators"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Kartes"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Režīms “Netraucēt”"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Skaļuma pogu saīsne"</string>
<string name="battery" msgid="769686279459897127">"Akumulators"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ekrāna ierakstīšana"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Nav nosaukuma"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Gaidstāve"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Fonta lielums"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Samazināt"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Palielināt"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Palielināšanas logs"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Palielināšanas loga vadīklas"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Tuvināt"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"Radās kļūda. Mēģiniet vēlreiz."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Notiek ielāde"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"planšetdators"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"Notiek multivides satura apraide"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"Notiek lietotnes <xliff:g id="APP_LABEL">%1$s</xliff:g> apraide"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktīva, pārbaudiet lietotni"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Netika atrasta"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Vadīkla nav pieejama"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Nevar apraidīt"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Nevar saglabāt. Mēģiniet vēlreiz."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Nevar saglabāt."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Izmantojiet vismaz 4 rakstzīmes"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Izmantojiet mazāk nekā 16 rakstzīmes"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Versijas numurs"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Versijas numurs ir kopēts starpliktuvē."</string>
<string name="basic_status" msgid="2315371112182658176">"Atvērt sarunu"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Ir pieejama vismaz viena ierīce."</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Pieskarieties saīsnei un turiet."</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Atcelt"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Apvērst tūlīt"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Labākas pašbildes uzņemšana, atlokot tālruni"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Vai apvērst uz priekšējo kameru labākai pašbildei?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Lai uzņemtu platāku fotoattēlu ar augstāku izšķirtspēju, izmantojiet aizmugurējo kameru."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Šis ekrāns tiks izslēgts."</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Mainīt ekrānus tagad"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Tālruņa atlocīšana"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Vai mainīt ekrānus?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Lai izmantotu augstāku izšķirtspēju, lietojiet aizmugurējo kameru"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Lai izmantotu augstāku izšķirtspēju, apvērsiet tālruni"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Salokāma ierīce tiek atlocīta"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Salokāma ierīce tiek apgriezta"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Atlikušais uzlādes līmenis: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Pārslēgties uz darba profilu"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Aizvērt"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Bloķēšanas ekrāna iestatījumi"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi nav pieejams"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera ir bloķēta"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kameras un mikrofona lietošana ir bloķēta"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofons ir bloķēts"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioritātes režīms ir ieslēgts"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Asistents klausās"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lv/tiles_states_strings.xml b/packages/SystemUI/res/values-lv/tiles_states_strings.xml
index 6e9264d2a347..d32efec81a99 100644
--- a/packages/SystemUI/res/values-lv/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-lv/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Izslēgts"</item>
<item msgid="5966994759929723339">"Ieslēgts"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Nav pieejams"</item>
+ <item msgid="2478289035899842865">"Izslēgts"</item>
+ <item msgid="5137565285664080143">"Ieslēgts"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 9bec87f19d07..64631c867c74 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Панел за известување"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Брзи поставки."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"„Брзи поставки“ и „Панел со известувања“."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Заклучи екран."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Работен заклучен екран"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Затвори"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Осветленост"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Инверзија на боите"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Корекција на боите"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Големина на фонтот"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Управувајте со корисниците"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Готово"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Затвори"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Известувања"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Кратенки на тастатурата"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Промени јазик на тастатура"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Избришете го текстот"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Кратенки"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Пребарувајте кратенки"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Не се пронајдени кратенки"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Системски"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Внесување"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Отворени аплик."</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Тековна аплик."</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Пристапете до панелот со известувања"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Снимете целосна слика од екранот"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Пристапете до список на системот / кратенки за апликациите"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Назад: вратете се во претходната состојба (копче за назад)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Пристапете до почетниот екран"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Преглед на отворените апликации"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Прелистувајте ги неодамнешните апликации (напред)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Прелистувајте ги неодамнешните апликации (назад)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Отв. список со сите аплик. и пребарувајте (т.е. Пребарување/Стартер)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Сокриј и (повторно) прикажи ја лентата со задачи"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Пристапете до поставките на системот"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Пристапете до „Помошник на Google“"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Заклучен екран"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Отворете ја апликацијата „Белешки“ за брз меморандум"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Системски мултитаскинг"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Активирајте поделен екран со тековната апликација десно"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Активирајте поделен екран со тековната апликација лево"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Префрлете се од поделен екран во цел екран"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"За време на поделен. екран: префрл. ги аплик. од една на друга страна"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Внесување"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Променете го влезниот јазик (следен јазик)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Променете го влезниот јазик (претходен јазик)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Пристапете до емоџијата"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Пристапете до гласовното пишување"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Апликации"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Помош"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Прелистувач"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Прелистувач (Chrome е стандардна опција)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Контакти"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Е-пошта"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Е-пошта (Gmail е стандардна опција)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Музика"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Календар"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Калкулатор"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Карти"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Не вознемирувај"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Кратенка за копчињата за јачина на звук"</string>
<string name="battery" msgid="769686279459897127">"Батерија"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"снимање на екранот"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Без наслов"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Подготвеност"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Големина на фонтот"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Намали"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Зголеми"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Прозорец за зголемување"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Контроли на прозорец за зголемување"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Зумирај"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"Нешто не е во ред. Обидете се повторно."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Се вчитува"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"таблет"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"Емитување на вашите аудиовизуелни содржини"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"Се емитува <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Неактивна, провери апликација"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Не е најдено"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Контролата не е достапна"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Не може да се емитува"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Не може да се зачува. Обидете се повторно."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Не може да се зачува."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Употребете најмалку 4 знаци"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Употребете помалку од 16 знаци"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Број на верзија"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Бројот на верзијата е копиран во привремената меморија."</string>
<string name="basic_status" msgid="2315371112182658176">"Започни разговор"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• достапен е најмалку еден уред"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Допрете и задржете ја кратенката"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Откажи"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Префрли сега"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Отворете го телефонот за подобро селфи"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Да се префрли на предниот екран за подобро селфи?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Користете ја задната камера за поширока фотографија со повисока резолуција."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Екранов ќе се исклучи"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Променете го екранот сега"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Отворете го телефонот"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Да се промени екранот?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Користете ја задната камера за да добиете повисока резолуција"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Отворете го телефонот за да добиете повисока резолуција"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Преклопувачки уред се отклопува"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Преклопувачки уред се врти"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Преостаната батерија: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Префрли се на работен профил"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Затвори"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Поставки за заклучен екран"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi не е достапно"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камерата е блокирана"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камерата и микрофонот се блокирани"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Микрофонот е блокиран"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Приоритетниот режим е вклучен"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Вниманието на „Помошникот“ е вклучено"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mk/tiles_states_strings.xml b/packages/SystemUI/res/values-mk/tiles_states_strings.xml
index 96c8a49ae0b6..8c4459a9ae6e 100644
--- a/packages/SystemUI/res/values-mk/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-mk/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Исклучено"</item>
<item msgid="5966994759929723339">"Вклучено"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Недостапно"</item>
+ <item msgid="2478289035899842865">"Исклучено"</item>
+ <item msgid="5137565285664080143">"Вклучено"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index e388d6a9b50e..75633a284c9c 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"അറിയിപ്പ് ഷെയ്‌ഡ്."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ദ്രുത ക്രമീകരണങ്ങൾ."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"അറിയിപ്പ് ഷെയ്‌ഡിനുള്ള ദ്രുത ക്രമീകരണം."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ലോക്ക് സ്‌ക്രീൻ."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"ഔദ്യോഗിക ലോക്ക് സ്ക്രീൻ"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"അവസാനിപ്പിക്കുക"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"തെളിച്ചം"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"നിറം വിപരീതമാക്കൽ"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"നിറം ശരിയാക്കൽ"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"ഫോണ്ട് വലുപ്പം"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"ഉപയോക്താക്കളെ മാനേജ് ചെയ്യുക"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"പൂർത്തിയാക്കി"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"അടയ്ക്കുക"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"അറിയിപ്പുകൾ"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"കീബോർഡ് കുറുക്കുവഴികൾ"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"കീബോർഡ് ലേഔട്ട് മാറുക"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"ടെക്‌സ്റ്റ് മായ്‌ക്കുക"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"കുറുക്കുവഴികൾ"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Search കുറുക്കുവഴികൾ"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"കുറുക്കുവഴി കണ്ടെത്തിയില്ല"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"സിസ്റ്റം"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"ഇൻപുട്ട്"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"തുറന്ന ആപ്പുകൾ"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"നിലവിലെ ആപ്പ്"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"അറിയിപ്പ് ഷെയ്‌ഡ് ആക്സസ് ചെയ്യുക"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"പൂർണ്ണ സ്ക്രീൻഷോട്ട് എടുക്കുക"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"സിസ്റ്റം / ആപ്പ് കുറുക്കുവഴികളുടെ ലിസ്റ്റ് ആക്‌സസ് ചെയ്യുക"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"മടങ്ങുക: മുമ്പത്തെ നിലയിലേക്ക് പോകുക (മടങ്ങുക ബട്ടൺ)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"ഹോം സ്‌ക്രീൻ ആക്സസ് ചെയ്യുക"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"തുറന്ന ആപ്പുകളുടെ അവലോകനം"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"സമീപകാലത്തെ ആപ്പുകൾ തമ്മിൽ മാറുക (മുന്നിലേക്ക്)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"സമീപകാലത്തെ ആപ്പുകൾ തമ്മിൽ മാറുക (പിന്നിലേക്ക്)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"ആപ്പ്, തിരയൽ ലിസ്റ്റുകളെല്ലാം ആക്സസ് ചെയ്യൂ (Search/Launcher എന്നിവ)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"ടാസ്‌ക്ബാർ മറയ്ക്കുക, (വീണ്ടും) കാണിക്കുക"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"സിസ്റ്റം ക്രമീകരണം ആക്സസ് ചെയ്യുക"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Google Assistant ആക്സസ് ചെയ്യുക"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"സ്‌ക്രീൻ ലോക്ക് ചെയ്യുക"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"അതിവേഗ മെമോ തയ്യാറാക്കുന്നതിന് നോട്ട്‌സ് ആപ്പ് തുറക്കുക"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"സിസ്റ്റം മൾട്ടിടാസ്‌കിംഗ്"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"നിലവിലെ ആപ്പ് വലതുവശത്ത് വരുന്ന രീതിയിൽ സ്ക്രീൻ വിഭജന മോഡിൽ കടക്കുക"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"നിലവിലെ ആപ്പ് ഇടതുവശത്ത് വരുന്ന രീതിയിൽ സ്ക്രീൻ വിഭജന മോഡിൽ കടക്കുക"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"സ്‌ക്രീൻ വിഭജന മോഡിൽ നിന്ന് പൂർണ്ണ സ്ക്രീനിലേക്ക് മാറുക"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"സ്‌ക്രീൻ വിഭജന മോഡിൽ: ഒരു ആപ്പിൽ നിന്ന് മറ്റൊന്നിലേക്ക് മാറുക"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"ഇൻപുട്ട്"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"ഇൻ‌പുട്ട് ഭാഷ മാറുക (അടുത്ത ഭാഷ)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"ഇൻ‌പുട്ട് ഭാഷ മാറുക (മുമ്പത്തെ ഭാഷ)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"ഇമോജി ആക്സസ് ചെയ്യുക"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"വോയ്‌സ് ടൈപ്പിംഗ് ആക്സസ് ചെയ്യുക"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"അപ്ലിക്കേഷനുകൾ"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"അസിസ്റ്റ്"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"ബ്രൗസർ"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"ബ്രൗസർ (ഡിഫോൾട്ടായി Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"കോൺടാക്റ്റുകൾ"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"ഇമെയിൽ"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"ഇമെയിൽ (ഡിഫോൾട്ടായി Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS:"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"സംഗീതം"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"കാൽക്കുലേറ്റർ"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"ശല്യപ്പെടുത്തരുത്"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"വോളിയം ബട്ടൺ കുറുക്കുവഴി"</string>
<string name="battery" msgid="769686279459897127">"ബാറ്ററി"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"സ്ക്രീൻ റെക്കോർഡിംഗ്"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"പേരില്ല"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"സ്‌റ്റാൻഡ്‌ബൈ"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"ഫോണ്ട് വലുപ്പം"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"ചെറുതാക്കുക"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"വലുതാക്കുക"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"മാഗ്നിഫിക്കേഷൻ വിൻഡോ"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"മാഗ്നിഫിക്കേഷൻ വിൻഡോ നിയന്ത്രണങ്ങൾ"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"സൂം ഇൻ ചെയ്യുക"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"ബ്രോഡ്‌കാസ്‌റ്റ് ചെയ്യാനാകുന്നില്ല"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"സംരക്ഷിക്കാൻ കഴിയില്ല. വീണ്ടും ശ്രമിക്കുക."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"സംരക്ഷിക്കാൻ കഴിയില്ല."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"കുറഞ്ഞത് 4 പ്രതീകങ്ങളെങ്കിലും ഉപയോഗിക്കുക"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16-ൽ കുറവ് പ്രതീകങ്ങൾ ഉപയോഗിക്കുക"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ബിൽഡ് നമ്പർ"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"ക്ലിപ്പ്ബോർഡിലേക്ക് ബിൽഡ് നമ്പർ പകർത്തി."</string>
<string name="basic_status" msgid="2315371112182658176">"സംഭാഷണം തുറക്കുക"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• ഒരു ഉപകരണമെങ്കിലും ലഭ്യമാണ്"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"സ്പർശിച്ച് പിടിക്കുക കുറുക്കുവഴി"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"റദ്ദാക്കുക"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"ഇപ്പോൾ ഫ്ലിപ്പ് ചെയ്യൂ"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"കൂടുതൽ മികച്ച സെൽഫി ലഭിക്കാൻ ഫോൺ അൺഫോൾഡ് ചെയ്യൂ"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"മികച്ച സെൽഫിക്ക് ഫ്രണ്ട് ഡിസ്പ്ലേയിലേക്ക് മാറണോ?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"ഉയർന്ന റെസല്യൂഷൻ ഉള്ള, വീതി കൂടിയ ഫോട്ടോയ്ക്ക്, പിൻഭാഗത്തെ ക്യാമറ ഉപയോഗിക്കുക."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ഈ സ്ക്രീൻ ഓഫാകും"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"ഇപ്പോൾ സ്ക്രീനുകൾ മാറുക"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"ഫോൺ അൺഫോൾഡ് ചെയ്യൽ"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"സ്ക്രീനുകൾ മാറണോ?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"ഉയർന്ന റെസല്യൂഷന്, പിൻ ക്യാമറ ഉപയോഗിക്കുക"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"ഉയർന്ന റെസല്യൂഷന്, ഫോൺ ഫ്ലിപ്പ് ചെയ്യുക"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ഫോൾഡ് ചെയ്യാവുന്ന ഉപകരണം അൺഫോൾഡ് ആകുന്നു"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ഫോൾഡ് ചെയ്യാവുന്ന ഉപകരണം, കറങ്ങുന്ന വിധത്തിൽ ഫ്ലിപ്പ് ആകുന്നു"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> ബാറ്ററി ചാർജ് ശേഷിക്കുന്നു"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"ഔദ്യോഗിക പ്രൊഫൈലിലേക്ക് മാറുക"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"അടയ്ക്കുക"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"ലോക്ക് സ്ക്രീൻ ക്രമീകരണം"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"വൈഫൈ ലഭ്യമല്ല"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"ക്യാമറ ബ്ലോക്ക് ചെയ്തിരിക്കുന്നു"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"ക്യാമറയും മൈക്രോഫോണും ബ്ലോക്ക് ചെയ്തിരിക്കുന്നു"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"മൈക്രോഫോൺ ബ്ലോക്ക് ചെയ്തിരിക്കുന്നു"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"മുൻഗണനാ മോഡ് ഓണാണ്"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant സജീവമാണ്"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ml/tiles_states_strings.xml b/packages/SystemUI/res/values-ml/tiles_states_strings.xml
index 7a078737aa96..62bac5cd1212 100644
--- a/packages/SystemUI/res/values-ml/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ml/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"ഓഫാണ്"</item>
<item msgid="5966994759929723339">"ഓണാണ്"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"ലഭ്യമല്ല"</item>
+ <item msgid="2478289035899842865">"ഓഫാണ്"</item>
+ <item msgid="5137565285664080143">"ഓണാണ്"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index e534342cc98d..c1be9f782916 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Мэдэгдлийн хураангуй самбар"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Шуурхай тохиргоо."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Шуурхай тохиргоо болон мэдэгдлийн хураангуй самбар."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Дэлгэц түгжих."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ажлын түгжигдсэн дэлгэц"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Хаах"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Тодрол"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Өнгө хувиргалт"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Өнгө тохируулга"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Фонтын хэмжээ"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Хэрэглэгчдийг удирдах"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Дууссан"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Хаах"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Мэдэгдэл"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Гарын товчлол"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Гарын бүдүүвч рүү сэлгэх"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Текстийг арилгах"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Товчлолууд"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Товчлолууд хайх"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Ямар ч товчлол олдсонгүй"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Систем"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Оролт"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Нээлттэй аппууд"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Одоогийн апп"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Мэдэгдлийн хураангуй самбарт хандах"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Бүтэн дэлгэцийн агшин авах"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Системийн жагсаалт / аппын товчлолд хандах"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Буцах: өмнөх төлөв рүү буцах (буцах товчлуур)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Үндсэн нүүрэнд хандах"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Нээлттэй аппуудын тойм"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Саяхны аппуудаар шилжих (урагшлах)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Саяхны аппуудаар шилжих (буцах)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Бүх апп болон хайлтын жагсаалтад хандах (ж.нь Хайлт/Эхлүүлэгч)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Ажлын хэсгийг нуух болон (дахин) харуулах"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Системийн тохиргоонд хандах"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Google Туслахад хандах"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Түгжигдсэн дэлгэц"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Шуурхай тэмдэглэхийн тулд Notes аппыг харуулах"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Систем олон ажил зэрэг хийх"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Одоогийн аппаар баруун гар талд Дэлгэц хуваахад орох"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Одоогийн аппаар зүүн гар талд Дэлгэц хуваахад орох"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Дэлгэц хуваахаас бүтэн дэлгэц рүү сэлгэх"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Дэлгэц хуваах үеэр: аппыг нэгээс нөгөөгөөр солих"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Оролт"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Оролтын хэлийг сэлгэх (дараагийн хэл)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Оролтын хэлийг сэлгэх (өмнөх хэл)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Эможид хандах"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Дуу хоолойгоор бичихэд хандах"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Апп"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Дэмжлэг"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Хөтөч"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Хөтөч (Chrome-г өгөгдмөлөөр тохируулах)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Харилцагчид"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Имэйл"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Имэйл (Gmail-г өгөгдмөлөөр тохируулах)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Хөгжим"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Календарь"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Тооны машин"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Газрын зураг"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Бүү саад бол"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Дууны түвшний товчлуурын товчлол"</string>
<string name="battery" msgid="769686279459897127">"Батарей"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"дэлгэцийн бичлэг"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Гарчиггүй"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Зогсолтын горим"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Фонтын хэмжээ"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Жижгэрүүлэх"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Томруулах"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Томруулалтын цонх"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Томруулалтын цонхны хяналт"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Томруулах"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"Алдаа гарлаа. Дахин оролдоно уу."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Ачаалж байна"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"таблет"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"Таны медиаг дамжуулж байна"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"<xliff:g id="APP_LABEL">%1$s</xliff:g>-г дамжуулж байна"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Идэвхгүй байна, аппыг шалгана уу"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Олдсонгүй"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Хяналт боломжгүй байна"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Нэвтрүүлэх боломжгүй"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Хадгалах боломжгүй. Дахин оролдоно уу."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Хадгалах боломжгүй."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Дор хаяж 4 тэмдэгт ашиглана уу."</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16-аас цөөн тэмдэгт ашиглана уу"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Хийцийн дугаар"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Хийцийн дугаарыг түр санах ойд хуулсан."</string>
<string name="basic_status" msgid="2315371112182658176">"Харилцан яриаг нээх"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Дор хаяж нэг төхөөрөмж боломжтой"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Товчлолд хүрээд удаан дарна уу"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Цуцлах"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Одоо хөнтрөх"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Илүү сайн селфи хийхийн тулд утсаа дэлгэнэ үү"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Сайн сельфи авахаар урд талын дэлгэц рүү хөнтрөх үү?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Илүү өндөр нягтаршилтай илүү өргөн зураг авахын тулд арын камерыг ашиглана уу."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Энэ дэлгэц унтарна"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Одоо дэлгэцүүдийг сэлгэх"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Утсыг дэлгэх"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Дэлгэцүүдийг сэлгэх үү?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Илүү өндөр нягтрал авах бол ар талын камерыг ашиглана уу"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Илүү өндөр нягтрал авах бол утсыг хөнтөрнө үү"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Эвхэгддэг төхөөрөмжийг дэлгэж байна"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Эвхэгддэг төхөөрөмжийг хөнтөрч байна"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> батарей үлдлээ"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Ажлын профайл руу сэлгэх"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Хаах"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Түгжигдсэн дэлгэцийн тохиргоо"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi боломжгүй байна"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камерыг блоклосон"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камер болон микрофоныг блоклосон"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Микрофоныг блоклосон"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Чухал горим асаалттай байна"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Туслах анхаарлаа хандуулж байна"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mn/tiles_states_strings.xml b/packages/SystemUI/res/values-mn/tiles_states_strings.xml
index 776c4877d1ad..33f359672477 100644
--- a/packages/SystemUI/res/values-mn/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-mn/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Унтраалттай"</item>
<item msgid="5966994759929723339">"Асаалттай"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Боломжгүй"</item>
+ <item msgid="2478289035899842865">"Унтраалттай"</item>
+ <item msgid="5137565285664080143">"Асаалттай"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index a023f0df72f6..b729efc167b5 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"सूचना शेड."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"क्विक सेटिंग्ज."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"क्विक सेटिंग्ज आणि सूचना शेड."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"लॉक स्क्रीन."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"कार्य लॉक स्क्रीन"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"बंद करा"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"चमक"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"कलर इन्व्हर्जन"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"रंग सुधारणा"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"फॉंटचा आकार"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"वापरकर्ते व्यवस्‍थापित करा"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"पूर्ण झाले"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"बंद करा"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"सूचना"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"कीबोर्ड शॉर्टकट"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"कीबोर्ड लेआउट स्विच करा"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"मजकूर साफ करा"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"शॉर्टकट"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"शॉर्टकट शोधा"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"एकही शॉर्टकट आढळला नाहीत"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"सिस्टीम"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"इनपुट"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"ॲप्स उघडा"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"सध्याचे अ‍ॅप"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"सूचना शेड अ‍ॅक्सेस करा"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"संपूर्ण स्क्रीनशॉट घ्या"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"सिस्टीम / अ‍ॅप्स शॉर्टकटची सूची अ‍ॅक्सेस करा"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"मागे: मागील स्थितीवर परत जा (मागे जा बटण)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"होम स्क्रीन अ‍ॅक्सेस करा"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"उघड्या असलेल्या अ‍ॅप्सचे अवलोकन"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"अलीकडील अ‍ॅप्स पहा (पुढील)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"अलीकडील अ‍ॅप्स पहा (मागील)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"सर्व अ‍ॅप्सची सूची अ‍ॅक्सेस करा आणि शोधा (उदा. शोध/लाँचर)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"टास्कबार लपवा आणि (पुन्हा) दाखवा"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"सिस्टीम सेटिंग्ज अ‍ॅक्सेस करा"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Google Assistant अ‍ॅक्सेस करा"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"लॉक स्क्रीन"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"झटपट मेमोसाठी Notes अ‍ॅप वर ओढा"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"सिस्टीम मल्टिटास्किंग"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"उजव्या बाजूला सध्याचे अ‍ॅप असलेल्या स्प्लिट स्क्रीनवर जा"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"डाव्या बाजूला सध्याचे अ‍ॅप असलेल्या स्प्लिट स्क्रीनवर जा"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"स्प्लिट स्क्रीन वरून फुल स्क्रीनवर स्विच करा"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"स्प्लिट स्क्रीन दरम्यान: एक अ‍ॅप दुसऱ्या अ‍ॅपने बदला"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"इनपुट"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"इनपुट भाषा स्विच करा (पुढील भाषा)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"इनपुट भाषा स्विच करा (मागील भाषा)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"इमोजी अ‍ॅक्सेस करा"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"व्हॉइस टायपिंग अ‍ॅक्सेस करा"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"ॲप्लिकेशन"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Assist"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"ब्राउझर"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"ब्राउझर (डीफॉल्ट म्हणून Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"संपर्क"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"ईमेल"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"ईमेल (डीफॉल्ट म्हणून Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"एसएमएस"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"संगीत"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"कॅलेंडर"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculator"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"व्यत्यय आणू नका"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"आवाजाच्या बटणांचा शार्टकट"</string>
<string name="battery" msgid="769686279459897127">"बॅटरी"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"स्क्रीन रेकॉर्डिंग"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"शीर्षक नाही"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"स्टँडबाय"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"फॉंट आकार"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"आणखी लहान करा"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"आणखी मोठे करा"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"मॅग्निफिकेशन विंडो"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"मॅग्निफिकेशन विंडो नियंत्रणे"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"झूम इन करा"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"काहीतरी चूक झाली. पुन्हा प्रयत्न करा."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"लोड करत आहे"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"टॅबलेट"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"तुमचा मीडिया कास्ट करत आहे"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"<xliff:g id="APP_LABEL">%1$s</xliff:g> कास्ट करत आहे"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"निष्क्रिय, ॲप तपासा"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"आढळले नाही"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"नियंत्रण उपलब्ध नाही"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"ब्रॉडकास्ट करू शकत नाही"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"सेव्ह करू शकत नाही. पुन्हा प्रयत्न करा."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"सेव्ह करू शकत नाही."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"किमान चार वर्ण वापरा"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"१६ पेक्षा कमी वर्ण वापरा"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"बिल्ड नंबर"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"बिल्ड नंबर क्लिपबोर्डवर कॉपी केला."</string>
<string name="basic_status" msgid="2315371112182658176">"संभाषण उघडा"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• किमान एक डिव्हाइस उपलब्ध करणे"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"स्पर्श करा आणि धरून ठेवा शॉर्टकट"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"रद्द करा"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"आता फ्लिप करा"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"आणखी चांगल्या सेल्फीसाठी फोनबद्दल अधिक जाणून घ्या"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"आणखी चांगल्या सेल्फीसाठी फ्रंट डिस्प्ले वापरायचा का?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"उच्च रेझोल्यूशन असलेल्या विस्तृत फोटोसाठी रीअर कॅमेरा वापरा."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ही स्क्रीन बंद होईल"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"आता स्क्रीन स्विच करा"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"फोन उघडा"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"स्क्रीन स्विच करायच्या का?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"उच्च रेझोल्यूशनसाठी रीअर कॅमेरा वापरा"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"उच्च रेझोल्यूशनसाठी, फोन फ्लिप करा"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"फोल्ड करता येण्यासारखे डिव्हाइस अनफोल्ड केले जात आहे"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"फोल्ड करता येण्यासारखे डिव्हाइस आजूबाजूला फ्लिप केले जात आहे"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> बॅटरी शिल्लक आहे"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"कार्य प्रोफाइलवर स्विच करा"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"बंद करा"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"लॉक स्क्रीन सेटिंग्ज"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"वाय-फाय उपलब्ध नाही"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"कॅमेरा ब्लॉक केला"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"कॅमेरा आणि मायक्रोफोन ब्लॉक केले आहेत"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"मायक्रोफोन ब्लॉक केला"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"प्राधान्य मोड सुरू आहे"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant चे लक्ष हे आता अ‍ॅक्टिव्ह आहे"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mr/tiles_states_strings.xml b/packages/SystemUI/res/values-mr/tiles_states_strings.xml
index f75f0d097998..24d3b47af961 100644
--- a/packages/SystemUI/res/values-mr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-mr/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"बंद आहे"</item>
<item msgid="5966994759929723339">"सुरू आहे"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"उपलब्ध नाही"</item>
+ <item msgid="2478289035899842865">"बंद आहे"</item>
+ <item msgid="5137565285664080143">"सुरू आहे"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 7075a32e8e30..9ed06362c359 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Bidai pemberitahuan."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Tetapan pantas."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Tetapan pantas dan Bidai pemberitahuan."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Kunci skrin."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Skrin kunci kerja"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Tutup"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Kecerahan"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Penyongsangan warna"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Pembetulan warna"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Saiz fon"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Urus pengguna"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Selesai"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Tutup"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Pemberitahuan"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Pintasan Papan Kekunci"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Tukar reka letak papan kekunci"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Kosongkan teks"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Pintasan"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Pintasan carian"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Tiada pintasan ditemukan"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistem"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Input"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Apl yang dibuka"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Apl semasa"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Akses bidai pemberitahuan"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Ambil tangkapan skrin penuh"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Akses senarai pintasan sistem / apl"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Kembali: pergi semula kepada keadaan sebelumnya (butang kembali)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Akses skrin utama"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Gambaran keseluruhan apl yang terbuka"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Mengitar apl terbaharu (hadapan)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Mengitar apl terbaharu (belakang)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Akses senarai semua apl dan cari (iaitu Carian/Pelancar)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Sembunyikan dan tunjukkan (semula) bar tugas"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Akses tetapan sistem"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Akses Google Assistant"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Kunci skrin"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Tarik ke atas apl Nota untuk memo pantas"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Berbilang tugas sistem"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Masuk skrin Pisah dengan apl semasa pada sisi kanan"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Masuk skrin Pisah dengan apl semasa pada sisi kiri"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Tukar daripada skrin Pisah kepada skrin penuh"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Semasa skrin Pisah: gantikan apl daripada satu apl kepada apl lain"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Input"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Tukar bahasa input (bahasa seterusnya)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Tukar bahasa input (bahasa sebelumnya)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Akses emoji"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Akses penaipan suara"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Aplikasi"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Bantu"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Penyemak imbas"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Penyemak imbas (Chrome sebagai lalai)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Kenalan"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"E-mel"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"E-mel (Gmail sebagai lalai)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Muzik"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalendar"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kalkulator"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Peta"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Jangan Ganggu"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Pintasan butang kelantangan"</string>
<string name="battery" msgid="769686279459897127">"Bateri"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"rakaman skrin"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Tiada tajuk"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Tunggu sedia"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Saiz Fon"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Kecilkan"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Besarkan"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Tetingkap Pembesaran"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kawalan Tetingkap Pembesaran"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Zum masuk"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Tidak dapat disiarkan"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Tidak dapat disimpan. Cuba lagi."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Tidak dapat disimpan."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Gunakan sekurang-kurangnya 4 aksara"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Gunakan kurang daripada 16 aksara"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Nombor binaan"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Nombor binaan disalin ke papan keratan."</string>
<string name="basic_status" msgid="2315371112182658176">"Buka perbualan"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Sekurang-kurangnya satu peranti tersedia"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Pintasan sentuh &amp; tahan"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Batal"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Balikkan sekarang"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Buka telefon untuk swafoto yang lebih baik"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Balikkan ke paparan depan utk swafoto lebih baik?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Gunakan kamera menghadap belakang untuk mendapatkan foto yang lebih luas dengan resolusi yang lebih tinggi."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Skrin ini akan dimatikan"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Tukar skrin sekarang"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Buka telefon"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Tukar skrin?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Untuk peleraian lebih tinggi, gunakan kamera belakang"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Untuk peleraian lebih tinggi, balikkan telefon"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Peranti boleh lipat dibuka"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Peranti boleh lipat diterbalikkan"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Bateri tinggal <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Tukar kepada profil kerja"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Tutup"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Tetapan skrin kunci"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi tidak tersedia"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera disekat"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera dan mikrofon disekat"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon disekat"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Mod keutamaan dihidupkan"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Perhatian pembantu dihidupkan"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ms/tiles_states_strings.xml b/packages/SystemUI/res/values-ms/tiles_states_strings.xml
index 9fa7ab51d064..07a8426feeb2 100644
--- a/packages/SystemUI/res/values-ms/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ms/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Mati"</item>
<item msgid="5966994759929723339">"Hidup"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Tidak tersedia"</item>
+ <item msgid="2478289035899842865">"Mati"</item>
+ <item msgid="5137565285664080143">"Hidup"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 65345d0bdda9..88165a83589a 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"အ​ကြောင်းကြားစာအကွက်"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"အမြန်လုပ် အပြင်အဆင်"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"‘အမြန်ဆက်တင်များ’ နှင့် ‘အကြောင်းကြားစာအကွက်’။"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"မျက်နှာပြင် သော့ပိတ်ရန်"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"အလုပ်သုံး လော့ခ်မျက်နှာပြင်"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"ပိတ်ရန်"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"အလင်းတောက်ပမှု"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"အရောင်ပြောင်းပြန်ပြုလုပ်ရန်"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"အရောင် အမှန်ပြင်ခြင်း"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"ဖောင့်အရွယ်အစား"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"အသုံးပြုသူများ စီမံရန်"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"ပြီးပါပြီ"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"ပိတ်ရန်"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"အကြောင်းကြားချက်များ"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"ကီးဘုတ် ဖြတ်လမ်းများ"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"ကီးဘုတ်အပြင်အဆင် ပြောင်းခြင်း"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"စာသား ဖယ်ရှားရန်"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ဖြတ်လမ်းလင့်ခ်များ"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"ဖြတ်လမ်းလင့်ခ်များ ရှာပါ"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"ဖြတ်လမ်းလင့်ခ် မတွေ့ပါ"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"စနစ်"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"စာရိုက်ခြင်း"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"ဖွင့်ထားသောအက်ပ်"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"လက်ရှိအက်ပ်"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"အကြောင်းကြားစာအကွက် သုံးရန်"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"ဖန်သားပြင်ဓာတ်ပုံအပြည့် ရိုက်ကူးရန်"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"စနစ် / အက်ပ်ဖြတ်လမ်းလင့်ခ်စာရင်း ဝင်ကြည့်ရန်"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"နောက်သို့- ယခင်အခြေအနေသို့ ပြန်သွားရန် (နောက်သို့ ခလုတ်)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"ပင်မစာမျက်နှာ ဝင်ကြည့်ရန်"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"ဖွင့်ထားသောအက်ပ်များ အနှစ်ချုပ်"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"လတ်တလောအက်ပ်များ ရှာဖွေကြည့်ရှုရန် (ရှေ့သို့)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"လတ်တလောအက်ပ်များ ရှာဖွေကြည့်ရှုရန် (နောက်သို့)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"အက်ပ်အားလုံးစာရင်းကို ဝင်ကြည့်ပြီး ရှာပါ (ဥပမာ- Search/Launcher)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"လုပ်ဆောင်စရာဘားကို ဖျောက်ထားပြီး ပြန်ပြရန်"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"စက်စနစ်ဆက်တင်များ ဝင်ကြည့်ရန်"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Google Assistant သုံးရန်"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"လော့ခ်မျက်နှာပြင်"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"အမြန်မှတ်သားရန် မှတ်စုရေးသောအက်ပ် ဖွင့်ပါ"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"စနစ်က တစ်ပြိုင်နက် များစွာလုပ်ခြင်း"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"လက်ရှိအက်ပ်ဖြင့် ညာဘက်ရှိ ‘မျက်နှာပြင် ခွဲ၍ပြသခြင်း’ သို့ ဝင်ရန်"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"လက်ရှိအက်ပ်ဖြင့် ဘယ်ဘက်ရှိ ‘မျက်နှာပြင် ခွဲ၍ပြသခြင်း’ သို့ ဝင်ရန်"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"‘မျက်နှာပြင် ခွဲ၍ပြသခြင်း’ မှ မျက်နှာပြင်အပြည့်သို့ ပြောင်းရန်"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"‘မျက်နှာပြင်ခွဲ၍ပြသစဉ်’- အက်ပ်ကို တစ်ခုမှ နောက်တစ်ခုသို့ အစားထိုးရန်"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"စာရိုက်ခြင်း"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"စာရိုက်မည့် ဘာသာစကား ပြောင်းရန် (နောက်ဘာသာစကား)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"စာရိုက်မည့် ဘာသာစကား ပြောင်းရန် (ယခင်ဘာသာစကား)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"အီမိုဂျီ သုံးရန်"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"အသံဖြင့်စာရိုက်ခြင်း သုံးရန်"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"အက်ပ်များ"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"အထောက်အကူ"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"ဘရောင်ဇာ"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"ဘရောင်ဇာ (Chrome ကို မူရင်းအဖြစ်)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"အဆက်အသွယ်များ"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"အီးမေးလ်"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"အီးမေးလ် (Gmail ကို မူရင်းအဖြစ်)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS စာတိုစနစ်"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Music"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"ပြက္ခဒိန်"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"ဂဏန်းတွက်စက်"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"မနှောင့်ယှက်ရ"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"အသံထိန်းချုပ်သည့်ခလုတ် ဖြတ်လမ်း"</string>
<string name="battery" msgid="769686279459897127">"ဘက်ထရီ"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"စခရင်ရိုက်ကူးမှု"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"ခေါင်းစဉ် မရှိပါ"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"အသင့်အနေအထား"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"ဖောင့်အရွယ်အစား"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"ချုံ့ရန်"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"ချဲ့ရန်"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"ဝင်းဒိုး ချဲ့ခြင်း"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"ဝင်းဒိုး ထိန်းချုပ်မှုများ ချဲ့ခြင်း"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"ဇူးမ်ဆွဲရန်"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"ထုတ်လွှင့်၍ မရပါ"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"သိမ်း၍မရပါ။ ထပ်စမ်းကြည့်ပါ။"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"သိမ်း၍မရပါ။"</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"အနည်းဆုံး အက္ခရာ ၄ လုံး သုံးရန်"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"အက္ခရာ ၁၆ လုံးအောက် သုံးရန်"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"တည်ဆောက်မှုနံပါတ်"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"တည်ဆောက်မှုနံပါတ်ကို ကလစ်ဘုတ်သို့ မိတ္တူကူးပြီးပါပြီ။"</string>
<string name="basic_status" msgid="2315371112182658176">"စကားဝိုင်းကို ဖွင့်ရန်"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• အနည်းဆုံး စက်တစ်ခုသုံးနိုင်ရမည်"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"ဖြတ်လမ်းလင့်ခ်ကို ထိပြီးဖိထားပါ"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"မလုပ်တော့"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"ယခုလှည့်လိုက်ပါ"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"ပိုကောင်းသော ဆယ်လ်ဖီအတွက် ဖုန်းကိုဖြန့်လိုက်ပါ"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"ပိုကောင်းသော ဆယ်လ်ဖီအတွက် ဖန်သားပြင်ကိုလှည့်မလား။"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"ပုံရိပ်ပြတ်သားကိန်း ပိုမြင့်ပြီး မြင်ကွင်းပိုကျယ်သည့် ဓာတ်ပုံအတွက် နောက်ဘက်ကင်မရာကို အသုံးပြုပါ။"</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ဤဖန်သားပြင်ကို ပိတ်လိုက်မည်"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"စခရင်များ ယခုပြောင်းရန်"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"ဖုန်းကို ဖြန့်လိုက်ပါ"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"စခရင်များ ပြောင်းမလား။"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"ပုံရိပ် ပိုမိုပြတ်သားစေရန် အနောက်ကင်မရာသုံးပါ"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"ပုံရိပ် ပိုမိုပြတ်သားစေရန် ဖုန်းကို တစ်ဖက်သို့ လှန်လိုက်ပါ"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ခေါက်နိုင်သောစက်ကို ဖြန့်လိုက်သည်"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ခေါက်နိုင်သောစက်ကို တစ်ဘက်သို့ လှန်လိုက်သည်"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"ဘက်ထရီ <xliff:g id="PERCENTAGE">%s</xliff:g> ကျန်သေးသည်"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"အလုပ်ပရိုဖိုင်သို့ ပြောင်းရန်"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"ပိတ်ရန်"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"လော့ခ်မျက်နှာပြင် ဆက်တင်များ"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi မရနိုင်ပါ"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"ကင်မရာကို ပိတ်ထားသည်"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"ကင်မရာနှင့် မိုက်ခရိုဖုန်းကို ပိတ်ထားသည်"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"မိုက်ခရိုဖုန်းကို ပိတ်ထားသည်"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"ဦးစားပေးမုဒ် ဖွင့်ထားသည်"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant နားထောင်နေသည်"</string>
</resources>
diff --git a/packages/SystemUI/res/values-my/tiles_states_strings.xml b/packages/SystemUI/res/values-my/tiles_states_strings.xml
index 493a7f0977c6..fd375d4f3eb1 100644
--- a/packages/SystemUI/res/values-my/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-my/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"ပိတ်"</item>
<item msgid="5966994759929723339">"ဖွင့်"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"မရနိုင်ပါ"</item>
+ <item msgid="2478289035899842865">"ပိတ်"</item>
+ <item msgid="5137565285664080143">"ဖွင့်"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index d6d0b0188846..33d87ead34df 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Varselskygge."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Hurtiginnstillinger."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Hurtiginnstillinger og varselpanelet"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Låseskjerm."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Låseskjerm for arbeid"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Lukk"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Lysstyrke"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Fargeinvertering"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Fargekorrigering"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Skriftstørrelse"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Administrer brukere"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Ferdig"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Lukk"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Varsler"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Hurtigtaster"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Bytt tastaturoppsett"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Fjern teksten"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Hurtigtaster"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Søk etter hurtigtaster"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Fant ingen hurtigtaster"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"System"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Inndata"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Åpne apper"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Aktiv app"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Åpne varselpanelet"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Ta en skjermdump av hele skjermen"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Se hurtigtastene for systemet/apper"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Tilbake: Gå tilbake til forrige tilstand (tilbakeknapp)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Åpne startskjermen"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Oversikt over åpne apper"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Bla gjennom nylige apper (fremover)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Bla gjennom nylige apper (bakover)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Se alle apper og søk (dvs. Søk/Appoversikt)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Skjul og vis oppgavelinjen"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Åpne systeminnstillingene"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Aktiver Google-assistenten"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Låseskjerm"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Åpne Notes-appen for å ta notater raskt"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitasking på systemet"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Åpne delt skjerm med den aktive appen til høyre"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Åpne delt skjerm med den aktive appen til venstre"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Bytt fra delt skjerm til fullskjerm"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"I delt skjerm: Bytt ut en app"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Skrivespråk"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Bytt skrivespråk (neste språk)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Bytt skrivespråk (forrige språk)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Se emojier"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Bruk stemmestyrt skriving"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Apper"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Assist"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Nettleser"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Nettleser (Chrome som standard)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Kontakter"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"E-post"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"E-post (Gmail som standard)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Musikk"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalender"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kalkulator"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Ikke forstyrr"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Hurtigtast for volumknappene"</string>
<string name="battery" msgid="769686279459897127">"Batteri"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"skjermopptak"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Ingen tittel"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Ventemodus"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Skriftstørrelse"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Gjør mindre"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Gjør større"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Forstørringsvindu"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kontroller for forstørringsvindu"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Zoom inn"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"Noe gikk galt. Prøv på nytt."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Laster inn"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"nettbrett"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"Caster mediene"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"Caster <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv. Sjekk appen"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ikke funnet"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Kontrollen er utilgjengelig"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Kan ikke kringkaste"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Kan ikke lagre. Prøv på nytt."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Kan ikke lagre."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Bruk minst 4 tegn"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Bruk færre enn 16 tegn"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Delversjonsnummer"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Delversjonsnummeret er kopiert til utklippstavlen."</string>
<string name="basic_status" msgid="2315371112182658176">"Åpen samtale"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• minst én enhet er tilgjengelig"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Trykk på og hold inne snarveien"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Avbryt"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Vend nå"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Brett ut telefonen for å ta bedre selfier"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Vil du bruke frontkameraet for bedre selfier?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Bruk det bakovervendte kameraet for å ta bredere bilder med høyere oppløsning."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Denne skjermen slås av"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Bytt skjerm nå"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Brett ut telefonen"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Vil du bytte skjerm?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Bruk baksidekameraet for å få høyere oppløsning"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Brett ut telefonen for å få høyere oppløsning"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"En sammenleggbar enhet blir brettet ut"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"En sammenleggbar enhet blir snudd"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> batteri gjenstår"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Bytt til jobbprofilen"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Lukk"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Innstillinger for låseskjermen"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wifi er ikke tilgjengelig"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kameraet er blokkert"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kameraet og mikrofonen er blokkert"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofonen er blokkert"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioriteringsmodus er på"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistentoppmerksomhet er på"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nb/tiles_states_strings.xml b/packages/SystemUI/res/values-nb/tiles_states_strings.xml
index 6fa902a662ff..e4a811941b2a 100644
--- a/packages/SystemUI/res/values-nb/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-nb/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Av"</item>
<item msgid="5966994759929723339">"På"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Utilgjengelig"</item>
+ <item msgid="2478289035899842865">"Av"</item>
+ <item msgid="5137565285664080143">"På"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 1c6435b4d9d0..48e134bb27e4 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"सूचना कक्ष।"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"द्रुत सेटिङहरू"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"द्रुत सेटिङ तथा सूचना कक्ष।"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"स्क्रीन बन्द गर्नुहोस्।"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"कार्य प्रोफाइलको लक स्क्रिन"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"बन्द गर्नुहोस्"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"उज्यालपन"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"कलर इन्भर्सन"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"कलर करेक्सन"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"फन्टको आकार"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"प्रयोगकर्ताहरू व्यवस्थित गर्नुहोस्"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"भयो"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"बन्द गर्नुहोस्"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"सूचनाहरू"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"किबोर्ड सर्टकटहरू"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"किबोर्डको लेआउट बदल्नुहोस्"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"टेक्स्ट हटाउनुहोस्"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"सर्टकटहरू"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"सर्टकटहरू खोज्नुहोस्"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"कुनै पनि सर्टकट भेटिएन"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"सिस्टम"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"इनपुट"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"खोलिएका एपहरू"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"हालको एप"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"सूचना कक्षमा जानुहोस्"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"पूरा स्क्रिनसट खिच्नुहोस्"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"सिस्टम / एपका सर्टकटहरूको सूची हेर्नुहोस्"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"पछाडि: अघिल्लो अवस्थामा फर्कनुहोस् (पछाडि बटन)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"होम स्क्रिनमा जानुहोस्"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"खोलिएका एपहरूको विवरण"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"हालसालै खोलिएका एपहरू हेर्नुहोस् (अगाडि)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"हालसालै खोलिएका एपहरू हेर्नुहोस् (पछाडि)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"सबै एप र खोज (अर्थात्, Search/लन्चर) को सूची हेर्नुहोस्"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"टास्कबार लुकाइयोस् र (पुनः) देखाइयोस्"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"सिस्टमका सेटिङमा जानुहोस्"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Google सहायक प्रयोग गर्नुहोस्"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"स्क्रिन लक गर्नुहोस्"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"झट्टै कुनै टिपोट लेख्न Notes एप प्रयोग गर्नुहोस्"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"सिस्टम मल्टिटास्किङ"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"हालको एप दायाँतर्फ रहने गरी स्प्लिट स्क्रिनमा प्रवेश गर्नुहोस्"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"हालको एप बायाँतर्फ रहने गरी स्प्लिट स्क्रिनमा प्रवेश गर्नुहोस्"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"स्प्लिट स्क्रिनको साटो फुल स्क्रिन प्रयोग गर्नुहोस्"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"स्प्लिट स्क्रिन प्रयोग गरिएका बेला: एउटा स्क्रिनमा भएको एप अर्कोमा लैजानुहोस्"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"इनपुट"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"इनपुट भाषा बदल्नुहोस् (अर्को भाषा)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"इनपुट भाषा बदल्नुहोस् (अघिल्लो भाषा)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"इमोजी प्रयोग गर्नुहोस्"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"भ्वाइस टाइपिङ प्रयोग गर्नुहोस्"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"एपहरू"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"सहायता"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"ब्राउजर"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"ब्राउजर (डिफल्ट ब्राउजर: Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"सम्पर्कहरू"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"इमेल"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"इमेल (डिफल्ट एप: Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"सङ्गीत"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"पात्रो"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"क्याल्कुलेटर"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"नक्सा"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"बाधा नपुऱ्याउनुहोस्"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"भोल्युम बटनका सर्टकट"</string>
<string name="battery" msgid="769686279459897127">"ब्याट्री"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"स्क्रिन रेकर्डिङ"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"शीर्षक छैन"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"स्ट्यान्डबाई"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"फन्टको आकार"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"अझ सानो बनाउनुहोस्"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"अझ ठुलो बनाउनुहोस्"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"म्याग्निफिकेसन विन्डो"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"म्याग्निफिकेसन विन्डोका नियन्त्रणहरू"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"जुम इन गर्नुहोस्"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"प्रसारण गर्न सकिएन"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"सेभ गर्न सकिएन। फेरि प्रयास गर्नुहोस्।"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"सेभ गर्न सकिएन।"</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"कम्तीमा ४ वटा वर्ण प्रयोग गर्नुहोस्"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"१६ वटाभन्दा कम वर्ण प्रयोग गर्नुहोस्"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"बिल्ड नम्बर"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"बिल्ड नम्बर कपी गरी क्लिपबोर्डमा सारियो।"</string>
<string name="basic_status" msgid="2315371112182658176">"वार्तालाप खोल्नुहोस्"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• कम्तीमा एउटा डिभाइस उपलब्ध छ"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"सर्टकट थिचिराख्नुहोस्"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"रद्द गर्नुहोस्"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"अहिले नै फ्लिप गर्नुहोस्"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"अझ राम्रो सेल्फी खिच्न फोन अनफोल्ड गर्नुहोस्"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"अझ राम्रो सेल्फी खिच्न फ्लिप गरी अगाडिपट्टिको डिस्प्ले प्रयोग गर्ने हो?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"अझ बढी रिजोल्युसन भएको फराकिलो फोटो खिच्न पछाडिपट्टिको क्यामेरा प्रयोग गर्नुहोस्।"</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ यो स्क्रिन अफ हुने छ"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"अहिले नै स्क्रिन बदल्नुहोस्"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"फोन अनफोल्ड गर्नुहोस्"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"स्क्रिनहरू बदल्ने हो?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"उच्च रिजोल्युसनको सेल्फी खिच्न पछाडिको क्यामेरा प्रयोग गर्नुहोस्"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"उच्च रिजोल्युसनको सेल्फी खिच्न फोन फ्लिप गर्नुहोस्"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"फोल्ड गर्न मिल्ने डिभाइस अनफोल्ड गरेको देखाइएको एनिमेसन"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"फोल्ड गर्न मिल्ने डिभाइस यताउता पल्टाएर देखाइएको एनिमेसन"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> ब्याट्री बाँकी छ"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"कार्य प्रोफाइल प्रयोग गर्नुहोस्"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"बन्द गर्नुहोस्"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"लक स्क्रिनसम्बन्धी सेटिङ"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi उपलब्ध छैन"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"क्यामेरा ब्लक गरिएको छ"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"क्यामेरा र माइक्रोफोन ब्लक गरिएको छ"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"माइक्रोफोन ब्लक गरिएको छ"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"प्राथमिकता मोड अन छ"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"सहायकले सुनिरहेको छ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ne/tiles_states_strings.xml b/packages/SystemUI/res/values-ne/tiles_states_strings.xml
index 17193bafd9a3..5cf91e533494 100644
--- a/packages/SystemUI/res/values-ne/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ne/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"अफ"</item>
<item msgid="5966994759929723339">"अन"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"उपलब्ध छैन"</item>
+ <item msgid="2478289035899842865">"अफ छ"</item>
+ <item msgid="5137565285664080143">"अन छ"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index d7954b7812a8..2f86231a4827 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Meldingenpaneel."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Snelle instellingen."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Snelle instellingen en meldingenpaneel."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Vergrendelscherm."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Vergrendelscherm voor werk"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Sluiten"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Helderheid"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Kleurinversie"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Kleurcorrectie"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Lettergrootte"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Gebruikers beheren"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Klaar"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Sluiten"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Meldingen"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Sneltoetsen"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Toetsenbordindeling wisselen"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Tekst wissen"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Sneltoetsen"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Sneltoetsen zoeken"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Geen sneltoetsen gevonden"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Systeem"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Invoer"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Apps openen"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Huidige app"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Het meldingenpaneel openen"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Een volledige schermafbeeldingen maken"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Lijst van snelkoppelingen voor systeem/apps openen"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Terug: terug naar de vorige status (terugknop)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Het startscherm openen"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Overzicht van geopende apps"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Door recente apps navigeren (vooruit)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Door recente apps navigeren (terug)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Toegangslijst van alle apps en zoekopties (bijv. Zoeken/Launcher)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Taakbalk verbergen en (opnieuw) tonen"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Systeeminstellingen openen"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"De Google Assistent activeren"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Scherm vergrendelen"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Notitie-app tevoorschijn halen voor snelle notitie"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Systeem-multitasking"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Gesplitst scherm openen met huidige app rechts"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Gesplitst scherm openen met huidige app links"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Van gesplitst scherm naar volledig scherm schakelen"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Tijdens gesplitst scherm: een app vervangen door een andere"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Invoer"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Invoertaal veranderen (volgende taal)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Invoertaal veranderen (vorige taal)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Emoji\'s openen"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Spraakgestuurd typen activeren"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Apps"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Assistentie"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Browser"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Browser (Chrome als standaard)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Contacten"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"E-mail"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"E-mail (Gmail als standaard)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"Sms"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Muziek"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Agenda"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Rekenmachine"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Niet storen"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Volumeknoppen als sneltoets"</string>
<string name="battery" msgid="769686279459897127">"Batterij"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"schermopname"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Geen titel"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Stand-by"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Lettergrootte"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Verkleinen"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Vergroten"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Vergrotingsvenster"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Bediening van vergrotingsvenster"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Inzoomen"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Kan niet uitzenden"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Kan niet opslaan. Probeer het opnieuw."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Kan niet opslaan."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Gebruik minstens 4 tekens"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Gebruik minder dan 16 tekens"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Buildnummer"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Buildnummer naar klembord gekopieerd."</string>
<string name="basic_status" msgid="2315371112182658176">"Gesprek openen"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Er is ten minste één apparaat beschikbaar"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Houd de sneltoets ingedrukt"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Annuleren"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Nu omkeren"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Klap de telefoon open voor een betere selfie"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Omkeren naar scherm voorkant voor een betere selfie?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Gebruik de camera aan de achterzijde voor een bredere foto met hogere resolutie."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Dit scherm gaat uit"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Wissel nu van scherm"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Telefoon openklappen"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Van scherm wisselen?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Gebruik de camera aan de achterzijde voor een hogere resolutie"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Draai de telefoon om voor een hogere resolutie"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Opvouwbaar apparaat wordt uitgevouwen"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Opvouwbaar apparaat wordt gedraaid"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Nog <xliff:g id="PERCENTAGE">%s</xliff:g> batterijlading"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Overschakelen naar werkprofiel"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Sluiten"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Instellingen vergrendelscherm"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wifi niet beschikbaar"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Camera geblokkeerd"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Camera en microfoon geblokkeerd"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microfoon geblokkeerd"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioriteitsmodus aan"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistent-aandacht aan"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nl/tiles_states_strings.xml b/packages/SystemUI/res/values-nl/tiles_states_strings.xml
index fbccd78eeb8f..592ecf5b69d6 100644
--- a/packages/SystemUI/res/values-nl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-nl/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Uit"</item>
<item msgid="5966994759929723339">"Aan"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Niet beschikbaar"</item>
+ <item msgid="2478289035899842865">"Uit"</item>
+ <item msgid="5137565285664080143">"Aan"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index d187ad6869c2..4ac1f8486768 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"ବିଜ୍ଞପ୍ତି ଶେଡ୍‍।"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"କ୍ୱିକ୍ ସେଟିଂସ୍।"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"କୁଇକ ସେଟିଂସ ଏବଂ ବିଜ୍ଞପ୍ତି ସେଡ।"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ଲକ୍‌ ସ୍କ୍ରୀନ୍‌।"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"ୱର୍କ ଲକ୍‍ ସ୍କ୍ରୀନ୍‍"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"ବନ୍ଦ କରନ୍ତୁ"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"ଉଜ୍ଜ୍ୱଳତା"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"ରଙ୍ଗ ଇନଭାର୍ସନ"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"ରଙ୍ଗ ସଂଶୋଧନ"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"ଫଣ୍ଟର ଆକାର"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"ୟୁଜରମାନଙ୍କୁ ପରିଚାଳନା କରନ୍ତୁ"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"ହୋଇଗଲା"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"ବନ୍ଦ କରନ୍ତୁ"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"ବିଜ୍ଞପ୍ତି"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"କୀ\'ବୋର୍ଡ ସର୍ଟକଟ୍"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"କୀ\'ବୋର୍ଡ୍‍ର ଲେଆଉଟ୍‍କୁ ବଦଳାନ୍ତୁ"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"ଟେକ୍ସଟ ଖାଲି କରନ୍ତୁ"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ସର୍ଟକଟଗୁଡ଼ିକ"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"ସର୍ଟକଟ ସର୍ଚ୍ଚ କରନ୍ତୁ"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"କୌଣସି ସର୍ଟକଟ ମିଳିଲା ନାହିଁ"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"ସିଷ୍ଟମ"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"ଇନପୁଟ କରନ୍ତୁ"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"ଆପ୍ସ ଖୋଲନ୍ତୁ"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"ବର୍ତ୍ତମାନର ଆପ"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"ବିଜ୍ଞପ୍ତି ସେଡକୁ ଆକ୍ସେସ କରନ୍ତୁ"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"ଏକ ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନସଟ ନିଅନ୍ତୁ"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"ସିଷ୍ଟମ / ଆପ୍ସ ସର୍ଟକଟର ଆକ୍ସେସ ତାଲିକା"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"ପଛକୁ: ପୂର୍ବ ସ୍ଥିତିକୁ ଫେରି ଯାଆନ୍ତୁ (ପଛକୁ ଯାଆନ୍ତୁ ବଟନ)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"ହୋମ ସ୍କ୍ରିନକୁ ଆକ୍ସେସ କରନ୍ତୁ"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"ଖୋଲାଥିବା ଆପ୍ସର ଓଭରଭିଉ"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"ବର୍ତ୍ତମାନର ଆପ୍ସ ମଧ୍ୟରେ ସ୍ଵିଚ କରନ୍ତୁ (ଆଗକୁ)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"ବର୍ତ୍ତମାନର ଆପ୍ସ ମଧ୍ୟରେ ସ୍ଵିଚ କରନ୍ତୁ (ପଛକୁ)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"ସମସ୍ତ ଆପ୍ସ ଏବଂ ସର୍ଚ୍ଚର ଆକ୍ସେସ ତାଲିକା (ଯଥା ସର୍ଚ୍ଚ/ଲଞ୍ଚର)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"ଲୁଚାନ୍ତୁ ଏବଂ (ପୁଣି)ଦେଖାନ୍ତୁ ଟାସ୍କବାର"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"ସିଷ୍ଟମ ସେଟିଂସର ଆକ୍ସେସ"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Google Assistantକୁ ଆକ୍ସେସ କରନ୍ତୁ"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"ଲକ ସ୍କ୍ରିନ"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"କ୍ୱିକ ମେମୋ ପାଇଁ Notes ଆପ ଖୋଲନ୍ତୁ"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"ସିଷ୍ଟମ ମଲ୍ଟିଟାସ୍କିଂ"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"RHSରେ ବର୍ତ୍ତମାନର ଆପ ସହ ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନକୁ ପ୍ରବେଶ କରାନ୍ତୁ"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"LHSରେ ବର୍ତ୍ତମାନର ଆପ ସହ ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନକୁ ପ୍ରବେଶ କରାନ୍ତୁ"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନରୁ ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନକୁ ସ୍ଵିଚ କରନ୍ତୁ"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନ ସମୟରେ: କୌଣସି ଆପକୁ ଗୋଟିଏରୁ ଅନ୍ୟ ଏକ ଆପରେ ବଦଳାନ୍ତୁ"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"ଇନପୁଟ କରନ୍ତୁ"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"ଇନପୁଟ ଭାଷା ସ୍ୱିଚ କରନ୍ତୁ (ପରବର୍ତ୍ତୀ ଭାଷା)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"ଇନପୁଟ ଭାଷା ସ୍ୱିଚ କରନ୍ତୁ (ପୂର୍ବବର୍ତ୍ତୀ ଭାଷା)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"ଇମୋଜି ଆକ୍ସେସ କରନ୍ତୁ"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"ଭଏସ ଟାଇପିଂ ଆକ୍ସେସ କରନ୍ତୁ"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"ଆପ୍ଲିକେସନ୍‌"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"ସହାୟତା"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"ବ୍ରାଉଜର୍"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"ବ୍ରାଉଜର (ଡିଫଲ୍ଟ ଭାବେ Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"କଣ୍ଟାକ୍ଟ"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"ଇମେଲ୍"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"ଇମେଲ (ଡିଫଲ୍ଟ ଭାବେ Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"ମ୍ୟୁଜିକ୍‍"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"କ୍ୟାଲେଣ୍ଡର"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"କାଲକୁଲେଟର"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"ଭଲ୍ୟୁମ ବଟନ୍‍ ଶର୍ଟକଟ୍‍"</string>
<string name="battery" msgid="769686279459897127">"ବ୍ୟାଟେରୀ"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ସ୍କ୍ରିନ ରେକର୍ଡିଂ"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"କୌଣସି ଶୀର୍ଷକ ନାହିଁ"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"ଷ୍ଟାଣ୍ଡବାଏ"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"ଫଣ୍ଟର ଆକାର"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"ଛୋଟ କରନ୍ତୁ"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"ବହୁତ ବଡ଼ କରନ୍ତୁ"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"ମ୍ୟାଗ୍ନିଫିକେସନ୍ ୱିଣ୍ଡୋ"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"ମ୍ୟାଗ୍ନିଫିକେସନ୍ ୱିଣ୍ଡୋ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"ଜୁମ୍ ଇନ୍ କରନ୍ତୁ"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"କିଛି ତ୍ରୁଟି ହୋଇଛି। ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"ଲୋଡ ହେଉଛି"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"ଟାବଲେଟ"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"ଆପଣଙ୍କ ମିଡିଆକୁ କାଷ୍ଟ କରାଯାଉଛି"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"<xliff:g id="APP_LABEL">%1$s</xliff:g>କୁ କାଷ୍ଟ କରାଯାଉଛି"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ନିଷ୍କ୍ରିୟ ଅଛି, ଆପ ଯାଞ୍ଚ କରନ୍ତୁ"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"ମିଳିଲା ନାହିଁ"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"ନିୟନ୍ତ୍ରଣ ଉପଲବ୍ଧ ନାହିଁ"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"ବ୍ରଡକାଷ୍ଟ କରାଯାଇପାରିବ ନାହିଁ"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"ସେଭ କରାଯାଇପାରିଲା ନାହିଁ। ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"ସେଭ କରାଯାଇପାରିଲା ନାହିଁ।"</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ଅତିକମରେ 4ଟି କେରେକ୍ଟର ବ୍ୟବହାର କରନ୍ତୁ"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16ଟିରୁ କମ କେରେକ୍ଟର ବ୍ୟବହାର କରନ୍ତୁ"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ବିଲ୍ଡ ନମ୍ୱର"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"କ୍ଲିପବୋର୍ଡକୁ କପି କରାଯାଇଥିବା ବିଲ୍ଡ ନମ୍ୱର।"</string>
<string name="basic_status" msgid="2315371112182658176">"ବାର୍ତ୍ତାଳାପ ଖୋଲନ୍ତୁ"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• ଅତିକମରେ ଗୋଟିଏ ଡିଭାଇସ ଉପଲବ୍ଧ ଅଛି"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"ସର୍ଟକଟକୁ ସ୍ପର୍ଶ କରି ଧରି ରଖନ୍ତୁ"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"ବାତିଲ କରନ୍ତୁ"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"ବର୍ତ୍ତମାନ ଫ୍ଲିପ କରନ୍ତୁ"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"ଏକ ଉନ୍ନତ ସେଲ୍ଫି ପାଇଁ ଫୋନକୁ ଅନଫୋଲ୍ଡ କରନ୍ତୁ"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"ଏକ ଉନ୍ନତ ସେଲ୍ଫି ପାଇଁ ସାମ୍ନା ଡିସପ୍ଲେକୁ ଫ୍ଲିପ କରିବେ?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"ଉଚ୍ଚ ରିଜୋଲ୍ୟୁସନ ସହ ଅଧିକ ଚଉଡ଼ାର ଏକ ଫଟୋ ନେବା ପାଇଁ ପଛ-ପଟର କେମେରା ବ୍ୟବହାର କରନ୍ତୁ।"</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ଏହି ସ୍କ୍ରିନ ବନ୍ଦ ହୋଇଯିବ"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"ବର୍ତ୍ତମାନ ସ୍କ୍ରିନ ସ୍ୱିଚ କରନ୍ତୁ"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"ଫୋନକୁ ଅନଫୋଲ୍ଡ କରନ୍ତୁ"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"ସ୍କ୍ରିନ ସ୍ୱିଚ କରିବେ?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"ଉଚ୍ଚ ରିଜୋଲ୍ୟୁସନ ପାଇଁ ପଛ କେମେରା ବ୍ୟବହାର କରନ୍ତୁ"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"ଉଚ୍ଚ ରିଜୋଲ୍ୟୁସନ ପାଇଁ ଫୋନକୁ ଫ୍ଲିପ କରନ୍ତୁ"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ଫୋଲ୍ଡ କରାଯାଇପାରୁଥିବା ଡିଭାଇସକୁ ଅନଫୋଲ୍ଡ କରାଯାଉଛି"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ଫୋଲ୍ଡ କରାଯାଇପାରୁଥିବା ଡିଭାଇସକୁ ଫ୍ଲିପ କରାଯାଉଛି"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> ବେଟେରୀ ଚାର୍ଜ ବାକି ଅଛି"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"ୱାର୍କ ପ୍ରୋଫାଇଲକୁ ସ୍ୱିଚ କରନ୍ତୁ"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"ବନ୍ଦ କରନ୍ତୁ"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"ଲକ ସ୍କ୍ରିନ ସେଟିଂସ"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"ୱାଇ-ଫାଇ ଉପଲବ୍ଧ ନାହିଁ"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"କେମେରାକୁ ବ୍ଲକ କରାଯାଇଛି"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"କେମେରା ଏବଂ ମାଇକ୍ରୋଫୋନକୁ ବ୍ଲକ କରାଯାଇଛି"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"ମାଇକ୍ରୋଫୋନକୁ ବ୍ଲକ କରାଯାଇଛି"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"ପ୍ରାୟୋରିଟି ମୋଡ ଚାଲୁ ଅଛି"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant ଆଟେନସନ ଚାଲୁ ଅଛି"</string>
</resources>
diff --git a/packages/SystemUI/res/values-or/tiles_states_strings.xml b/packages/SystemUI/res/values-or/tiles_states_strings.xml
index acaa3fb6f6a8..d362c65fa971 100644
--- a/packages/SystemUI/res/values-or/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-or/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"ବନ୍ଦ ଅଛି"</item>
<item msgid="5966994759929723339">"ଚାଲୁ ଅଛି"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"ଅନୁପଲବ୍ଧ"</item>
+ <item msgid="2478289035899842865">"ବନ୍ଦ ଅଛି"</item>
+ <item msgid="5137565285664080143">"ଚାଲୁ ଅଛି"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index fb4c7590b92d..236093010eea 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"ਸੂਚਨਾ ਸ਼ੇਡ।"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ।"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸੂਚਨਾ ਸ਼ੇਡ।"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">" ਲਾਕ ਸਕ੍ਰੀਨ।"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"ਕਾਰਜ-ਸਥਾਨ ਲਾਕ ਸਕ੍ਰੀਨ"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"ਬੰਦ ਕਰੋ"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"ਚਮਕ"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"ਰੰਗ ਪਲਟਨਾ"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"ਰੰਗ ਸੁਧਾਈ"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"ਫੌਂਟ ਦਾ ਆਕਾਰ"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"ਵਰਤੋਂਕਾਰਾਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"ਹੋ ਗਿਆ"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"ਬੰਦ ਕਰੋ"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"ਸੂਚਨਾਵਾਂ"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"ਕੀ-ਬੋਰਡ ਸ਼ਾਰਟਕੱਟ"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"ਕੀ-ਬੋਰਡ ਖਾਕਾ ਬਦਲੋ"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"ਲਿਖਤ ਕਲੀਅਰ ਕਰੋ"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ਸ਼ਾਰਟਕੱਟ"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"ਸ਼ਾਰਟਕੱਟਾਂ ਨੂੰ ਖੋਜੋ"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"ਕੋਈ ਸ਼ਾਰਟਕੱਟ ਨਹੀਂ ਮਿਲਿਆ"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"ਸਿਸਟਮ"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"ਇਨਪੁੱਟ"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"ਐਪਾਂ ਖੋਲ੍ਹੋ"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"ਮੌਜੂਦਾ ਐਪ"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"ਸੂਚਨਾ ਸ਼ੇਡ ਤੱਕ ਪਹੁੰਚ ਕਰੋ"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"ਪੂਰਾ ਸਕ੍ਰੀਨਸ਼ਾਟ ਲਓ"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"ਸਿਸਟਮ / ਐਪ ਸ਼ਾਰਟਕੱਟਾਂ ਦੀ ਸੂਚੀ ਤੱਕ ਪਹੁੰਚ ਕਰੋ"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"ਪਿੱਛੇ ਜਾਓ: ਪਿਛਲੀ ਸਥਿਤੀ \'ਤੇ ਵਾਪਸ ਜਾਓ (\'ਪਿੱਛੇ ਜਾਓ\' ਬਟਨ)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"ਹੋਮ ਸਕ੍ਰੀਨ ਤੱਕ ਪਹੁੰਚ ਕਰੋ"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"ਐਪਾਂ ਖੋਲ੍ਹੋ ਦੀ ਰੂਪ-ਰੇਖਾ"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"ਹਾਲ ਹੀ ਵਿੱਚ ਖੋਲ੍ਹੀਆਂ ਐਪਾਂ ਦੇਖੋ (ਅੱਗੇ)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"ਹਾਲ ਹੀ ਵਿੱਚ ਖੋਲ੍ਹੀਆਂ ਐਪਾਂ ਦੇਖੋ (ਪਿੱਛੇ)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"ਸਾਰੀਆਂ ਐਪਾਂ ਦੀ ਸੂਚੀ ਤੱਕ ਪਹੁੰਚ ਕਰੋ ਅਤੇ ਖੋਜੋ (ਜਿਵੇਂ ਕਿ, Search/ਲਾਂਚਰ)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"ਟਾਸਕਬਾਰ ਲੁਕਾਓ ਅਤੇ (ਮੁੜ)ਦਿਖਾਓ"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"ਸਿਸਟਮ ਸੈਟਿੰਗਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰੋ"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Google Assistant ਤੱਕ ਪਹੁੰਚ ਕਰੋ"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"ਲਾਕ ਸਕ੍ਰੀਨ"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"ਤੁਰੰਤ ਮੈਮੋ ਲਈ \'ਨੋਟ-ਕਥਨ\' ਐਪ ਨੂੰ ਉੱਪਰ ਵੱਲ ਖਿੱਚੋ"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"ਸਿਸਟਮ ਮਲਟੀਟਾਸਕਿੰਗ"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"RHS ਲਈ ਮੌਜੂਦਾ ਐਪ ਨਾਲ ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਵਿੱਚ ਦਾਖਲ ਹੋਵੋ"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"LHS ਲਈ ਮੌਜੂਦਾ ਐਪ ਨਾਲ ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਵਿੱਚ ਦਾਖਲ ਹੋਵੋ"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਤੋਂ ਪੂਰੀ ਸਕ੍ਰੀਨ ਵਿੱਚ ਸਵਿੱਚ ਕਰੋ"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਦੌਰਾਨ: ਇੱਕ ਐਪ ਨਾਲ ਦੂਜੀ ਐਪ ਬਦਲੋ"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"ਇਨਪੁੱਟ"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"ਇਨਪੁੱਟ ਭਾਸ਼ਾ ਨੂੰ ਸਵਿੱਚ ਕਰੋ (ਅਗਲੀ ਭਾਸ਼ਾ)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"ਇਨਪੁੱਟ ਭਾਸ਼ਾ ਨੂੰ ਸਵਿੱਚ ਕਰੋ (ਪਿਛਲੀ ਭਾਸ਼ਾ)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"ਇਮੋਜੀ ਤੱਕ ਪਹੁੰਚ ਕਰੋ"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"ਅਵਾਜ਼ੀ ਟਾਈਪਿੰਗ ਤੱਕ ਪਹੁੰਚ"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"ਐਪਲੀਕੇਸ਼ਨਾਂ"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"ਸਹਾਇਕ"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"ਬ੍ਰਾਊਜ਼ਰ"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"ਬ੍ਰਾਊਜ਼ਰ (ਪੂਰਵ-ਨਿਰਧਾਰਿਤ ਵਜੋਂ Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"ਸੰਪਰਕ"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"ਈਮੇਲ"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"ਈਮੇਲ (ਪੂਰਵ-ਨਿਰਧਾਰਿਤ ਵਜੋਂ Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"ਸੰਗੀਤ"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculator"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"ਨਕਸ਼ੇ"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"ਵੌਲਿਊਮ ਬਟਨ ਸ਼ਾਰਟਕੱਟ"</string>
<string name="battery" msgid="769686279459897127">"ਬੈਟਰੀ"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਿੰਗ"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"ਕੋਈ ਸਿਰਲੇਖ ਨਹੀਂ"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"ਸਟੈਂਡਬਾਈ"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"ਫ਼ੌਂਟ ਦਾ ਆਕਾਰ"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"ਛੋਟਾ ਕਰੋ"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"ਵੱਡਾ ਕਰੋ"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"ਵੱਡਦਰਸ਼ੀਕਰਨ Window"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"ਵੱਡਦਰਸ਼ੀਕਰਨ Window ਦੇ ਕੰਟਰੋਲ"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"ਜ਼ੂਮ ਵਧਾਓ"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"ਕੋਈ ਗੜਬੜ ਹੋ ਗਈ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"ਲੋਡ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"ਟੈਬਲੈੱਟ"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"ਤੁਹਾਡੇ ਮੀਡੀਆ ਨੂੰ ਕਾਸਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"<xliff:g id="APP_LABEL">%1$s</xliff:g> \'ਤੇ ਕਾਸਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ਅਕਿਰਿਆਸ਼ੀਲ, ਐਪ ਦੀ ਜਾਂਚ ਕਰੋ"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"ਨਹੀਂ ਮਿਲਿਆ"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"ਕੰਟਰੋਲ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"ਪ੍ਰਸਾਰਨ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"ਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"ਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ।"</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ਘੱਟੋ-ਘੱਟ 4 ਅੱਖਰ-ਚਿੰਨ੍ਹ ਵਰਤੋ"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16 ਤੋਂ ਘੱਟ ਅੱਖਰ-ਚਿੰਨ੍ਹ ਵਰਤੋ"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ਬਿਲਡ ਨੰਬਰ"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"ਬਿਲਡ ਨੰਬਰ ਨੂੰ ਕਲਿੱਪਬੋਰਡ \'ਤੇ ਕਾਪੀ ਕੀਤਾ ਗਿਆ।"</string>
<string name="basic_status" msgid="2315371112182658176">"ਗੱਲਬਾਤ ਖੋਲ੍ਹੋ"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• ਘੱਟੋ-ਘੱਟ ਇੱਕ ਡੀਵਾਈਸ ਉਪਲਬਧ ਹੈ"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"ਸ਼ਾਰਟਕੱਟ ਨੂੰ ਸਪਰਸ਼ ਕਰ ਕੇ ਰੱਖੋ"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"ਰੱਦ ਕਰੋ"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"ਹੁਣੇ ਫਲਿੱਪ ਕਰੋ"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"ਬਿਹਤਰ ਸੈਲਫ਼ੀ ਲਈ ਫ਼ੋਨ ਨੂੰ ਖੋਲ੍ਹੋ"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"ਕੀ ਬਿਹਤਰ ਸੈਲਫ਼ੀ ਲਈ ਅਗਲੀ ਡਿਸਪਲੇ \'ਤੇ ਫਲਿੱਪ ਕਰਨਾ ਹੈ?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"ਉੱਚ ਰੈਜ਼ੋਲਿਊਸ਼ਨ ਵਾਲੀ ਜ਼ਿਆਦਾ ਚੌੜੀ ਫ਼ੋਟੋ ਲਈ ਪਿਛਲੇ ਕੈਮਰੇ ਦੀ ਵਰਤੋਂ ਕਰੋ।"</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ਇਹ ਸਕ੍ਰੀਨ ਬੰਦ ਹੋ ਜਾਵੇਗੀ"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"ਹੁਣ ਸਕ੍ਰੀਨਾਂ ਨੂੰ ਸਵਿੱਚ ਕਰੋ"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"ਫ਼ੋਨ ਨੂੰ ਖੋਲ੍ਹੋ"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"ਕੀ ਸਕ੍ਰੀਨਾਂ ਨੂੰ ਸਵਿੱਚ ਕਰਨਾ ਹੈ?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"ਉੱਚ ਰੈਜ਼ੋਲਿਊਸ਼ਨ ਲਈ, ਪਿਛਲਾ ਕੈਮਰਾ ਵਰਤੋ"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"ਉੱਚ ਰੈਜ਼ੋਲਿਊਸ਼ਨ ਲਈ, ਫ਼ੋਨ ਨੂੰ ਫਲਿੱਪ ਕਰੋ"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ਮੋੜਨਯੋਗ ਡੀਵਾਈਸ ਨੂੰ ਖੋਲ੍ਹਿਆ ਜਾ ਰਿਹਾ ਹੈ"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ਮੋੜਨਯੋਗ ਡੀਵਾਈਸ ਨੂੰ ਆਲੇ-ਦੁਆਲੇ ਫਲਿੱਪ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> ਬੈਟਰੀ ਬਾਕੀ"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ \'ਤੇ ਜਾਓ"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"ਬੰਦ ਕਰੋ"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"ਲਾਕ ਸਕ੍ਰੀਨ ਸੈਟਿੰਗਾਂ"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"ਵਾਈ-ਫਾਈ ਉਪਲਬਧ ਨਹੀਂ"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"ਕੈਮਰਾ ਬਲਾਕ ਕੀਤਾ ਗਿਆ"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"ਕੈਮਰਾ ਅਤੇ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਬਲਾਕ ਕੀਤੇ ਗਏ"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਬਲਾਕ ਕੀਤਾ ਗਿਆ"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"ਤਰਜੀਹ ਮੋਡ ਚਾਲੂ ਹੈ"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant ਧਿਆਨ ਸੁਵਿਧਾ ਨੂੰ ਚਾਲੂ ਹੈ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pa/tiles_states_strings.xml b/packages/SystemUI/res/values-pa/tiles_states_strings.xml
index 9653b923224a..f249afb72b6d 100644
--- a/packages/SystemUI/res/values-pa/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pa/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"ਬੰਦ"</item>
<item msgid="5966994759929723339">"ਚਾਲੂ"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"ਉਪਲਬਧ ਨਹੀਂ"</item>
+ <item msgid="2478289035899842865">"ਬੰਦ"</item>
+ <item msgid="5137565285664080143">"ਚਾਲੂ"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index da2e56e261cd..18450ab36f63 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Obszar powiadomień."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Szybkie ustawienia."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Szybkie ustawienia i obszar powiadomień."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Ekran blokady."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ekran blokady wyświetlany podczas działania"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Zamknij"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Jasność"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Odwrócenie kolorów"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Korekcja kolorów"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Rozmiar czcionki"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Zarządzaj użytkownikami"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Gotowe"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Zamknij"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Powiadomienia"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Skróty klawiszowe"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Przełącz układ klawiatury"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Czyszczenie tekstu"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Skróty"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Wyszukiwanie skrótów"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nie znaleziono skrótów"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"System"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Wprowadzanie"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Otwieranie aplikacji"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Bieżąca aplikacja"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Otwieranie obszaru powiadomień"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Robienie pełnego zrzutu ekranu"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Otwieranie listy skrótów do systemu/aplikacji"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Wstecz: powrót do poprzedniego stanu (przycisk Wstecz)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Otwieranie ekranu głównego"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Przegląd otwartych aplikacji"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Przełączanie się między ostatnimi aplikacjami (do przodu)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Przełączanie się między ostatnimi aplikacjami (wstecz)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Otwieranie listy wszystkich aplikacji i wyszukiwanie (tj. wyszukiwarka/Launcher)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Ukrywanie i ponowne pokazywanie paska aplikacji"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Otwieranie ustawień systemu"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Otwieranie Asystenta Google"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Blokada ekranu"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Otwieranie aplikacji do notatek w przypadku szybkich notatek"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Wielozadaniowość w systemie"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Uruchamianie trybu podzielonego ekranu z bieżącą aplikacją po prawej"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Uruchamianie trybu podzielonego ekranu z bieżącą aplikacją po lewej"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Przełączanie podzielonego ekranu na pełny ekran"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Podczas podzielonego ekranu: zastępowanie aplikacji"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Wprowadzanie"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Przełączanie języka wprowadzania (następny język)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Przełączanie języka wprowadzania (poprzedni język)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Otwieranie emotikonów"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Otwieranie pisania głosowego"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Aplikacje"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Pomoc"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Przeglądarka"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Przeglądarka (domyślnie Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Kontakty"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"E-mail"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"E-mail (domyślnie Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Muzyka"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalendarz"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kalkulator"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Mapy"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Nie przeszkadzać"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Wł./wył. przyciskami głośności"</string>
<string name="battery" msgid="769686279459897127">"Bateria"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"nagrywanie ekranu"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Bez tytułu"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Tryb gotowości"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Rozmiar czcionki"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Pomniejsz"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Powiększ"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Okno powiększenia"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Elementy sterujące okna powiększenia"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Powiększ"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"Coś poszło nie tak. Spróbuj ponownie."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Wczytuję"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"tablet"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"Przesyłanie multimediów"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"Przesyłanie treści z aplikacji <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Nieaktywny, sprawdź aplikację"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nie znaleziono"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Element jest niedostępny"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Nie można przesyłać"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Nie można zapisać. Spróbuj ponownie."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Nie można zapisać."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Wpisz co najmniej 4 znaki"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Wpisz mniej niż 16 znaków"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numer kompilacji"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Numer kompilacji został skopiowany do schowka."</string>
<string name="basic_status" msgid="2315371112182658176">"Otwarta rozmowa"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Dostępne jest co najmniej 1 urządzenie."</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Skrót – naciśnij i przytrzymaj"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Anuluj"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Przełącz teraz"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Rozłóż telefon, aby uzyskać lepszej jakości selfie"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Przełączyć na przedni wyświetlacz?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Użyj tylnego aparatu, aby zrobić szersze zdjęcie o większej rozdzielczości."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"* Ten ekran się wyłączy"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Przełącz ekrany teraz"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Otwieranie telefonu"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Przełączyć ekrany?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Użyj tylnego aparatu, aby uzyskać wyższą rozdzielczość"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Odwróć telefon, aby uzyskać wyższą rozdzielczość"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Składane urządzenie jest rozkładane"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Składane urządzenie jest obracane"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Pozostało <xliff:g id="PERCENTAGE">%s</xliff:g> baterii"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Przełącz na profil służbowy"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Zamknij"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Ustawienia ekranu blokady"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Sieć Wi-Fi jest niedostępna"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera jest zablokowana"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera i mikrofon są zablokowane"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon jest zablokowany"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Tryb priorytetowy jest włączony"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Asystent jest aktywny"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pl/tiles_states_strings.xml b/packages/SystemUI/res/values-pl/tiles_states_strings.xml
index 50650986c517..c73cbed76946 100644
--- a/packages/SystemUI/res/values-pl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pl/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Wyłączono"</item>
<item msgid="5966994759929723339">"Włączono"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Brak dostępu"</item>
+ <item msgid="2478289035899842865">"Wyłączono"</item>
+ <item msgid="5137565285664080143">"Włączono"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index e7edaae9ca85..8add565ce87d 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Aba de notificações."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Configurações rápidas."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Configurações rápidas e aba de notificações."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Tela de bloqueio."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Tela de bloqueio de trabalho"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Fechar"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Brilho"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inversão de cores"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Correção de cor"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Tamanho da fonte"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Gerenciar usuários"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Concluído"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Fechar"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notificações"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Atalhos do teclado"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Alterar layout do teclado"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Apagar texto"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Atalhos"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Atalhos de pesquisa"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nenhum atalho encontrado"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistema"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Entrada"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Apps abertos"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"App atual"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Acessar a aba de notificações"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Capturar toda a tela"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Acessar lista de atalhos do sistema / de apps"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Voltar ao estado anterior (botão \"Voltar\")"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Acessar a tela inicial"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Visão geral dos apps abertos"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Percorrer apps recentes (avançar)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Percorrer apps recentes (voltar)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Acessar lista de todos os apps e pesquisa (por exemplo, Pesquisa/Tela de início)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Ocultar e mostrar a barra de tarefas"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Acessar configurações do sistema"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Acessar o Google Assistente"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Tela de bloqueio"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Fazer uma anotação rápida no app Notes"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitarefa do sistema"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Usar a tela dividida com o app atual à direita"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Usar a tela dividida com o app atual à esquerda"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Mudar de tela dividida para tela cheia"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Com a tela dividida: substituir um app por outro"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Entrada"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Trocar o idioma de entrada (próximo)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Trocar o idioma de entrada (anterior)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Acessar emojis"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Acessar a digitação por voz"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Aplicativos"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Assistente"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Navegador"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Navegador (Chrome por padrão)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Contatos"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"E-mail"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"E-mail (Gmail por padrão)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Música"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Agenda"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculadora"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Mapas"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Não perturbe"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Atalho de botões de volume"</string>
<string name="battery" msgid="769686279459897127">"Bateria"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"gravação de tela"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sem título"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Em espera"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Tamanho da fonte"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Diminuir"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Aumentar"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Janela de ampliação"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Controles da janela de ampliação"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Aumentar zoom"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Não foi possível fazer a transmissão"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Falha ao salvar. Tente de novo."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Falha ao salvar."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Use pelo menos 4 caracteres"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Use menos de 16 caracteres"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número da versão"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Número da versão copiado para a área de transferência."</string>
<string name="basic_status" msgid="2315371112182658176">"Conversa aberta"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Pelo menos um dispositivo está disponível"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Toque e pressione o atalho"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Cancelar"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Virar agora"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Abra o smartphone para tirar uma selfie melhor"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Usar o display frontal para tirar uma selfie melhor?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Use a câmera traseira para tirar uma foto mais ampla e com maior resolução."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Esta tela vai ser desativada"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Trocar de tela agora"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Abra o smartphone"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Trocar de tela?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Para uma resolução maior, use a câmera traseira"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Para uma resolução maior, vire o smartphone"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo dobrável sendo aberto"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo dobrável sendo virado"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Bateria restante: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Alternar para o perfil de trabalho"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Fechar"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Configurações de tela de bloqueio"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi indisponível"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Câmara bloqueada"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Câmera e microfone bloqueados"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microfone bloqueado"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Modo de prioridade ativado"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Atenção do Assistente ativada"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml b/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml
index ebe67d86ca23..28c07f40b6b9 100644
--- a/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Desativado"</item>
<item msgid="5966994759929723339">"Ativado"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Indisponível"</item>
+ <item msgid="2478289035899842865">"Desativado"</item>
+ <item msgid="5137565285664080143">"Ativado"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 4ec30804e524..f8a684c626e2 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Painel de notificações."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Definições rápidas."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Definições rápidas e painel de notificações."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Ecrã de bloqueio."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ecrã de bloqueio de trabalho"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Fechar"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Brilho"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inversão de cores"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Correção da cor"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Tamanho do tipo de letra"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Gerir utilizadores"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Concluído"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Fechar"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notificações"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Atalhos de teclado"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Alterar esquema de teclado"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Limpar texto"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Atalhos"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Pesquise atalhos"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nenhum atalho encontrado"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistema"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Entrada"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Apps abertas"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"App atual"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Aceda ao painel de notificações"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Faça uma captura de ecrã completa"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Aceda à lista dos atalhos de apps/sistema"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Anterior: volte ao estado anterior (botão anterior)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Aceda ao ecrã principal"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Vista geral das apps abertas"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Percorra as apps recentes (para a frente)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Percorra as apps recentes (para trás)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Aceda à lista de todas as apps e pesquise (por ex., Pesquisa/Launcher)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Oculte e volte a apresentar a barra de tarefas"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Aceda às definições do sistema"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Aceda ao Assistente Google"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Ecrã de bloqueio"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Inicie a app Notas para criar uma nota rápida"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Execução de várias tarefas em simultâneo no sistema"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Aceda ao ecrã dividido com a app atual para RHS"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Aceda ao ecrã dividido com a app atual para LHS"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Mude do ecrã dividido para o ecrã inteiro"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Durante o ecrã dividido: substitua uma app por outra"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Entrada"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Mude de idioma de entrada (idioma seguinte)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Mude de idioma de entrada (idioma anterior)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Aceda a emojis"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Aceda à digitação por voz"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Apps"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Assistência"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Navegador"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Navegador (Chrome como predefinição)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Contactos"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Email"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Email (Gmail como predefinição)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Música"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendário"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculadora"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Não incomodar"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Atalho dos botões de volume"</string>
<string name="battery" msgid="769686279459897127">"Bateria"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"gravação de ecrã"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sem título"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Modo de espera"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Tamanho do tipo de letra"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Diminuir"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Aumentar"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Janela de ampliação"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Controlos da janela de ampliação"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Aumentar zoom"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Não é possível transmitir"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Não é possível guardar. Tente novamente."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Não é possível guardar."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Use, pelo menos, 4 carateres"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Use menos de 16 carateres"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número da compilação"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Número da compilação copiado para a área de transferência."</string>
<string name="basic_status" msgid="2315371112182658176">"Abrir conversa"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Está disponível, pelo menos, um dispositivo"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Toque sem soltar no atalho"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Cancelar"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Inverter agora"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Desdobre o telemóvel para uma selfie melhor"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Inverter para ecrã frontal para uma selfie melhor?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Use a câmara traseira para uma foto mais ampla com uma resolução superior."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Este ecrã vai ser desligado"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Mudar de ecrã agora"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Desdobre o telemóvel"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Mudar de ecrã?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Para uma resolução superior, use a câmara traseira"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Para uma resolução superior, inverta o telemóvel"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo dobrável a ser desdobrado"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo dobrável a ser virado ao contrário"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> de bateria restante"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Mudar para perfil de trabalho"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Fechar"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Definições do ecrã de bloqueio"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi indisponível"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Câmara bloqueada"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Câmara e microfone bloqueados"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microfone bloqueado"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Modo Prioridade ativado"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Atenção do Assistente ativada"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/tiles_states_strings.xml b/packages/SystemUI/res/values-pt-rPT/tiles_states_strings.xml
index bda7473ba15b..b58b8488a3e4 100644
--- a/packages/SystemUI/res/values-pt-rPT/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Desativado"</item>
<item msgid="5966994759929723339">"Ativado"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Indisponível"</item>
+ <item msgid="2478289035899842865">"Desativado"</item>
+ <item msgid="5137565285664080143">"Ativado"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index e7edaae9ca85..8add565ce87d 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Aba de notificações."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Configurações rápidas."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Configurações rápidas e aba de notificações."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Tela de bloqueio."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Tela de bloqueio de trabalho"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Fechar"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Brilho"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inversão de cores"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Correção de cor"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Tamanho da fonte"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Gerenciar usuários"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Concluído"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Fechar"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notificações"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Atalhos do teclado"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Alterar layout do teclado"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Apagar texto"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Atalhos"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Atalhos de pesquisa"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nenhum atalho encontrado"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistema"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Entrada"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Apps abertos"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"App atual"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Acessar a aba de notificações"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Capturar toda a tela"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Acessar lista de atalhos do sistema / de apps"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Voltar ao estado anterior (botão \"Voltar\")"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Acessar a tela inicial"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Visão geral dos apps abertos"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Percorrer apps recentes (avançar)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Percorrer apps recentes (voltar)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Acessar lista de todos os apps e pesquisa (por exemplo, Pesquisa/Tela de início)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Ocultar e mostrar a barra de tarefas"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Acessar configurações do sistema"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Acessar o Google Assistente"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Tela de bloqueio"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Fazer uma anotação rápida no app Notes"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitarefa do sistema"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Usar a tela dividida com o app atual à direita"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Usar a tela dividida com o app atual à esquerda"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Mudar de tela dividida para tela cheia"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Com a tela dividida: substituir um app por outro"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Entrada"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Trocar o idioma de entrada (próximo)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Trocar o idioma de entrada (anterior)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Acessar emojis"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Acessar a digitação por voz"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Aplicativos"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Assistente"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Navegador"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Navegador (Chrome por padrão)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Contatos"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"E-mail"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"E-mail (Gmail por padrão)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Música"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Agenda"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculadora"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Mapas"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Não perturbe"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Atalho de botões de volume"</string>
<string name="battery" msgid="769686279459897127">"Bateria"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"gravação de tela"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sem título"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Em espera"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Tamanho da fonte"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Diminuir"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Aumentar"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Janela de ampliação"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Controles da janela de ampliação"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Aumentar zoom"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Não foi possível fazer a transmissão"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Falha ao salvar. Tente de novo."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Falha ao salvar."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Use pelo menos 4 caracteres"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Use menos de 16 caracteres"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número da versão"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Número da versão copiado para a área de transferência."</string>
<string name="basic_status" msgid="2315371112182658176">"Conversa aberta"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Pelo menos um dispositivo está disponível"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Toque e pressione o atalho"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Cancelar"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Virar agora"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Abra o smartphone para tirar uma selfie melhor"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Usar o display frontal para tirar uma selfie melhor?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Use a câmera traseira para tirar uma foto mais ampla e com maior resolução."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Esta tela vai ser desativada"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Trocar de tela agora"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Abra o smartphone"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Trocar de tela?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Para uma resolução maior, use a câmera traseira"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Para uma resolução maior, vire o smartphone"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo dobrável sendo aberto"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo dobrável sendo virado"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Bateria restante: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Alternar para o perfil de trabalho"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Fechar"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Configurações de tela de bloqueio"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi indisponível"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Câmara bloqueada"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Câmera e microfone bloqueados"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microfone bloqueado"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Modo de prioridade ativado"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Atenção do Assistente ativada"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt/tiles_states_strings.xml b/packages/SystemUI/res/values-pt/tiles_states_strings.xml
index ebe67d86ca23..28c07f40b6b9 100644
--- a/packages/SystemUI/res/values-pt/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pt/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Desativado"</item>
<item msgid="5966994759929723339">"Ativado"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Indisponível"</item>
+ <item msgid="2478289035899842865">"Desativado"</item>
+ <item msgid="5137565285664080143">"Ativado"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 7526cba2a8a3..a4698d600582 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Fereastră pentru notificări."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Setări rapide."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Fereastră de Setări rapide și notificări."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Ecranul de blocare."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ecran de blocare pentru serviciu"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Închide"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Luminozitate"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inversarea culorilor"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Corecția culorii"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Dimensiunea fontului"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Gestionează utilizatorii"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Terminat"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Închide"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notificări"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Comenzi rapide de la tastatură"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Schimbă aspectul tastaturii"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Șterge textul"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Comenzi rapide"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Caută comenzi rapide"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nu există comenzi rapide"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistem"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Introducere"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Aplicații deschise"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Aplicația actuală"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Accesează fereastra de notificări"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Fă o captură de ecran completă"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Accesează lista comenzilor rapide pentru sistem / aplicații"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Înapoi: revino la starea anterioară (butonul înapoi)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Accesează ecranul de pornire"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Prezentare generală a aplicațiilor deschise"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Parcurge aplicațiile recente (înainte)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Parcurge aplicațiile recente (înapoi)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Accesează lista tuturor aplicațiilor și caută (Căutare / Lansator)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Ascunde și reafișează bara de activități"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Accesează setările de sistem"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Accesează Asistentul Google"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Ecranul de blocare"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Accesează aplicația Note pentru notițe rapide"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitasking pe sistem"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Accesează ecranul împărțit cu aplicația actuală în dreapta"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Accesează ecranul împărțit cu aplicația actuală în stânga"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Comută de la ecranul împărțit la ecranul complet"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"În modul ecran împărțit: înlocuiește o aplicație cu alta"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Introducere"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Schimbă limba de introducere a textului (limba următoare)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Schimbă limba de introducere a textului (limba anterioară)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Accesează emoji"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Accesează tastarea vocală"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Aplicații"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Asistent"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Browser"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Browser (Chrome este setat ca prestabilit)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Agendă"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"E-mail"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"E-mail (aplicația Gmail este setată ca prestabilită)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Muzică"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculator"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Nu deranja"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Comandă rapidă din butoanele de volum"</string>
<string name="battery" msgid="769686279459897127">"Baterie"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"înregistrare de ecran"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Fără titlu"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Standby"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Dimensiunea fontului"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Micșorează"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Mărește"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Fereastra de mărire"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Comenzi pentru fereastra de mărire"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Mărește"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"A apărut o eroare. Încearcă din nou."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Se încarcă"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"tabletă"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"Se proiectează conținutul media"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"Se proiectează <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactiv, verifică aplicația"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nu s-a găsit"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Comanda este indisponibilă"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Nu se poate transmite"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Nu se poate salva. Încearcă din nou."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Nu se poate salva."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Folosește minimum 4 caractere."</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Folosește maximum 16 caractere"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numărul versiunii"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Numărul versiunii s-a copiat în clipboard."</string>
<string name="basic_status" msgid="2315371112182658176">"Deschide conversația"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Este disponibil cel puțin un dispozitiv"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Atinge lung comanda rapidă"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Anulează"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Întoarce-l acum"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Desfă telefonul pentru un selfie mai bun"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Comuți la ecranul frontal pentru un selfie mai bun?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Folosește camera posterioară pentru o fotografie mai lată, cu rezoluție mai mare."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Acest ecran se va dezactiva"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Schimbă ecranul acum"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Deschide telefonul"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Schimbi ecranul?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Pentru o rezoluție mai mare, folosește camera foto posterioară"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Pentru o rezoluție mai mare, deschide telefonul"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispozitiv pliabil care este desfăcut"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispozitiv pliabil care este întors"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> baterie rămasă"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Comută la profilul de serviciu"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Închide"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Setările ecranului de blocare"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Conexiune Wi-Fi indisponibilă"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Camera foto a fost blocată"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Camera foto și microfonul sunt blocate"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microfonul a fost blocat"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Modul Cu prioritate este activat"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Asistentul este atent"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ro/tiles_states_strings.xml b/packages/SystemUI/res/values-ro/tiles_states_strings.xml
index 7b7bb3ac11d8..5a5eb9f6788c 100644
--- a/packages/SystemUI/res/values-ro/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ro/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Dezactivat"</item>
<item msgid="5966994759929723339">"Activat"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Indisponibil"</item>
+ <item msgid="2478289035899842865">"Dezactivat"</item>
+ <item msgid="5137565285664080143">"Activat"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 57aef617f479..32a784c94b8c 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Панель уведомлений"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Быстрые настройки"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Быстрые настройки и панель уведомлений."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Экран блокировки."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Заблокировано"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Закрыть"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Яркость"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Инверсия цветов"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Коррекция цвета"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Размер шрифта"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Управление пользователями"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Готово"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Закрыть"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Уведомления"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Быстрые клавиши"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Переключение раскладки"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Очистить строку поиска"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Сочетания клавиш"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Поиск сочетаний клавиш"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Нет сочетаний клавиш."</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Система"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Ввод"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Запущенные приложения"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Это приложение"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Показать панель уведомлений"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Сделать скриншот всего экрана"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Открыть список сочетаний клавиш для системы и приложений"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Возврат к предыдущему состоянию (кнопка \"Назад\")"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Открыть главный экран"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Открыть список запущенных приложений"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Просмотреть недавние приложения (в обычном порядке)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Просмотреть недавние приложения (в обратном порядке)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Открыть список всех приложений и результатов поиска (Поиск/Панель запуска)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Скрыть/показать панель задач"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Открыть настройки системы"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Запустить Google Ассистента"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Заблокировать экран"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Создать быструю заметку"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Режим многозадачности"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Включить разделение экрана с текущим приложением справа"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Включить разделение экрана с текущим приложением слева"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Переключиться из режима разделения экрана в полноэкранный режим"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"В режиме разделения экрана заменить одно приложение другим"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Ввод"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Переключиться на следующий язык ввода"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Переключиться на предыдущий язык ввода"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Открыть список эмодзи"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Активировать голосовой ввод"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Приложения"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Помощник"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Браузер"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Браузер (по умолчанию Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Контакты"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Эл. почта"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Электронная почта (по умолчанию Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Музыка"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Календарь"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Калькулятор"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Карты"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Не беспокоить"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Кнопки регулировки громкости"</string>
<string name="battery" msgid="769686279459897127">"Батарея"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"запись экрана"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Без названия"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Переход в режим ожидания"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Размер шрифта"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Уменьшить"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Увеличить"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Окно увеличения"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Настройки окна увеличения"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Увеличить"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Не удалось запустить трансляцию"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Не удалось сохранить. Повторите попытку."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Не удалось сохранить."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Минимальное количество символов – 4"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Максимальное количество символов – 16"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Номер сборки"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Номер сборки скопирован в буфер обмена."</string>
<string name="basic_status" msgid="2315371112182658176">"Открытый чат"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Доступно хотя бы одно устройство."</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Нажмите и удерживайте ярлык"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Отмена"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Перевернуть сейчас"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Разложите телефон, чтобы селфи получилось лучше"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Перейти на передний экран?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Используйте основную камеру с широкоугольным объективом и высоким разрешением."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Этот экран отключится"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Переключиться на другой экран"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Разложите телефон"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Переключиться на другой экран?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Используйте основную камеру, чтобы делать снимки с более высоким разрешением."</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Переверните телефон и используйте основную камеру, чтобы делать снимки с более высоким разрешением."</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Складное устройство в разложенном виде"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Перевернутое складное устройство"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Уровень заряда батареи: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Перейти в рабочий профиль"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Закрыть"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Настройки блокировки экрана"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Функция Wi-Fi недоступна"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камера заблокирована"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камера и микрофон заблокированы"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Микрофон заблокирован"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Режим \"Только важные\" включен"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Ассистент готов слушать"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ru/tiles_states_strings.xml b/packages/SystemUI/res/values-ru/tiles_states_strings.xml
index 6255bd8ee26d..cd140791bbd5 100644
--- a/packages/SystemUI/res/values-ru/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ru/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Отключено"</item>
<item msgid="5966994759929723339">"Включено"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Недоступно"</item>
+ <item msgid="2478289035899842865">"Выключено"</item>
+ <item msgid="5137565285664080143">"Включено"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 8ca011d11cb2..8bb334ee1d43 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"දැනුම්දීම් ආවරණය."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ක්ෂණික සැකසීම්."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ඉක්මන් සැකසීම් සහ දැනුම්දීම් ඡායිතය."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"අගුළු තිරය."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"කාර්යාල අගුලු තිරය"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"වසන්න"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"දීප්තිමත් බව"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"වර්ණ අපවර්තනය"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"වර්ණ නිවැරදි කිරීම"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"අකුරු විශාලත්වය"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"පරිශීලකයන් කළමනාකරණය කරන්න"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"නිමයි"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"වසන්න"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"දැනුම්දීම්"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"යතුරු පුවරු කෙටිමං"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"යතුරුපුවරු පිරිසැලසුම මාරු කරන්න"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"පෙළ හිස් කරන්න"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"කෙටිමං"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"කෙටිමං සොයන්න"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"කෙටිමං හමු නොවුණි"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"පද්ධතිය"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"ආදානය"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"විවෘත යෙදුම්"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"වත්මන් යෙදුම"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"දැනුම්දීම් සෙවනට ප්‍රවේශ වන්න"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"පූර්ණ තිර රුවක් ගන්න"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"පද්ධති / යෙදුම් කෙටිමං ලැයිස්තුවට ප්‍රවේශ වන්න"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"ආපසු: පෙර තත්ත්වයට ආපසු යන්න (ආපසු බොත්තම)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"මුල් තිරයට ප්‍රවේශ වන්න"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"විවෘත යෙදුම් පිළිබඳ දළ විශ්ලේෂණය"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"මෑත යෙදුම් හරහා කාලක්‍රම කරන්න (ඉදිරියට)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"මෑත යෙදුම් හරහා කාලක්‍රම කරන්න (ආපසු)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"සියලු යෙදුම් සහ සෙවීම් ලැයිස්තුවට ප්‍රවේශය (එනම් සෙවීම/දියත් කිරීම)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"කාර්ය තීරුව සඟවන්න සහ (යළි) පෙන්වන්න"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"පද්ධති සැකසීම් වෙත ප්‍රවේශ වන්න"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Google සහායක වෙත ප්‍රවේශ වන්න"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"තිරය අගුළු දමන්න"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"ඉක්මන් සිහිපත සඳහා සටහන් යෙදුම අදින්න"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"පද්ධති බහු කාර්ය"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"RHS වෙත වත්මන් යෙදුම සමග බෙදුම් තිරයට ඇතුළු වන්න"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"LHS වෙත වත්මන් යෙදුම සමග බෙදුම් තිරයට ඇතුළු වන්න"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"බෙදුම් තිරයේ සිට පූර්ණ තිරයට මාරු වන්න"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"බෙදුම් තිරය අතරතුර: යෙදුමක් එකකින් තවත් එකක් ප්‍රතිස්ථාපනය කරන්න"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"ආදානය"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"ආදාන භාෂාව මාරු කරන්න (මීළඟ භාෂාව)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"ආදාන භාෂාව මාරු කරන්න (පෙර භාෂාව)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"ඉමොජි වෙත ප්‍රවේශ වන්න"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"හඬ ටයිප් කිරීමට ප්‍රවේශ වන්න"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"යෙදුම්"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"සහාය"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"බ්‍රවුසරය"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"බ්‍රව්සරය (Chrome පෙරනිමිය ලෙස)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"සම්බන්ධතා"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"ඊ-තැපෑල"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"ඉ-තැපෑල (Gmail පෙරනිමිය ලෙස)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"සංගීතය"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"දින දර්ශනය"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"ගණකය"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"සිතියම්"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"බාධා නොකරන්න"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"හඩ පරිමා බොත්තම් කෙටිමග"</string>
<string name="battery" msgid="769686279459897127">"බැටරිය"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"තිර පටිගත කිරීම"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"මාතෘකාවක් නැත"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"පොරොත්තු"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"අකුරු විශාලත්වය"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"වඩා කුඩා කරන්න"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"වඩා විශාල කරන්න"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"විශාලන කවුළුව"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"විශාලනය කිරීමේ කවුළු පාලන"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"විශාලනය වැඩි කරන්න"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"යම් දෙයක් වැරදිණි. නැවත උත්සාහ කරන්න."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"පූරණය වේ"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"ටැබ්ලටය"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"ඔබේ මාධ්‍ය විකාශය කිරීම"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"<xliff:g id="APP_LABEL">%1$s</xliff:g> විකාශය කරමින්"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"අක්‍රියයි, යෙදුම පරීක්ෂා කරන්න"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"හමු නොවිණි"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"පාලනය ලබා ගත නොහැකිය"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"විකාශනය කළ නොහැකිය"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"සුරැකිය නොහැකිය. නැවත උත්සාහ කරන්න."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"සුරැකිය නොහැකිය."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"අවම වශයෙන් අනුලකුණු 4ක් භාවිතා කරන්න"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"අනුලකුණු 16කට වඩා අඩුවෙන් භාවිතා කරන්න"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"නිමැවුම් අංකය"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"නිමැවුම් අංකය පසුරු පුවරුවට පිටපත් කරන ලදි."</string>
<string name="basic_status" msgid="2315371112182658176">"සංවාදය විවෘත කරන්න"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• අවම වශයෙන් එක උපාංගයක් ලැබේ"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"ස්පර්ශ කර අල්ලා සිටීමේ කෙටිමඟ"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"අවලංගු කරන්න"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"දැන් පෙරළන්න"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"වඩා හොඳ සෙල්ෆියක් සඳහා දුරකථනය දිගහරින්න"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"වඩා හොඳ සෙල්ෆියක් සඳහා ඉදිරිපස සංදර්ශකයට පෙරළන්න ද?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"ඉහළ විභේදන සහිත පුළුල් ඡායාරූපයක් සඳහා පසුපසට මුහුණලා ඇති කැමරාව භාවිතා කරන්න."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ මෙම තිරය ක්‍රියා විරහිත වනු ඇත"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"දැන් තිර මාරු කරන්න"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"දුරකථනය දිගහරින්න"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"තිර මාරු කරන්න ද?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"ඉහළ විභේදනය සඳහා, පසුපස කැමරාව භාවිතා කරන්න"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"ඉහළ විභේදනය සඳහා, දුරකථනය හරවන්න"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"දිග හැරෙමින් පවතින නැමිය හැකි උපාංගය"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"වටා පෙරළෙමින් තිබෙන නැමිය හැකි උපාංගය"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> බැටරිය ඉතිරිව ඇත"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"කාර්යාල පැතිකඩ වෙත මාරු වන්න"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"වසන්න"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"අගුළු තිර සැකසීම්"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi ලද නොහැක"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"කැමරාව අවහිරයි"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"කැමරාව සහ මයික්‍රොෆෝනය අවහිරයි"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"මයික්‍රොෆෝනය අවහිරයි"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"ප්‍රමුඛතා මාදිලිය සක්‍රීයයි"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"සහයක අවධානය යොමු කරයි"</string>
</resources>
diff --git a/packages/SystemUI/res/values-si/tiles_states_strings.xml b/packages/SystemUI/res/values-si/tiles_states_strings.xml
index 327e0b92c967..fcd768bfc4e3 100644
--- a/packages/SystemUI/res/values-si/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-si/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"ක්‍රියාවිරහිතයි"</item>
<item msgid="5966994759929723339">"ක්‍රියාත්මකයි"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"නොමැත"</item>
+ <item msgid="2478289035899842865">"ක්‍රියාවිරහිතයි"</item>
+ <item msgid="5137565285664080143">"ක්‍රියාත්මකයි"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index fd67778f0b65..f4181540e7fb 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Panel upozornení."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Rýchle nastavenia."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Rýchle nastavenia a panel upozornení"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Uzamknutá obrazovka"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Uzamknutá obrazovka pracovného profilu"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Zavrieť"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Jas"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inverzia farieb"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Úprava farieb"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Veľkosť písma"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Spravovať používateľov"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Hotovo"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Zavrieť"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Upozornenia"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Klávesové skratky"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Prepnúť rozloženie klávesnice"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Vymazať text"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Skratky"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Hľadajte skratky"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nenašli sa žiadne skratky"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Systém"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Vstup"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Otvorenie apl."</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Aktuálna aplik."</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Prístup k panelu upozornení"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Vytvorenie snímky celej obrazovky"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Zoznam prístupov systému a odkazy do aplikácií"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Späť: prechod na predchádzajúci stav (tlačidlo Späť)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Prístup k ploche"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Prehľad otvorených aplikácií"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Cyklické prechádzanie po nedávnych aplikáciách (dopredu)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Cyklické prechádzanie po nedávnych aplikáciách (dozadu)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Zoznam prístupov všet. aplik. a vyhľad. (teda Vyhľadávanie a Launcher)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Skrytie a opätovné zobrazenie panela úloh"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Prístup k nastaveniam systému"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Prístup k Asistentovi Google"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Uzamknutá obrazovka"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Otvorenie aplikácie Poznámky na rýchle zapisovanie"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitasking systému"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Rozdelenie obrazovky s aktuálnou aplikáciou vpravo"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Rozdelenie obrazovky s aktuálnou aplikáciou vľavo"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Prepnutie rozdelenej obrazovky na celú"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Počas rozdelenej obrazovky: nahradenie aplikácie inou"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Vstup"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Prepnutie vstupného jazyka (ďalší jazyk)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Prepnutie vstupného jazyka (predchádzajúci jazyk)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Prístup k emodži"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Prístup k hlasovému zadávaniu"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Aplikácie"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Pomocná aplikácia"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Prehliadač"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Prehliadač (Chrome ako predvolený)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Kontakty"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"E-mail"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Pošta (Gmail ako predvolená služba)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Hudba"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalendár"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kalkulačka"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Mapy"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Režim bez vyrušení"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Skratka tlačidiel hlasitosti"</string>
<string name="battery" msgid="769686279459897127">"Batéria"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"nahrávanie obrazovky"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Bez názvu"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Pohotovostný režim"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Veľkosť písma"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Zmenšiť"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Zväčšiť"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Okno priblíženia"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Ovládacie prvky okna priblíženia"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Priblížiť"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Nedá sa vysielať"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Nedá sa uložiť. Skúste to znova."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Nedá sa uložiť."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Použite aspoň štyri znaky"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Použite menej než 16 znakov"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Číslo zostavy"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Číslo zostavy bolo skopírované do schránky."</string>
<string name="basic_status" msgid="2315371112182658176">"Otvorená konverzácia"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• K dispozícii je minimálne jedno zariadenie"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Pridržte skratku"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Zrušiť"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Otočiť"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Ak chcete lepšie selfie, rozložte telefón"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Otočiť na prednú obrazovku pre lepšie selfie?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Pomocou zadného fotoaparátu vytvorte širšiu fotku s vyšším rozlíšením."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Táto obrazovka sa vypne"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Prepnite obrazovky"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Rozloženie telefónu"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Chcete prepnúť obrazovky?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Ak chcete vyššie rozlíšenie, použite zadnú kameru"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Ak chcete vyššie rozlíšenie, prevráťte telefón"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Rozloženie skladacieho zariadenia"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Prevrátenie skladacieho zariadenia"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Zostáva <xliff:g id="PERCENTAGE">%s</xliff:g> batérie"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Prepnúť na pracovný profil"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Zavrieť"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Nastavenia uzamknutej obrazovky"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi‑Fi nie je k dispozícii"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera je blokovaná"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera a mikrofón sú blokované"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofón je blokovaný"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Režim priority je zapnutý"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Pozornosť Asistenta je zapnutá"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sk/tiles_states_strings.xml b/packages/SystemUI/res/values-sk/tiles_states_strings.xml
index 3cbde1c9574c..660f85d365e2 100644
--- a/packages/SystemUI/res/values-sk/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sk/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Vypnuté"</item>
<item msgid="5966994759929723339">"Zapnuté"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Nedostupné"</item>
+ <item msgid="2478289035899842865">"Vypnuté"</item>
+ <item msgid="5137565285664080143">"Zapnuté"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 6122f3891b73..3bc835165fde 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -188,8 +188,8 @@
<string name="accessibility_battery_level" msgid="5143715405241138822">"Baterija <xliff:g id="NUMBER">%d</xliff:g> odstotkov."</string>
<string name="accessibility_battery_level_with_estimate" msgid="6548654589315074529">"Baterija je napolnjena na <xliff:g id="PERCENTAGE">%1$d</xliff:g> %% – <xliff:g id="TIME">%2$s</xliff:g>."</string>
<string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Baterija se polni, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> odstotkov."</string>
- <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"Baterija je napolnjena na <xliff:g id="PERCENTAGE">%d</xliff:g> %% – zaradi zaščite baterije je polnjenje začasno zaustavljeno."</string>
- <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"Baterija je napolnjena na <xliff:g id="PERCENTAGE">%1$d</xliff:g> %% – <xliff:g id="TIME">%2$s</xliff:g> je zaradi zaščite baterije polnjenje začasno zaustavljeno."</string>
+ <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"Baterija je napolnjena na <xliff:g id="PERCENTAGE">%d</xliff:g> odstotkov. Zaradi zaščite baterije je polnjenje začasno zaustavljeno."</string>
+ <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"Baterija je napolnjena na <xliff:g id="PERCENTAGE">%1$d</xliff:g> odstotkov – <xliff:g id="TIME">%2$s</xliff:g>. Zaradi zaščite baterije je polnjenje začasno zaustavljeno."</string>
<string name="accessibility_overflow_action" msgid="8555835828182509104">"Prikaži vsa obvestila"</string>
<string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter omogočen."</string>
<string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Zvonjenje z vibriranjem."</string>
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Zaslon z obvestili."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Hitre nastavitve."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Hitre nastavitve in zaslon z obvestili"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Zaklenjen zaslon"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Zaklenjen zaslon delovnega profila"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Zapri"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Svetlost"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Inverzija barv"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Popravljanje barv"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Velikost pisave"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Upravljanje uporabnikov"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Končano"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Zapri"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Obvestila"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Bližnjične tipke"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Preklop postavitve tipkovnice"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Izbris besedila"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Bližnjice"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Iskanje bližnjic"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Ni najdenih bližnjic."</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistem"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Vrsta vnosa"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Odprte aplikacije"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Trenutna aplikacija"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Dostop do zaslona z obvestili"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Ustvarjanje posnetka celotnega zaslona"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Dostop do seznama sistemskih bližnjic in bližnjic do aplikacij"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Nazaj: Vrnitev v prejšnje stanje (gumb za vrnitev)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Dostop do začetnega zaslona"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Pregled odprtih aplikacij"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Krožno preklapljanje med nedavnimi aplikacijami (naprej)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Krožno preklapljanje med nedavnimi aplikacijami (nazaj)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Dostop do seznama vseh aplikacij in iskanja (tj. iskanje/zaganjalnik)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Skritje in (vnovični) prikaz opravilne vrstice"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Dostop do sistemskih nastavitev"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Dostop do Pomočnika Google"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Zaklepanje zaslona"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Priklic aplikacije za zapiske za zapis hitre zabeležke"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Sistemska večopravilnost"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Vklop razdeljenega zaslona s trenutno aplikacijo na desni"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Vklop razdeljenega zaslona s trenutno aplikacijo na levi"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Preklop iz razdeljenega zaslona v celozaslonski način"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Pri razdeljenem zaslonu: Medsebojna zamenjava aplikacij"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Vnosna naprava"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Preklop jezika vnosa (naslednji jezik)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Preklop jezika vnosa (prejšnji jezik)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Dostop do emodžijev"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Dostop do glasovnega tipkanja"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Aplikacije"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Pomoč"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Brskalnik"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Brskalnik (privzeto Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Stiki"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"E-pošta"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"E-pošta (privzeto Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"Sporočila SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Glasba"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Koledar"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Računalo"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Zemljevidi"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Ne moti"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Bližnjica z gumboma za glasnost"</string>
<string name="battery" msgid="769686279459897127">"Baterija"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"snemanje zaslona"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Brez naslova"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Stanje pripravljenosti"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Velikost pisave"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Pomanjšanje"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Povečanje"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Povečevalno okno"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kontrolniki povečevalnega okna"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Povečaj"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"Prišlo je do napake. Poskusite znova."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Nalaganje"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"tablični računalnik"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"Predvajanje predstavnosti"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"Predvajanje aplikacije <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno, poglejte aplikacijo"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ni mogoče najti"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Kontrolnik ni na voljo"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Oddajanje ni mogoče"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Ni mogoče shraniti. Poskusite znova."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Ni mogoče shraniti."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Uporabite vsaj 4 znake."</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Uporabite manj kot 16 znakov."</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Delovna različica"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Delovna različica je bila kopirana v odložišče."</string>
<string name="basic_status" msgid="2315371112182658176">"Odprt pogovor"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Na voljo mora biti vsaj ena naprava."</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Pridržite bližnjico"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Prekliči"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Obrni"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Razprite telefon za boljši selfi"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Obrnite telefon na sprednji zaslon za boljši selfi"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Uporabite hrbtni fotoaparat, da posnamete širšo sliko višje ločljivosti."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Ta zaslon se bo izklopil."</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Preklopi zaslona zdaj"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Razprite telefon."</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Želite preklopiti zaslona?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Za višjo ločljivost uporabite hrbtni fotoaparat"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Za višjo ločljivost obrnite telefon"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Razpiranje zložljive naprave"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Obračanje zložljive naprave"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Preostanek energije baterije: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Preklopi na delovni profil"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Zapri"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Nastavitve zaklepanja zaslona"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi ni na voljo."</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Fotoaparat je blokiran."</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Fotoaparat in mikrofon sta blokirana."</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon je blokiran."</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prednostni način je vklopljen."</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Zaznavanje pomočnika je vklopljeno."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sl/tiles_states_strings.xml b/packages/SystemUI/res/values-sl/tiles_states_strings.xml
index e720819b4b60..d7e62caac28d 100644
--- a/packages/SystemUI/res/values-sl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sl/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Izklopljeno"</item>
<item msgid="5966994759929723339">"Vklopljeno"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Ni na voljo"</item>
+ <item msgid="2478289035899842865">"Izklopljeno"</item>
+ <item msgid="5137565285664080143">"Vklopljeno"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index dd75f30c3fbf..6a35e38ee9b3 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Streha e njoftimeve."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Cilësimet e shpejta."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"\"Cilësimet e shpejta\" dhe \"Streha e njoftimeve\"."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Ekrani i kyçjes."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ekrani i kyçjes së punës"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Mbylle"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Ndriçimi"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Anasjellja e ngjyrës"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Korrigjimi i ngjyrës"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Madhësia e fontit"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Menaxho përdoruesit"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"U krye"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Mbyll"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Njoftimet"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Shkurtoret e tastierës"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Ndërro strukturën e tastierës"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Pastro tekstin"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Shkurtoret"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Kërko shkurtoret"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Nuk u gjet shkurtore"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistemi"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Hyrja"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Apl. e hapura"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Apl. aktual"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Qasu te streha e njoftimeve"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Bëj një pamje të plotë ekrani"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Qasu te lista e sistemeve/shkurtoreve të aplikacioneve"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Pas: kthehu pas te gjendja e mëparshme (butoni pas)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Qasu tek ekrani bazë"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Përmbledhje e aplikacioneve të hapura"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Lëviz mes aplikacioneve të fundit (përpara)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Lëviz mes aplikacioneve të fundit (pas)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Qasu te lista e aplikacioneve dhe kërko (p.sh. Kërko/Launcher)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Fshih dhe (ri)shfaq shiritin e detyrave"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Qasu te cilësimet e sistemit"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Qasu tek \"Asistenti i Google\""</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Ekrani i kyçjes"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Hap aplikacionin \"Shënimet\" për një memorandum të shpejtë"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Kryerja e shumë detyrave nga sistemi"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Fut ekranin e ndarë me aplikacionin aktual te RHS-ja"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Fut ekranin e ndarë me aplikacionin aktual te LHS-ja"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Kalo nga ekrani i ndarë në ekranin e plotë"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Gjatë ekranit të ndarë: zëvendëso një aplikacion nga një te një tjetër"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Hyrja"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Ndërro gjuhën e hyrjes (gjuha tjetër)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Ndërro gjuhën e hyrjes (gjuha e mëparshme)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Qasu te emoji-t"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Qasu te shkrimi me zë"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Aplikacionet"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Asistenti"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Shfletuesi"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Shfletuesi (Chrome si i parazgjedhur)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Kontaktet"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Email-i"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Email (Gmail si i parazgjedhur)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Muzikë"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalendari"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Makina llogaritëse"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Mos shqetëso"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Shkurtorja e butonave të volumit"</string>
<string name="battery" msgid="769686279459897127">"Bateria"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"regjistrim i ekranit"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Pa titull"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Në gatishmëri"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Madhësia e fontit"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Zvogëlo"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Zmadho"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Dritarja e zmadhimit"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kontrollet e dritares së zmadhimit"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Zmadho"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Nuk mund të transmetohet"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Nuk mund të ruhet. Provo përsëri."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Nuk mund të ruhet."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Përdor të paktën 4 karaktere"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Përdor më pak se 16 karaktere"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numri i ndërtimit"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Numri i ndërtimit u kopjua te kujtesa e fragmenteve"</string>
<string name="basic_status" msgid="2315371112182658176">"Hap bisedën"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Ofrohet të paktën një pajisje"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Prek dhe mbaj shtypur shkurtoren"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Anulo"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Ktheje tani"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Shpalos telefonin për një selfi më të mirë"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Të kthehet tek ekrani para për selfi më të mirë?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Përdor lenten e kamerës së pasme për një fotografi më të gjerë me rezolucion më të lartë."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Ky ekran do të fiket"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Ndërro ekranet tani"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Shpalos telefonin"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Të ndërrohen ekranet?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Për rezolucion më të lartë, përdor kamerën e pasme"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Për rezolucion më të lartë, përmbys telefonin"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Pajisja e palosshme duke u hapur"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Pajisja e palosshme duke u rrotulluar"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Përqindja e mbetur e baterisë: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Kalo te profili i punës"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Mbyll"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Cilësimet e ekranit të kyçjes"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi nuk ofrohet"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera u bllokua"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera dhe mikrofoni u bllokuan"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofoni u bllokua"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Modaliteti i përparësisë aktiv"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Vëmendja e \"Asistentit\" aktive"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sq/tiles_states_strings.xml b/packages/SystemUI/res/values-sq/tiles_states_strings.xml
index 7a09f2450354..45f63bf8e2e8 100644
--- a/packages/SystemUI/res/values-sq/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sq/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Joaktiv"</item>
<item msgid="5966994759929723339">"Aktiv"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Nuk ofrohet"</item>
+ <item msgid="2478289035899842865">"Joaktiv"</item>
+ <item msgid="5137565285664080143">"Aktiv"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 1cdf8585748b..fb4f455c3736 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Прозор са обавештењима."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Брза подешавања."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Брза подешавања и трака са обавештењима."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Закључан екран."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Закључан екран за посао"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Затвори"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Осветљеност"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Инверзија боја"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Корекција боја"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Величина фонта"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Управљаjте корисницима"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Готово"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Затвори"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Обавештења"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Тастерске пречице"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Промени распоред тастатуре"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Обришите текст"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Пречице"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Претражите пречице"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Нису пронађене пречице"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Систем"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Унос"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Отварање аплик"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Актуелна аплик"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Приступ траци са обавештењима"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Снимање екрана"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Приступ листи пречица за систем/апликације"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Назад: назад на претходно стање (дугме Назад)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Приступ почетном екрану"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Преглед отворених апликација"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Преглед недавних апликација (напред)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Преглед недавних апликација (назад)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Приступ листи свих алпикација и претрага (нпр. Претрага/Покретач)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Скривање и поновно приказивање траке задатака"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Приступ подешавањима система"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Приступ Google помоћнику"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Закључавање екрана"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Отварање апликације Белешке за брзо прављење белешке"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Обављање више задатака система истовремено"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Покретање подељеног екрана за актуелну апликацију на десној страни"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Покретање подељеног екрана за актуелну апликацију на левој страни"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Прелазак са подељеног екрана на цео екран"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Током подељеног екрана: замена једне апликације другом"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Унос"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Промена језика уноса (следећи језик)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Промена језика уноса (претходни језик)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Приступ емоџијима"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Приступ уносу текста гласом"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Апликације"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Апликација за помоћ"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Прегледач"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Прегледач (подразумевано Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Контакти"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Имејл"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Имејл (Gmail као подразумевани)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Музика"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Календар"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Калкулатор"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Мапе"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Не узнемиравај"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Пречица за дугмад за јачину звука"</string>
<string name="battery" msgid="769686279459897127">"Батерија"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"снимање екрана"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Без наслова"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Стање приправности"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Величина фонта"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Умањите"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Увећајте"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Прозор за увећање"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Контроле прозора за увећање"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Увећајте"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"Дошло је до грешке. Пробајте поново."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Учитава се"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"таблет"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"Пребацивање медија"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"Пребацује се <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Неактивно. Видите апликацију"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Није пронађено"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Контрола није доступна"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Емитовање није успело"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Чување није успело. Пробајте поново."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Чување није успело."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Користите бар 4 знака"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Користите мање од 16 знакова"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Број верзије"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Број верзије је копиран у привремену меморију."</string>
<string name="basic_status" msgid="2315371112182658176">"Отворите конверзацију"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• да је доступан барем један уређај"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Додирните и задржите пречицу"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Откажи"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Обрни"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Отворите телефон за бољи селфи"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Желите да обрнете на предњи екран за бољи селфи?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Користите задњу камеру да бисте снимили ширу слику са вишом резолуцијом."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Овај екран ће се искључити"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Замени екране"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Отворите телефон"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Желите да замените екране?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"За већу резолуцију користите задњу камеру"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"За већу резолуцију обрните телефон"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Уређај на преклоп се отвара"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Уређај на преклоп се обрће"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Преостало је још<xliff:g id="PERCENTAGE">%s</xliff:g> батерије"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Пређи на пословни профил"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Затвори"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Подешавања закључаног екрана"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"WiFi није доступан"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камера је блокирана"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камера и микрофон су блокирани"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Микрофон је блокиран"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Приоритетни режим је укључен"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Помоћник је у активном стању"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sr/tiles_states_strings.xml b/packages/SystemUI/res/values-sr/tiles_states_strings.xml
index dace491993ba..c959bfb0eb73 100644
--- a/packages/SystemUI/res/values-sr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sr/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Искључено"</item>
<item msgid="5966994759929723339">"Укључено"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Недоступно"</item>
+ <item msgid="2478289035899842865">"Искључено"</item>
+ <item msgid="5137565285664080143">"Укључено"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 92e0ad45f13b..8dcf0cd3a6bc 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Meddelandepanel."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Snabbinställningar."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Snabbinställningar och meddelandepanel."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Låsskärm."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Låsskärm för arbete"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Stäng"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Ljusstyrka"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Färginvertering"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Färgkorrigering"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Teckenstorlek"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Hantera användare"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Klart"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Stäng"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Aviseringar"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Kortkommandon"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Byt tangentbordslayout"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Rensa text"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Kortkommandon"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Sök efter kortkommando"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Inga resultat"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"System"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Inmatning"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Öppna appar"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Aktuell app"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Öppna meddelandepanelen"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Ta en skärmbild av hela skärmen"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Öppna lista över system- och appgenvägar"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Bakåt: gå tillbaka till föregående läge (bakåtknapp)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Öppna startskärmen"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Översikt över öppna appar"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Bläddra igenom de senaste apparna (framåt)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Bläddra igenom de senaste apparna (bakåt)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Öppna en lista över alla appar och sökningar (t.ex. Sök/Appstartaren)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Dölj och visa aktivitetsfältet"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Öppna systeminställningarna"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Öppna Google Assistent"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Lås skärmen"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Ta fram anteckningsappen för en snabb anteckning"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Systemets multikörning"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Öppna delad skärm med aktuell app till höger"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Öppna delad skärm med aktuell app till vänster"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Byt mellan delad skärm och helskärm"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Med delad skärm: ersätt en app med en annan"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Inmatning"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Byt inmatningsspråk (nästa språk)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Byt inmatningsspråk (föregående språk)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Öppna emojis"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Öppna röststyrning"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Appar"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Hjälp"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Webbläsare"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Webbläsare (Chrome som standard)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Kontakter"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"E-post"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"E-post (Gmail som standard)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"Sms"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Musik"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalender"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kalkylator"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Kartor"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Stör ej"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Genväg till volymknappar"</string>
<string name="battery" msgid="769686279459897127">"Batteri"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"skärminspelning"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Ingen titel"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Viloläge"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Teckenstorlek"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Förminska"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Förstora"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Förstoringsfönster"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Inställningar för förstoringsfönster"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Zooma in"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"Något gick fel. Försök igen."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Läser in"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"surfplatta"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"Castar din media"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"Castar <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv, kolla appen"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Hittades inte"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Styrning är inte tillgänglig"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Det gick inte att sända ut"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Det gick inte att spara. Försök igen."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Det gick inte att spara."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Använd minst 4 tecken"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Använd färre än 16 tecken"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Versionsnummer"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Versionsnumret har kopierats till urklipp."</string>
<string name="basic_status" msgid="2315371112182658176">"Öppen konversation"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• minst en enhet är tillgänglig"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Tryck länge på genvägen"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Avbryt"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Vänd nu"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Vik upp telefonen för att ta en bättre selfie"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Vill du ta en bättre selfie med främre kameran?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Använd den bakre kameran för att ta ett mer vidsträckt foto med högre upplösning."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Den här skärmen inaktiveras"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Byt skärm nu"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Vik ut telefonen"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Vill du byta skärm?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Använd den bakre kameran för högre upplösning"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Vänd telefonen för högre upplösning"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"En vikbar enhet viks upp"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"En vikbar enhet vänds"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> av batteriet återstår"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Byt till jobbprofilen"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Stäng"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Inställningar för låsskärm"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wifi är inte tillgängligt"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kameran är blockerad"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kameran och mikrofonen är blockerade"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofonen är blockerad"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioritetsläge är aktiverat"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistenten är aktiverad"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sv/tiles_states_strings.xml b/packages/SystemUI/res/values-sv/tiles_states_strings.xml
index 9e69b00adf64..28717dfa5229 100644
--- a/packages/SystemUI/res/values-sv/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sv/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Av"</item>
<item msgid="5966994759929723339">"På"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Inte tillgängligt"</item>
+ <item msgid="2478289035899842865">"Av"</item>
+ <item msgid="5137565285664080143">"På"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index fec66b240cad..49d4733c8b3c 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Kivuli cha arifa."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Mipangilio ya haraka."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Mipangilio ya haraka na Sehemu ya arifa."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Skrini iliyofungwa."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Skrini iliyofungwa ya kazini"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Funga"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Ung\'avu"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Ugeuzaji rangi"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Usahihishaji wa rangirangi"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Ukubwa wa fonti"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Dhibiti watumiaji"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Nimemaliza"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Funga"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Arifa"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Mikato ya Kibodi"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Badili mkao wa kibodi"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Futa maandishi"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Njia za mkato"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Tafuta njia za mkato"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Hakuna njia za mkato zilizopatikana"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Mfumo"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Vifaa vya kuingiza data"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Fungua programu"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Programu ya sasa"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Fikia sehemu ya arifa"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Piga picha kamili ya skrini"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Orodha ya ufikiaji ya mfumo / njia za mikato za programu"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Nyuma: rudi kwenye hali ya awali (kitufe cha nyuma)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Fikia skrini ya kwanza"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Muhtasari wa programu zilizofunguliwa"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Pitia programu za hivi karibuni (mbele)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Pitia programu za hivi karibuni (nyuma)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Orodha ya ufikiaji ya programu na utafutaji wote (k.m. Utafutaji/Kifungua programu)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Ficha na uonyeshe upya upauzana"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Fikia mipangilio ya mfumo"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Fikia programu ya Mratibu wa Google"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Funga skrini"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Fungua programu ya Madokezo ili uandike taarifa"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Majukumu mengi ya mfumo"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Weka Skrini iliyogawanywa na programu ya sasa kwenye upande wa kulia"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Weka Skrini iliyogawanywa na programu ya sasa kwenye upande wa kushoto"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Badilisha kutoka Skrini iliyogawanywa utumie skrini nzima"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Wakati wa Skrini iliyogawanywa: badilisha kutoka programu moja hadi nyingine"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Vifaa vya kuingiza data"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Badilisha lugha ya kuweka data (lugha inayofuata)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Badilisha lugha ya kuweka data (lugha ya awali)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Fikia emoji"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Fikia kuandika kwa kutamka"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Programu"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Programu ya usaidizi"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Kivinjari"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Kivinjari (Chrome iwe chaguomsingi)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Anwani"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Barua pepe"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Barua pepe (Gmail iwe chaguomsingi)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Muziki"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalenda"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kikokotoo"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Ramani"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Usinisumbue"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Njia ya mkato ya vitufe vya sauti"</string>
<string name="battery" msgid="769686279459897127">"Betri"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"kurekodi skrini"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Wimbo hauna jina"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Hali tuli"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Ukubwa wa Fonti"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Punguza"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Kuza"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Dirisha la Ukuzaji"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Vidhibiti vya Dirisha la Ukuzaji"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Vuta karibu"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"Hitilafu fulani imetokea. Jaribu tena."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Inapakia"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"kompyuta kibao"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"Inatuma maudhui yako"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"Inatuma <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Haitumiki, angalia programu"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Hakipatikani"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Kidhibiti hakipatikani"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Imeshindwa kutuma arifa"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Imeshindwa kuhifadhi. Jaribu tena."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Imeshindwa kuhifadhi."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Tumia angalau herufi 4"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Tumia herufi chini ya 16"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Nambari ya muundo"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Nambari ya muundo imewekwa kwenye ubao wa kunakili."</string>
<string name="basic_status" msgid="2315371112182658176">"Fungua mazungumzo"</string>
@@ -1048,7 +1083,7 @@
<string name="log_access_confirmation_title" msgid="4843557604739943395">"Ungependa kuruhusu <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> ifikie kumbukumbu zote za kifaa?"</string>
<string name="log_access_confirmation_allow" msgid="752147861593202968">"Ruhusu ufikiaji wa mara moja"</string>
<string name="log_access_confirmation_deny" msgid="2389461495803585795">"Usiruhusu"</string>
- <string name="log_access_confirmation_body" msgid="6883031912003112634">"Kumbukumbu za kifaa hurekodi kinachofanyika kwenye kifaa chako. Programu zinaweza kutumia kumbukumbu hizi ili kutambua na kurekebisha hitilafu.\n\nHuenda baadhi ya kumbukumbu zikawa na taarifa nyeti, hivyo ruhusu tu programu unazoziamini kufikia kumbukumbu zote za kifaa. \n\nIwapo hutaruhusu programu hii ifikie kumbukumbu zote za kifaa, bado inaweza kufikia kumbukumbu zake yenyewe. Huenda mtengenezaji wa kifaa chako bado akaweza kufikia baadhi ya kumbukumbu au taarifa zilizopo kwenye kifaa chako."</string>
+ <string name="log_access_confirmation_body" msgid="6883031912003112634">"Kumbukumbu za kifaa hurekodi kinachofanyika kwenye kifaa chako. Programu zinaweza kutumia kumbukumbu hizi ili kutambua na kurekebisha hitilafu.\n\nHuenda baadhi ya kumbukumbu zikawa na taarifa nyeti, hivyo ruhusu tu programu unazoziamini zifikie kumbukumbu zote za kifaa. \n\nIwapo hutaruhusu programu hii ifikie kumbukumbu zote za kifaa, bado inaweza kufikia kumbukumbu zake yenyewe. Huenda mtengenezaji wa kifaa chako bado akaweza kufikia baadhi ya kumbukumbu au taarifa zilizopo kwenye kifaa chako."</string>
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Pata maelezo zaidi"</string>
<string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"Pata maelezo zaidi katika <xliff:g id="URL">%s</xliff:g>"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"Fungua <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Angalau kifaa kimoja kinapatikana"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Gusa na ushikilie njia ya mkato"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Ghairi"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Geuza kifaa sasa"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Kunjua simu ili upige selfi iliyo bora"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Ungependa kugeuza skrini ya mbele ili upige selfi?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Tumia kamera ya nyuma ili upige picha pana iliyo na ubora wa juu."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Skrini hii itajizima"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Badilisha skrini sasa"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Kunjua simu"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Ungependa kubadilisha skrini?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Kwa ubora wa juu, tumia kamera ya nyuma"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Kwa ubora wa juu, geuza simu"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Kifaa kinachokunjwa kikikunjuliwa"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Kifaa kinachokunjwa kikigeuzwa"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Chaji ya betri imesalia <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Tumia wasifu wa kazini"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Funga"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Mipangilio ya skrini iliyofungwa"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi haipatikani"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera imezuiwa"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera na maikrofoni zimezuiwa"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Maikrofoni imezuiwa"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Hali ya kipaumbele imewashwa"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Programu ya Mratibu imewashwa"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sw/tiles_states_strings.xml b/packages/SystemUI/res/values-sw/tiles_states_strings.xml
index 2f765ef5320a..2fe40603bc7d 100644
--- a/packages/SystemUI/res/values-sw/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sw/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Imezimwa"</item>
<item msgid="5966994759929723339">"Imewashwa"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Haipatikani"</item>
+ <item msgid="2478289035899842865">"Umezima"</item>
+ <item msgid="5137565285664080143">"Umewasha"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 45b137a9acec..59becc69506c 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -62,7 +62,6 @@
<dimen name="qs_security_footer_background_inset">0dp</dimen>
<dimen name="qs_panel_padding_top">8dp</dimen>
- <dimen name="qs_panel_padding_top_combined_headers">@dimen/qs_panel_padding_top</dimen>
<!-- The width of large/content heavy dialogs (e.g. Internet, Media output, etc) -->
<dimen name="large_dialog_width">472dp</dimen>
@@ -88,4 +87,7 @@
<!-- Biometric Auth pattern view size, better to align keyguard_security_width -->
<dimen name="biometric_auth_pattern_view_size">348dp</dimen>
+
+ <dimen name="controls_header_horizontal_padding">12dp</dimen>
+ <dimen name="controls_content_margin_horizontal">24dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-sw720dp-land/dimens.xml b/packages/SystemUI/res/values-sw720dp-land/dimens.xml
index 9ed936050aa2..8583f0549960 100644
--- a/packages/SystemUI/res/values-sw720dp-land/dimens.xml
+++ b/packages/SystemUI/res/values-sw720dp-land/dimens.xml
@@ -37,6 +37,8 @@
<dimen name="qs_media_rec_album_size">112dp</dimen>
<dimen name="qs_media_rec_album_side_margin">16dp</dimen>
+ <dimen name="controls_panel_corner_radius">40dp</dimen>
+
<dimen name="lockscreen_shade_max_over_scroll_amount">42dp</dimen>
<!-- Roughly the same distance as media on LS to media on QS. We will translate by this value
diff --git a/packages/SystemUI/res/values-sw720dp-port/dimens.xml b/packages/SystemUI/res/values-sw720dp-port/dimens.xml
index 8b41a44b9ba3..9248d585bba7 100644
--- a/packages/SystemUI/res/values-sw720dp-port/dimens.xml
+++ b/packages/SystemUI/res/values-sw720dp-port/dimens.xml
@@ -33,5 +33,7 @@
side -->
<dimen name="qs_tiles_page_horizontal_margin">60dp</dimen>
+ <dimen name="controls_panel_corner_radius">46dp</dimen>
+
<dimen name="notification_section_divider_height">16dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-sw720dp/dimens.xml b/packages/SystemUI/res/values-sw720dp/dimens.xml
index 8f59df655c3a..20864591ae5a 100644
--- a/packages/SystemUI/res/values-sw720dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw720dp/dimens.xml
@@ -19,7 +19,8 @@
<!-- gap on either side of status bar notification icons -->
<dimen name="status_bar_icon_padding">1dp</dimen>
- <dimen name="controls_padding_horizontal">40dp</dimen>
+ <dimen name="controls_header_horizontal_padding">28dp</dimen>
+ <dimen name="controls_content_margin_horizontal">40dp</dimen>
<dimen name="large_screen_shade_header_height">56dp</dimen>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 20889bac3182..f62029a85c26 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -198,6 +198,8 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"அறிவிப்பு விவரம்."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"உடனடி அமைப்பு."</string>
+ <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
+ <skip />
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"லாக் ஸ்கிரீன்."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"பணி லாக் ஸ்கிரீன்"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"மூடு"</string>
@@ -258,6 +260,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"ஒளிர்வு"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"கலர் இன்வெர்ஷன்"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"கலர் கரெக்‌ஷன்"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"எழுத்து வடிவத்தின் அளவு"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"பயனர்களை நிர்வகியுங்கள்"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"முடிந்தது"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"மூடுக"</string>
@@ -613,14 +616,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"அறிவிப்புகள்"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"கீபோர்டு ஷார்ட்கட்கள்"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"கீபோர்டு லே அவுட்டை மாற்று"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"வார்த்தைகளை அழிக்கும்"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ஷார்ட்கட்கள்"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"ஷார்ட்கட்களைத் தேடுக"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"ஷார்ட்கட்கள் எதுவுமில்லை"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"சிஸ்டம்"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"உள்ளீடு"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"திறந்த ஆப்ஸ்"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"தற்போதைய ஆப்ஸ்"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"அறிவிப்பு விவரத்திற்கான அணுகல்"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"முழு ஸ்கிரீன்ஷாட் எடுத்தல்"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"சிஸ்டம் / ஆப்ஸ் ஷார்ட்கட்களுக்கான அணுகல் பட்டியல்"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"பின்செல்: முந்தைய நிலைக்குச் செல்லுதல் (பின்செல்வதற்கான பட்டன்)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"முகப்புத் திரைக்கான அணுகல்"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"திறந்திருக்கும் ஆப்ஸைப் பார்த்தல்"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"சமீபத்திய ஆப்ஸுக்கிடையில் (பிந்தையது) மாறுதல்"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"சமீபத்திய ஆப்ஸுக்கிடையில் (முந்தையது) மாறுதல்"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"அனைத்து ஆப்ஸ் மற்றும் தேடலுக்குமான (தேடல், தொடக்கி) அணுகல் பட்டியல்"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"செயல் பட்டியை மறைத்தல் மற்றும் (மீண்டும்) காட்டுதல்"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"சிஸ்டம் அமைப்புகளுக்கான அணுகல்"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Google Assistantடிற்கான அணுகல்"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"பூட்டுத் திரை"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"மெமோவை விரைவாகத் தயாரிக்க Notes ஆப்ஸைப் பயன்படுத்துதல்"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"சிஸ்டம் பல வேலைகளைச் செய்தல்"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"வலதுபுறத்தில் தற்போதைய ஆப்ஸ் தோன்றுமாறு திரைப் பிரிப்பை அமைத்தல்"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"இடதுபுறத்தில் தற்போதைய ஆப்ஸ் தோன்றுமாறு திரைப் பிரிப்பை அமைத்தல்"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"திரைப் பிரிப்பு பயன்முறையிலிருந்து முழுத்திரைக்கு மாறுதல்"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"திரைப் பிரிப்பின்போது: ஓர் ஆப்ஸுக்குப் பதிலாக மற்றொன்றை மாற்றுதல்"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"உள்ளீடு"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"உள்ளீட்டு மொழியை மாற்றுதல் (அடுத்த மொழி)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"உள்ளீட்டு மொழியை மாற்றுதல் (முந்தைய மொழி)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"ஈமோஜிக்கான அணுகல்"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"குரல் டைப்பிங்கிற்கான அணுகல்"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"ஆப்ஸ்"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"அசிஸ்ட்"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"உலாவி"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"உலாவி (இயல்பாக Chrome இருக்கும்)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"தொடர்புகள்"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"மின்னஞ்சல்"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"மின்னஞ்சல் (இயல்பாக Gmail இருக்கும்)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"மியூசிக்"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"கால்குலேட்டர்"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"தொந்தரவு செய்ய வேண்டாம்"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"ஒலியளவுப் பொத்தான்களுக்கான ஷார்ட்கட்"</string>
<string name="battery" msgid="769686279459897127">"பேட்டரி"</string>
@@ -783,6 +820,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ஸ்கிரீன் ரெக்கார்டிங்"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"தலைப்பு இல்லை"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"இயக்க நேரம்"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"எழுத்து வடிவத்தின் அளவு"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"சிறிதாக்கும்"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"பெரிதாக்கும்"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"பெரிதாக்கல் சாளரம்"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"பெரிதாக்கல் சாளரக் கட்டுப்பாடுகள்"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"பெரிதாக்கு"</string>
@@ -889,10 +929,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"ஏதோ தவறாகிவிட்டது. மீண்டும் முயலவும்."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"ஏற்றுகிறது"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"டேப்லெட்"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"உங்கள் மீடியா அலைபரப்பப்படுகிறது"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"<xliff:g id="APP_LABEL">%1$s</xliff:g> ஆப்ஸை அலைபரப்புகிறது"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"செயலில் இல்லை , சரிபார்க்கவும்"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"இல்லை"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"கட்டுப்பாடு இல்லை"</string>
@@ -929,10 +967,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"ஒளிபரப்ப முடியவில்லை"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"சேமிக்க முடியவில்லை. மீண்டும் முயலவும்."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"சேமிக்க முடியவில்லை."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"குறைந்தது 4 எழுத்துகளைப் பயன்படுத்துங்கள்"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16 எழுத்துகளுக்குக் குறைவாகப் பயன்படுத்துங்கள்"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"பதிப்பு எண்"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"பதிப்பு எண் கிளிப்போர்டுக்கு நகலெடுக்கப்பட்டது."</string>
<string name="basic_status" msgid="2315371112182658176">"திறந்தநிலை உரையாடல்"</string>
@@ -1059,11 +1095,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• குறைந்தபட்சம் ஒரு சாதனமாவது கிடைக்க வேண்டும்"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"ஷார்ட்கட்டை தொட்டுப் பிடிக்கவும்"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"ரத்துசெய்"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"இப்போது மாற்றவும்"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"சிறந்த செல்ஃபிக்கு மொபைலை மடக்காதீர்கள்"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"சிறந்த செல்ஃபிக்கு முன்புற டிஸ்பிளேவிற்கு மாற்றவா?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"அதிகத் தெளிவுத்திறனுடன் அகலக் கோணத்தில் படத்தை எடுப்பதற்குப் பின்பக்கக் கேமராவைப் பயன்படுத்துங்கள்."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ இந்தத் திரை ஆஃப் ஆகிவிடும்"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"இப்போது திரைகளை மாற்றவா?"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"மொபைலை விரியுங்கள்"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"காட்சித் திரைகளை மாற்றுவது எப்படி?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"உயர் தெளிவுத்திறனுக்கு, பின்புறக் கேமராவை உபயோகிங்கள்"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"உயர் தெளிவுத்திறனுக்கு, மொபைலை ஃபிளிப் செய்யுங்கள்"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"மடக்கத்தக்க சாதனம் திறக்கப்படுகிறது"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"மடக்கத்தக்க சாதனம் ஃபிளிப் செய்யப்பட்டு திருப்பப்படுகிறது"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> பேட்டரி மீதமுள்ளது"</string>
@@ -1075,4 +1111,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"பணிக் கணக்கிற்கு மாறு"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"மூடுக"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"பூட்டுத் திரை அமைப்புகள்"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"வைஃபை கிடைக்கவில்லை"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"கேமரா தடுக்கப்பட்டுள்ளது"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"கேமராவும் மைக்ரோஃபோனும் தடுக்கப்பட்டுள்ளன"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"மைக்ரோஃபோன் தடுக்கப்பட்டுள்ளது"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"முன்னுரிமைப் பயன்முறை இயக்கத்தில் உள்ளது"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"அசிஸ்டண்ட்டின் கவனம் இயக்கத்தில் உள்ளது"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ta/tiles_states_strings.xml b/packages/SystemUI/res/values-ta/tiles_states_strings.xml
index 41f64125753c..5bcc6c761e1c 100644
--- a/packages/SystemUI/res/values-ta/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ta/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"முடக்கப்பட்டுள்ளது"</item>
<item msgid="5966994759929723339">"இயக்கப்பட்டுள்ளது"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"கிடைக்கவில்லை"</item>
+ <item msgid="2478289035899842865">"முடக்கப்பட்டுள்ளது"</item>
+ <item msgid="5137565285664080143">"இயக்கப்பட்டுள்ளது"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 97cdce5b83d3..4a0cb46cb52d 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"నోటిఫికేషన్ షేడ్."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"శీఘ్ర సెట్టింగ్‌లు."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"క్విక్ సెట్టింగ్‌లు, నోటిఫికేషన్ తెర."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"లాక్ స్క్రీన్."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"కార్యాలయ లాక్ స్క్రీన్"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"మూసివేస్తుంది"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"ప్రకాశం"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"కలర్ మార్పిడి"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"కలర్ కరెక్షన్"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"ఫాంట్ సైజ్"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"యూజర్‌లను మేనేజ్ చేయండి"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"పూర్తయింది"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"మూసివేయి"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"నోటిఫికేషన్‌లు"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"కీబోర్డ్ షార్ట్‌కట్‌లు"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"కీబోర్డ్ లేఅవుట్‌ను మార్చండి"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"టెక్స్ట్‌ను క్లియర్ చేయండి"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"షార్ట్‌కట్‌లు"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"షార్ట్‌కట్స్ సెర్చ్ చేయండి"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"షార్ట్‌కట్‌లు ఏవీ లేవు"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"సిస్టమ్"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"ఇన్‌పుట్"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"యాప్స్ తెరవండి"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"ప్రస్తుత యాప్"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"నోటిఫికేషన్ తెరను యాక్సెస్ చేయండి"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"పూర్తి స్క్రీన్‌షాట్ తీసుకోండి"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"సిస్టమ్ / యాప్స్ షార్ట్‌కట్స్ లిస్ట్‌ను యాక్సెస్ చేయండి"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"వెనుకకు: మునుపటి స్థితికి తిరిగి వెళ్లండి (వెనుకకు బటన్)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"మొదటి స్క్రీన్‌ను యాక్సెస్ చేయండి"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Overview of open apps"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"ఇటీవలి యాప్‌లను ఒక్కొక్కటిగా చూడండి (ముందుకు)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"ఇటీవలి యాప్‌లను ఒక్కొక్కటిగా చూడండి (వెనుకకు)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"అన్ని యాప్‌లు, సెర్చ్ లిస్ట్‌ను యాక్సెస్ చేయండి (అంటే సెర్చ్/లాంచర్)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"టాస్క్‌బార్‌ను దాచిపెట్టి (తిరిగి) చూపించండి"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"సిస్టమ్ సెట్టింగ్‌లను యాక్సెస్ చేయండి"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Google Assistantను యాక్సెస్ చేయండి"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"లాక్ స్క్రీన్"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"క్విక్ మెమో కోసం Notes యాప్‌ను లాగండి"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"సిస్టమ్ మల్టీ-టాస్కింగ్"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"RHSకు ప్రస్తుత యాప్‌తో స్ప్లిట్ స్క్రీన్‌ను ఎంటర్ చేయండి"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"LHSకు ప్రస్తుత యాప్‌తో స్ప్లిట్ స్క్రీన్‌ను ఎంటర్ చేయండి"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"స్ప్లిట్ స్క్రీన్‌ను ఫుల్ స్క్రీన్‌కు మార్చండి"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"స్ప్లిట్ స్క్రీన్ సమయంలో: యాప్‌ను ఒకదాని నుండి మరొకదానికి రీప్లేస్ చేయండి"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"ఇన్‌పుట్"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"ఇన్‌పుట్ భాషకు స్విచ్ అవ్వండి (తర్వాతి భాష)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"ఇన్‌పుట్ భాషకు స్విచ్ అవ్వండి (మునుపటి భాష)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"ఎమోజిని యాక్సెస్ చేయండి"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"వాయిస్ టైపింగ్‌ను యాక్సెస్ చేయండి"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"అప్లికేషన్‌లు"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"సహాయకం"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"బ్రౌజర్"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"బ్రౌజర్ (ఆటోమేటిక్ సెట్టింగ్‌గా Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"కాంటాక్ట్‌లు"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"ఈమెయిల్‌"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"ఈమెయిల్ (ఆటోమేటిక్ సెట్టింగ్‌గా Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"మ్యూజిక్"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"క్యాలిక్యులేటర్"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"అంతరాయం కలిగించవద్దు"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"వాల్యూమ్ బటన్‌ల షార్ట్‌కట్"</string>
<string name="battery" msgid="769686279459897127">"బ్యాటరీ"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"స్క్రీన్ రికార్డింగ్"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"శీర్షిక లేదు"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"స్టాండ్‌బై"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"ఫాంట్ సైజ్"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"చిన్నదిగా చేస్తుంది"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"పెద్దదిగా చేస్తుంది"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"మ్యాగ్నిఫికేషన్ విండో"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"మ్యాగ్నిఫికేషన్ నియంత్రణల విండో"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"దగ్గరగా జూమ్ చేయండి"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"ప్రసారం చేయడం సాధ్యపడలేదు"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"సేవ్ చేయడం సాధ్యపడదు. మళ్లీ ట్రై చేయండి."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"సేవ్ చేయడం సాధ్యపడదు."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"కనీసం 4 అక్షరాలను ఉపయోగించండి"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16 కంటే తక్కువ అక్షరాలను ఉపయోగించండి"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"బిల్డ్ నంబర్"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"బిల్డ్ నంబర్, క్లిప్‌బోర్డ్‌కు కాపీ చేయబడింది."</string>
<string name="basic_status" msgid="2315371112182658176">"సంభాషణను తెరవండి"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• కనీసం ఒక పరికరమైనా అందుబాటులో ఉందని"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"షార్ట్‌కట్‌ను తాకి, నొక్కి ఉంచు"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"రద్దు చేయండి"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"ఇప్పుడే తిప్పండి"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"మెరుగైన సెల్ఫీ కోసం ఫోన్‌ను అన్‌ఫోల్డ్ చేయండి"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"మంచి సెల్ఫీ కోసం ముందు వైపు డిస్‌ప్లేకు తిప్పాలా?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"వెనుక వైపున ఉన్న కెమెరాను ఉపయోగించి అధిక రిజల్యూషన్ గల, మరింత వెడల్పైన ఫోటోను పొందండి."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ఈ స్క్రీన్ ఆఫ్ అవుతుంది"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"ఇప్పుడే స్క్రీన్‌లను మార్చండి"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"ఫోన్‌ను అన్‌ఫోల్డ్ చేయండి"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"స్క్రీన్‌లను మార్చాలా?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"అధిక రిజల్యూషన్ కోసం, వెనుక వైపు కెమెరాను ఉపయోగించండి"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"అధిక రిజల్యూషన్ కోసం, ఫోన్‌ను తిప్పండి"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"మడవగల పరికరం విప్పబడుతోంది"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"మడవగల పరికరం చుట్టూ తిప్పబడుతోంది"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> బ్యాటరీ మిగిలి ఉంది"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"వర్క్ ప్రొఫైల్‌కు మారండి"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"మూసివేయండి"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"లాక్ స్క్రీన్ సెట్టింగ్‌లు"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi అందుబాటులో లేదు"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"కెమెరా బ్లాక్ చేయబడింది"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"కెమెరా, మైక్రోఫోన్ బ్లాక్ చేయబడ్డాయి"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"మైక్రోఫోన్ బ్లాక్ చేయబడింది"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"ప్రయారిటీ మోడ్ ఆన్‌లో ఉంది"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant అటెన్షన్ ఆన్‌లో ఉంది"</string>
</resources>
diff --git a/packages/SystemUI/res/values-te/tiles_states_strings.xml b/packages/SystemUI/res/values-te/tiles_states_strings.xml
index 44ba47781ae7..6549c5631161 100644
--- a/packages/SystemUI/res/values-te/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-te/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"ఆఫ్"</item>
<item msgid="5966994759929723339">"ఆన్"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"అందుబాటులో లేదు"</item>
+ <item msgid="2478289035899842865">"ఆఫ్‌లో ఉంది"</item>
+ <item msgid="5137565285664080143">"ఆన్‌లో ఉంది"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 05f643d56de9..64a528066931 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"หน้าต่างแจ้งเตือน"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"การตั้งค่าด่วน"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"การตั้งค่าด่วนและหน้าต่างแจ้งเตือน"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ล็อกหน้าจอ"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"หน้าจอล็อกของโปรไฟล์งาน"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"ปิด"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"ความสว่าง"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"การกลับสี"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"การแก้สี"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"ขนาดแบบอักษร"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"จัดการผู้ใช้"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"เสร็จสิ้น"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"ปิด"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"การแจ้งเตือน"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"แป้นพิมพ์ลัด"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"สลับรูปแบบแป้นพิมพ์"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"ล้างข้อความ"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"ทางลัด"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"ค้นหาทางลัด"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"ไม่พบทางลัด"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"ระบบ"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"อินพุต"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"แอปที่เปิดอยู่"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"แอปปัจจุบัน"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"เข้าถึงหน้าต่างแจ้งเตือน"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"ถ่ายภาพหน้าจอแบบเต็มจอ"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"เข้าถึงรายการทางลัดของระบบ/แอปทั้งหมด"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"ย้อนกลับ: กลับไปยังสถานะก่อนหน้า (ปุ่มย้อนกลับ)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"เข้าถึงหน้าจอหลัก"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"ภาพรวมของแอปที่เปิดอยู่"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"สลับระหว่างแอปล่าสุด (ไปข้างหน้า)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"สลับระหว่างแอปล่าสุด (กลับหลัง)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"เข้าถึงรายการแอปและการค้นหา (เช่น Search/Launcher)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"ซ่อนและแสดงแถบงาน (อีกครั้ง)"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"เข้าถึงการตั้งค่าระบบ"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"เข้าถึง Google Assistant"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"ล็อกหน้าจอ"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"เปิดแอปโน้ตเพื่อจดบันทึก"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"การทํางานหลายอย่างพร้อมกันของระบบ"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"เข้าสู่โหมดแยกหน้าจอโดยแอปปัจจุบันอยู่ด้านขวา"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"เข้าสู่โหมดแยกหน้าจอโดยแอปปัจจุบันอยู่ด้านซ้าย"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"เปลี่ยนจากโหมดแยกหน้าจอเป็นเต็มหน้าจอ"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"ระหว่างใช้โหมดแยกหน้าจอ: เปลี่ยนแอปหนึ่งเป็นอีกแอปหนึ่ง"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"อินพุต"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"เปลี่ยนภาษาในการป้อนข้อมูล (ภาษาถัดไป)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"เปลี่ยนภาษาในการป้อนข้อมูล (ภาษาก่อนหน้า)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"เข้าถึงอีโมจิ"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"เข้าถึงการพิมพ์ด้วยเสียง"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"แอปพลิเคชัน"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"ผู้ช่วย"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"เบราว์เซอร์"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"เบราว์เซอร์ (Chrome เป็นค่าเริ่มต้น)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"รายชื่อติดต่อ"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"อีเมล"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"อีเมล (Gmail เป็นค่าเริ่มต้น)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"เพลง"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"ปฏิทิน"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"เครื่องคิดเลข"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"แผนที่"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"ห้ามรบกวน"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"ทางลัดปุ่มปรับระดับเสียง"</string>
<string name="battery" msgid="769686279459897127">"แบตเตอรี่"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"การบันทึกหน้าจอ"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"ไม่มีชื่อ"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"สแตนด์บาย"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"ขนาดแบบอักษร"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"ทำให้เล็กลง"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"ทำให้ใหญ่ขึ้น"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"หน้าต่างการขยาย"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"การควบคุมหน้าต่างการขยาย"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"ซูมเข้า"</string>
@@ -815,7 +854,7 @@
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"แตะเพื่อเปิดฟีเจอร์การช่วยเหลือพิเศษ ปรับแต่งหรือแทนที่ปุ่มนี้ในการตั้งค่า\n\n"<annotation id="link">"ดูการตั้งค่า"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"ย้ายปุ่มไปที่ขอบเพื่อซ่อนชั่วคราว"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"เลิกทำ"</string>
- <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"นำทางลัดฟีเจอร์<xliff:g id="FEATURE_NAME">%s</xliff:g>ออกแล้ว"</string>
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"นำทางลัด<xliff:g id="FEATURE_NAME">%s</xliff:g>ออกแล้ว"</string>
<string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{นำทางลัด # รายการออกแล้ว}other{นำทางลัด # รายการออกแล้ว}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ย้ายไปด้านซ้ายบน"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"ย้ายไปด้านขวาบน"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"ออกอากาศไม่ได้"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"บันทึกไม่ได้ โปรดลองอีกครั้ง"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"บันทึกไม่ได้"</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"ใช้อักขระอย่างน้อย 4 ตัว"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"ใช้อักขระไม่เกิน 16 ตัว"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"หมายเลขบิลด์"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"คัดลอกหมายเลขบิลด์ไปยังคลิปบอร์ดแล้ว"</string>
<string name="basic_status" msgid="2315371112182658176">"เปิดการสนทนา"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• มีอุปกรณ์พร้อมใช้งานอย่างน้อย 1 รายการ"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"แตะแป้นพิมพ์ลัดค้างไว้"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"ยกเลิก"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"พลิกเลย"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"กางโทรศัพท์เพื่อเซลฟีที่ดียิ่งขึ้น"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"พลิกเป็นหน้าจอด้านหน้าเพื่อภาพเซลฟีที่ดีขึ้นไหม"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"ใช้กล้องหลังเพื่อถ่ายภาพกว้างขึ้นด้วยความละเอียดสูงขึ้น"</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ หน้าจอนี้จะปิดไป"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"สลับหน้าจอเลย"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"กางโทรศัพท์ออก"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"สลับหน้าจอไหม"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"ใช้กล้องหลังเพื่อให้ได้ภาพที่มีความละเอียดมากขึ้น"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"พลิกด้านโทรศัพท์เพื่อให้ได้ภาพที่มีความละเอียดมากขึ้น"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"อุปกรณ์ที่พับได้กำลังกางออก"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"อุปกรณ์ที่พับได้กำลังพลิกไปมา"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"เหลือแบตเตอรี่ <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"สลับไปใช้โปรไฟล์งาน"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"ปิด"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"การตั้งค่าหน้าจอล็อก"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi ไม่พร้อมใช้งาน"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"กล้องถูกบล็อกอยู่"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"กล้องและไมโครโฟนถูกบล็อกอยู่"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"ไมโครโฟนถูกบล็อกอยู่"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"โหมดลำดับความสำคัญเปิดอยู่"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"การเรียกใช้งาน Assistant เปิดอยู่"</string>
</resources>
diff --git a/packages/SystemUI/res/values-th/tiles_states_strings.xml b/packages/SystemUI/res/values-th/tiles_states_strings.xml
index 9cd060f2cabf..69449a72196e 100644
--- a/packages/SystemUI/res/values-th/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-th/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"ปิด"</item>
<item msgid="5966994759929723339">"เปิด"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"ไม่พร้อมใช้งาน"</item>
+ <item msgid="2478289035899842865">"ปิด"</item>
+ <item msgid="5137565285664080143">"เปิด"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 8206db1a8f1f..d4d583f105e0 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Notification shade."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Mga mabilisang setting."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Mga mabilisang setting at Notification shade."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Lock screen."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Lock screen sa trabaho"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Isara"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Brightness"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Pag-invert ng kulay"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Pagtatama ng kulay"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Laki ng font"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Pamahalaan ang mga user"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Tapos na"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Isara"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Mga Notification"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Mga Keyboard Shortcut"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Magpalit ng layout ng keyboard"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"I-clear ang text"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Mga Shortcut"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Maghanap ng mga shortcut"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Walang nakitang shortcut"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"System"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Input"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Buksan ang app"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Kasalukuyang app"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"I-access ang notification shade"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Kumuha ng buong screenshot"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"I-access ang listahan ng mga shortcut ng system / mga app"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Bumalik: bumalik sa nakaraang status (button na bumalik)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"I-access ang home screen"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Pangkalahatang-ideya ng mga bukas na app"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Mag-cycle sa mga kamakailang app (sumulong)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Mag-cycle sa mga kamakailang app (bumalik)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"I-access ang listahan ng lahat ng app at paghahanap (ibig sabihin, Search/Launcher)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Itago at ipakita (ulit) ang taskbar"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"I-access ang mga setting ng system"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"I-access ang Google Assistant"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"I-lock ang screen"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Buksan ang Notes app para sa mabilis na memo"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitasking ng system"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Lumipat sa Split screen nang nasa RHS ang kasalukuyang app"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Lumipat sa Split screen nang nasa LHS ang kasalukuyang app"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Lumipat sa full screen mula sa Split screen"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Habang nasa Split screen: magpalit-palit ng app"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Input"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Magpalit ng wika ng pag-input (susunod na wika)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Magpalit ng wika ng pag-input (nakaraang wika)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"I-access ang emoji"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"I-access ang voice typing"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Mga Application"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Tulong"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Browser"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Browser (Chrome bilang default)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Mga Contact"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Email"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Email (Gmail bilang default)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Music"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Kalendaryo"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculator"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Mga mapa"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Huwag Istorbohin"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Shortcut ng mga button ng volume"</string>
<string name="battery" msgid="769686279459897127">"Baterya"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"pag-record ng screen"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Walang pamagat"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Naka-standby"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Laki ng Font"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Paliitin"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Palakihin"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Window ng Pag-magnify"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Mga Kontrol sa Pag-magnify ng Window"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Mag-zoom in"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"Nagkaproblema. Subukan ulit."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Naglo-load"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"tablet"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"Pag-cast ng iyong media"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"Kina-cast ang <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Hindi aktibo, tingnan ang app"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Hindi nahanap"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Hindi available ang kontrol"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Hindi makapag-broadcast"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Hindi ma-save. Subukan ulit."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Hindi ma-save."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Gumamit ng hindi bababa sa 4 na character"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Gumamit ng mas kaunti sa 16 na character"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numero ng build"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Nakopya sa clipboard ang numero ng build."</string>
<string name="basic_status" msgid="2315371112182658176">"Buksan ang pag-uusap"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• May kahit isang device na available"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Pindutin nang matagal: shortcut"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Kanselahin"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"I-flip na ngayon"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"I-unfold ang telepono para sa mas magandang selfie"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"I-flip sa front display para sa magandang selfie?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Gamitin ang camera sa harap para sa mas malawak na larawan na may mas mataas na resolution."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Mag-o-off ang screen na ito"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Lumipat na ng screen"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"I-unfold ang telepono"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Lumipat ng screen?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Para sa mas mataas na resolution, gamitin ang camera sa likod"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Para sa mas mataas na resolution, i-flip ang telepono"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Ina-unfold na foldable na device"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Fini-flip na foldable na device"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> baterya na lang ang natitira"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Lumipat sa profile sa trabaho"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Isara"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Mga setting ng lock screen"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Hindi available ang Wi-Fi"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Naka-block ang camera"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Naka-block ang camera at mikropono"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Naka-block ang mikropono"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Naka-on ang Priority mode"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Naka-on ang atensyon ng Assistant"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tl/tiles_states_strings.xml b/packages/SystemUI/res/values-tl/tiles_states_strings.xml
index cd7dcf51b279..689c2a26ca61 100644
--- a/packages/SystemUI/res/values-tl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-tl/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Naka-off"</item>
<item msgid="5966994759929723339">"Naka-on"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Hindi available"</item>
+ <item msgid="2478289035899842865">"Naka-off"</item>
+ <item msgid="5137565285664080143">"Naka-on"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index be2f84a88b31..4df50fc99c6d 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Bildirim gölgesi."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Hızlı ayarlar."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Hızlı ayarlar ve Bildirim gölgesi."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Kilit ekranı"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"İş profili kilit ekranı"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Kapat"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Parlaklık"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Rengi ters çevirme"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Renk düzeltme"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Yazı tipi boyutu"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Kullanıcıları yönet"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Bitti"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Kapat"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Bildirimler"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Klavye Kısayolları"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Klavye düzenini değiştir"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Metni temizle"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Kısayollar"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Kısayol araması yapın"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Kısayol bulunamadı"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistem"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Giriş"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Uygulamaları açma"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Mevcut uygulama"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Bildirim gölgesine erişin"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Tam ekran görüntüsü alın"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Sistem/uygulama kısayolları listesine erişin"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Geri: Önceki duruma geri dönün (geri düğmesi)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Ana ekrana erişin"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Açık uygulamalara genel bakış"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Son uygulamalar arasında gezinin (ileri)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Son uygulamalar arasında gezinin (geri)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Tüm uygulama ve arama (ör. Arama/Launcher) listesine erişin"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Görev çubuğunu gizleyin ve (yeniden) gösterin"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Sistem ayarlarına erişin"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Google Asistan\'a erişin"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Kilit ekranı"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Hızlıca not almak için Notlar uygulamasını açın"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Sistem çoklu görevi"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Mevcut uygulamayı sağ tarafa alarak bölünmüş ekrana geçin"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Mevcut uygulamayı sol tarafa alarak bölünmüş ekrana geçin"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Bölünmüş ekrandan tam ekrana geçin"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Bölünmüş ekran etkinken: Bir uygulamayı başkasıyla değiştirin"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Giriş"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Giriş dilini değiştirin (sonraki dil)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Giriş dilini değiştirin (önceki dil)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Emojilere erişin"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Sesle yazma özelliğine erişin"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Uygulamalar"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Asistan"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Tarayıcı"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Tarayıcı (varsayılan olarak Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Kişiler"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"E-posta"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"E-posta (varsayılan olarak Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Müzik"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Takvim"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Hesap Makinesi"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Haritalar"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Rahatsız Etmeyin"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Ses düğmeleri kısayolu"</string>
<string name="battery" msgid="769686279459897127">"Pil"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ekran kaydı"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Başlıksız"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Beklemeye alınıyor"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Yazı Tipi Boyutu"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Küçült"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Büyüt"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Büyütme Penceresi"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Büyütme Penceresi Kontrolleri"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Yakınlaştır"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"Bir hata oluştu. Tekrar deneyin."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Yükleme"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"tablet"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"Medyanız yayınlanıyor"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"<xliff:g id="APP_LABEL">%1$s</xliff:g> yayınlanıyor"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Devre dışı, uygulamaya bakın"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Bulunamadı"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Kontrol kullanılamıyor"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Yayınlanamıyor"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Kaydedilemiyor. Tekrar deneyin."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Kaydedilemiyor."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"En az 4 karakter kullanın."</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"En fazla 16 karakter kullanın"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Derleme numarası"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Derleme numarası panoya kopyalandı."</string>
<string name="basic_status" msgid="2315371112182658176">"Görüşmeyi aç"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• En az bir cihaz mevcut olmalıdır"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Kısayola dokunup basılı tutun"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"İptal"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Şimdi çevirin"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Daha iyi selfie çekmek için telefonu açın"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Daha iyi bir selfie için ön ekrana geçilsin mi?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Daha yüksek çözünürlüğe sahip daha büyük bir fotoğraf için arka yüz kamerasını kullanın."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Bu ekran kapatılacak"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Ekranı şimdi değiştirin"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Telefonu açın"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Ekran değiştirilsin mi?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Daha yüksek çözünürlük için arka kamerayı kullanın"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Daha yüksek çözünürlük için telefonu çevirin"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Katlanabilir cihaz açılıyor"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Katlanabilir cihaz döndürülüyor"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> pil kaldı"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"İş profiline geç"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Kapat"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Kilit ekranı ayarları"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Kablosuz bağlantı kullanılamıyor"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera engellendi"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera ve mikrofon engellendi"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon engellendi"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Öncelik modu etkin"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Asistan dinliyor"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tr/tiles_states_strings.xml b/packages/SystemUI/res/values-tr/tiles_states_strings.xml
index 28ba7dcb9010..a8c7f784920d 100644
--- a/packages/SystemUI/res/values-tr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-tr/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Kapalı"</item>
<item msgid="5966994759929723339">"Açık"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Kullanılamıyor"</item>
+ <item msgid="2478289035899842865">"Kapalı"</item>
+ <item msgid="5137565285664080143">"Açık"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 824e64a15d97..c24f858e1154 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Панель сповіщень."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Швидке налаштування."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Швидкі налаштування й панель сповіщень."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Заблокований екран."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Екран блокування завдання"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Закрити"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Яскравість"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Інверсія кольорів"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Корекція кольору"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Розмір шрифту"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Керувати користувачами"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Готово"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Закрити"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Сповіщення"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Комбінації клавіш"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Змінити розкладку клавіатури"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Видалити текст"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Швидкі команди"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Пошук швидких команд"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Швидк. команд не знайдено"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Система"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Метод введення"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Відкр. додатки"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Поточн. додаток"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Відкрити панель сповіщень"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Зробити знімок усього екрана"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Відкрити список системних ярликів і ярликів додатків"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Назад: повернутися до попереднього стану (кнопка \"Назад\")"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Перейти на головний екран"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Огляд відкритих додатків"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Перемикатися між останніми додатками (уперед)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Перемикатися між останніми додатками (назад)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Відкрити список усіх додатків і запитів (Пошук/Панель запуску)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Сховати або знову показати панель завдань"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Відкрити налаштування системи"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Відкрити Google Асистента"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Заблокувати екран"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Відкривати додаток \"Нотатки\" для швидких приміток"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Багатозадачність системи"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Розділити екран із поточним додатком праворуч"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Розділити екран із поточним додатком ліворуч"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Перемкнути з розділеного екрана на весь екран"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Під час розділення екрана: замінити додаток іншим"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Метод введення"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Змінити мову введення (наступна мова)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Змінити мову введення (попередня мова)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Відкрити смайли"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Відкрити голосовий ввід"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Додатки"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Помічник"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Веб-переглядач"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Веб-переглядач (за умовчанням – Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Контакти"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Електронна пошта"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Електронна пошта (за умовчанням – Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Музика"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Календар"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Калькулятор"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Карти"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Не турбувати"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Кнопки гучності на корпусі"</string>
<string name="battery" msgid="769686279459897127">"Акумулятор"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"запис відео з екрана"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Без назви"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Режим очікування"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Розмір шрифту"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Зменшити"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Збільшити"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Вікно збільшення"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Елементи керування вікна збільшення"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Наблизити"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"Сталася помилка. Повторіть спробу."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Завантаження"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"планшет"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"Трансляція медіаконтенту"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"Трансляція додатка <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Неактивно, перейдіть у додаток"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Не знайдено"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Елемент керування недоступний"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Неможливо транслювати"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Не вдалося зберегти. Повторіть спробу."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Не вдалося зберегти."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Введіть принаймні 4 символи"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Введіть менше ніж 16 символів"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Номер складання"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Номер складання скопійовано в буфер обміну."</string>
<string name="basic_status" msgid="2315371112182658176">"Відкрита розмова"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Принаймні один пристрій доступний"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Натисніть і утримуйте ярлик"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Скасувати"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Перевернути"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Розгорніть телефон, щоб зробити краще селфі"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Перемкнути на фронтальну камеру для кращого селфі?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Використовуйте камеру на задній панелі, щоб зробити знімок із ширшим кутом і вищою роздільною здатністю."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Цей екран вимкнеться"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Використовувати інший екран"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Розгорніть телефон"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Використовувати інший екран?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Для вищої роздільної здатності використовуйте основну камеру"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Для вищої роздільної здатності переверніть телефон"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Розкладний пристрій у розкладеному стані"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Розкладний пристрій обертається"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Заряд акумулятора: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Перейти в робочий профіль"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Закрити"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Параметри заблокованого екрана"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Мережа Wi-Fi недоступна"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камеру заблоковано"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камеру й мікрофон заблоковано"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Мікрофон заблоковано"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Режим пріоритету ввімкнено"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Асистента активовано"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uk/tiles_states_strings.xml b/packages/SystemUI/res/values-uk/tiles_states_strings.xml
index 3f6ca461ac1d..4062f1be4c08 100644
--- a/packages/SystemUI/res/values-uk/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-uk/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Вимкнено"</item>
<item msgid="5966994759929723339">"Увімкнено"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Недоступно"</item>
+ <item msgid="2478289035899842865">"Вимкнено"</item>
+ <item msgid="5137565285664080143">"Увімкнено"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index a72bbc26f8ce..17ff36b09f63 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -93,8 +93,8 @@
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"دایاں احاطہ <xliff:g id="PERCENT">%1$d</xliff:g> فیصد"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"دفتری پروفائل میں <xliff:g id="APP">%1$s</xliff:g> میں محفوظ کی گئی"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"فائلز"</string>
- <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> نے اس اسکرین شاٹ کا پتا لگایا۔"</string>
- <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> اور دیگر کھلی ایپس نے اس اسکرین شاٹ کا پتا لگایا۔"</string>
+ <string name="screenshot_detected_template" msgid="7940376642921719915">"‫<xliff:g id="APPNAME">%1$s</xliff:g> نے اس اسکرین شاٹ کا پتا لگایا۔"</string>
+ <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"‫<xliff:g id="APPNAME">%1$s</xliff:g> اور دیگر کھلی ایپس نے اس اسکرین شاٹ کا پتا لگایا۔"</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"نوٹ میں شامل کریں"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"اسکرین ریکارڈر"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"سکرین ریکارڈنگ پروسیس ہورہی ہے"</string>
@@ -188,8 +188,8 @@
<string name="accessibility_battery_level" msgid="5143715405241138822">"بیٹری <xliff:g id="NUMBER">%d</xliff:g> فیصد۔"</string>
<string name="accessibility_battery_level_with_estimate" msgid="6548654589315074529">"بیٹری <xliff:g id="PERCENTAGE">%1$d</xliff:g> فیصد ہے، <xliff:g id="TIME">%2$s</xliff:g> تک چلے گی"</string>
<string name="accessibility_battery_level_charging" msgid="8892191177774027364">"بیٹری چارج ہو رہی ہے، اس وقت <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> فیصد ہے۔"</string>
- <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"بیٹری <xliff:g id="PERCENTAGE">%d</xliff:g> فیصد پے، بیٹری کے تحفظ کے لیے چارجنگ موقوف ہو گئی ہے۔"</string>
- <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"بیٹری <xliff:g id="PERCENTAGE">%1$d</xliff:g> فیصد پے، <xliff:g id="TIME">%2$s</xliff:g> تک چلے گی، بیٹری کے تحفظ کے لیے چارجنگ موقوف ہو گئی ہے۔"</string>
+ <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"بیٹری <xliff:g id="PERCENTAGE">%d</xliff:g> فیصد، بیٹری کے تحفظ کے لیے چارجنگ موقوف ہو گئی ہے۔"</string>
+ <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"بیٹری <xliff:g id="PERCENTAGE">%1$d</xliff:g> فیصد، <xliff:g id="TIME">%2$s</xliff:g>، بیٹری کے تحفظ کے لیے چارجنگ موقوف ہو گئی ہے۔"</string>
<string name="accessibility_overflow_action" msgid="8555835828182509104">"تمام اطلاعات دیکھیں"</string>
<string name="accessibility_tty_enabled" msgid="1123180388823381118">"ٹیلی ٹائپ رائٹر فعال ہے۔"</string>
<string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"رنگر وائبریٹ۔"</string>
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"اطلاعاتی شیڈ۔"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"فوری ترتیبات۔"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"فوری ترتیبات اور اطلاعاتی شیڈ۔"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"مقفل اسکرین۔"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"دفتری مقفل اسکرین"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"بند کریں"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"چمکیلا پن"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"رنگوں کی تقلیب"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"رنگ کی اصلاح"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"فونٹ سائز"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"صارفین کا نظم کریں"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"ہو گیا"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"بند کریں"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"اطلاعات"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"کی بورڈ شارٹ کٹس"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"کی بورڈ لے آؤٹ سوئچ کریں"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"ٹیکسٹ صاف کریں"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"شارٹ کٹس"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"شارٹ کٹس تلاش کریں"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"کوئی شارٹ کٹ نہیں ملا"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"سسٹم"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"ان پٹ"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"ایپس کھولیں"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"موجودہ ایپ"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"اطلاعاتی شیڈ تک رسائی حاصل کریں"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"پوری اسکرین شاٹ لیں"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"سسٹم / ایپس شارٹ کٹس کی فہرست تک رسائی حاصل کریں"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"پیچھے: گزشتہ حالت پر واپس جائیں (پیچھے جانے کا بٹن)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"ہوم اسکرین تک رسائی حاصل کریں"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"کھلی ایپس کا مجموعی جائزہ"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"حالیہ ایپس میں یکے بعد دیگرے جائیں (آگے جائیں)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"حالیہ ایپس میں یکے بعد دیگرے جائیں (پیچھے جائیں)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"تمام ایپس اور تلاش کی فہرست تک رسائی حاصل کریں (یعنی تلاش/لانچر)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"ٹاسک بار کو چھپائیں اور (دوبارہ) دکھائیں"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"سسٹم کی ترتیبات تک رسائی"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"‏Google اسسٹنٹ تک رسائی حاصل کریں"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"مقفل اسکرین"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"فوری میمو کے ليے نوٹس ایپ حاصل کریں"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"سسٹم ملٹی ٹاسکنگ"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"موجودہ ایپ کے ساتھ دائیں جانب اسپلٹ اسکرین انٹر کریں"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"موجودہ ایپ کے ساتھ بائیں جانب اسپلٹ اسکرین انٹر کریں"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"اسپلٹ اسکرین سے پوری سکرین پر سوئچ کریں"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"اسپلٹ اسکرین کے دوران: ایک ایپ کو دوسرے سے تبدیل کریں"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"ان پٹ"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"ان پٹ زبان سوئچ کریں (اگلی زبان)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"ان پٹ زبان سوئچ کریں (گزشتہ زبان)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"ایموجی تک رسائی"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"صوتی ٹائپنگ تک رسائی"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"ایپلیکیشنز"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"اسسٹ"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"براؤزر"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"‏براؤزر (بطور ڈیفالٹ Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"رابطے"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"ای میل"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"‏ای میل (بطور ڈیفالٹ Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"موسیقی"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"کیلنڈر"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"کیلکولیٹر"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"ڈسٹرب نہ کریں"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"والیوم بٹنز کے شارٹ کٹ"</string>
<string name="battery" msgid="769686279459897127">"بیٹری"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"اسکرین ریکارڈنگ"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"کوئی عنوان نہیں ہے"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"اسٹینڈ بائی"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"فونٹ سائز"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"چھوٹا کریں"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"بڑا کریں"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"میگنیفکیشن ونڈو"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"میگنیفکیشن ونڈو کنٹرولز"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"زوم ان کریں"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"کچھ غلط ہوگیا۔ پھر کوشش کریں۔"</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"لوڈ ہو رہا ہے"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"ٹیبلیٹ"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"آپ کا میڈیا کاسٹ ہو رہا ہے"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"<xliff:g id="APP_LABEL">%1$s</xliff:g> کاسٹ ہو رہا ہے"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"غیر فعال، ایپ چیک کریں"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"نہیں ملا"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"کنٹرول دستیاب نہیں ہے"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"براڈکاسٹ نہیں کیا جا سکتا"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"محفوظ نہیں کیا جا سکا۔ پھر کوشش کریں۔"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"محفوظ نہیں کیا جا سکا۔"</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"کم از کم 4 حروف استعمال کریں"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"16 حروف سے کم استعمال کریں"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"بلڈ نمبر"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"بلڈ نمبر کلپ بورڈ میں کاپی ہو گیا۔"</string>
<string name="basic_status" msgid="2315371112182658176">"گفتگو کھولیں"</string>
@@ -1045,12 +1080,12 @@
<string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"نامعلوم"</string>
<string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"h:mm"</string>
<string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string>
- <string name="log_access_confirmation_title" msgid="4843557604739943395">"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> کو آلے کے تمام لاگز تک رسائی کی اجازت دیں؟"</string>
+ <string name="log_access_confirmation_title" msgid="4843557604739943395">"‫<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> کو آلے کے تمام لاگز تک رسائی کی اجازت دیں؟"</string>
<string name="log_access_confirmation_allow" msgid="752147861593202968">"یک وقتی رسائی کی اجازت دیں"</string>
<string name="log_access_confirmation_deny" msgid="2389461495803585795">"اجازت نہ دیں"</string>
<string name="log_access_confirmation_body" msgid="6883031912003112634">"آپ کے آلے پر جو ہوتا ہے آلے کے لاگز اسے ریکارڈ کر لیتے ہیں۔ ایپس ان لاگز کا استعمال مسائل کو تلاش کرنے اور ان کو حل کرنے کے لیے کر سکتی ہیں۔\n\nکچھ لاگز میں حساس معلومات شامل ہو سکتی ہیں، اس لیے صرف اپنی بھروسے مند ایپس کو ہی آلے کے تمام لاگز تک رسائی کی اجازت دیں۔ \n\nاگر آپ اس ایپ کو آلے کے تمام لاگز تک رسائی کی اجازت نہیں دیتے ہیں تب بھی یہ اپنے لاگز تک رسائی حاصل کر سکتی ہے۔ آپ کے آلے کا مینوفیکچرر اب بھی آپ کے آلے پر کچھ لاگز یا معلومات تک رسائی حاصل کر سکتا ہے۔"</string>
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"مزید جانیں"</string>
- <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"<xliff:g id="URL">%s</xliff:g> پر مزید جانیں"</string>
+ <string name="log_access_confirmation_learn_more_at" msgid="5635666259505215905">"مزید جاننے کیلئے <xliff:g id="URL">%s</xliff:g> ملاحظہ کریں"</string>
<string name="keyguard_affordance_enablement_dialog_action_template" msgid="8164857863036314664">"<xliff:g id="APPNAME">%1$s</xliff:g> کھولیں"</string>
<string name="keyguard_affordance_enablement_dialog_wallet_instruction_1" msgid="8439655049139819278">"• ایپ سیٹ اپ ہو گئی ہے"</string>
<string name="keyguard_affordance_enablement_dialog_wallet_instruction_2" msgid="4321089250629477835">"• والٹ میں کم از کم ایک کارڈ شامل کیا گیا ہے"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• کم از کم ایک آلہ دستیاب ہے"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"شارٹ کٹ ٹچ کریں اور دبائے رکھیں"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"منسوخ کریں"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"اب پلٹائیں"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"بہتر سیلفی کے لیے فون کھولیں"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"بہتر سیلفی کے لیے سامنے والے ڈسپلے پر پلٹائیں؟"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"اعلی ریزولیوشن والی وسیع تصویر کے لیے ییچھے والا کیمرا استعمال کریں۔"</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ یہ اسکرین آف ہو جائے گی"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"اب اسکرینز سوئچ کریں"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"فون کھولیں"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"اسکرینز سوئچ کریں؟"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"زیادہ ریزولوشن کے لیے، بَیک کیمرا استعمال کریں"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"زیادہ ریزولوشن کے لیے، فون پلٹائیں"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"فولڈ ہونے والے آلے کو کھولا جا رہا ہے"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"فولڈ ہونے والے آلے کو گھمایا جا رہا ہے"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> بیٹری باقی ہے"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"دفتری پروفائل پر سوئچ کریں"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"بند کریں"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"مقفل اسکرین کی ترتیبات"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"‏Wi-Fi دستیاب نہیں ہے"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"کیمرا مسدود ہے"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"کیمرا اور مائیکروفون مسدود ہے"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"مائیکروفون مسدود ہے"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"ترجیحی موڈ آن ہے"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"اسسٹنٹ کی توجہ آن ہے"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ur/tiles_states_strings.xml b/packages/SystemUI/res/values-ur/tiles_states_strings.xml
index 05aa4e91e5cc..bb27b9fbe9f2 100644
--- a/packages/SystemUI/res/values-ur/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ur/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"آف"</item>
<item msgid="5966994759929723339">"آن"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"دستیاب نہیں ہیں"</item>
+ <item msgid="2478289035899842865">"آف ہے"</item>
+ <item msgid="5137565285664080143">"آن ہے"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 31dd7c12955c..0046e04105f0 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -93,8 +93,8 @@
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Oʻng chegara <xliff:g id="PERCENT">%1$d</xliff:g> foiz"</string>
<string name="screenshot_work_profile_notification" msgid="203041724052970693">"Ish profilidagi <xliff:g id="APP">%1$s</xliff:g> ilovasiga saqlandi"</string>
<string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Fayllar"</string>
- <string name="screenshot_detected_template" msgid="7940376642921719915">"Bu skrinshotda <xliff:g id="APPNAME">%1$s</xliff:g> aniqlandi."</string>
- <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"Bu skrinshotda <xliff:g id="APPNAME">%1$s</xliff:g> va boshqa ochiq ilovalar aniqlandi"</string>
+ <string name="screenshot_detected_template" msgid="7940376642921719915">"<xliff:g id="APPNAME">%1$s</xliff:g> skrinshot olinganini aniqladi."</string>
+ <string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> va boshqa ochiq ilovalar skrinshot olinganini aniqladi."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Qaydga qoʻshish"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Ekrandan yozib olish"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekran yozib olinmoqda"</string>
@@ -188,8 +188,8 @@
<string name="accessibility_battery_level" msgid="5143715405241138822">"Batareya <xliff:g id="NUMBER">%d</xliff:g> foiz."</string>
<string name="accessibility_battery_level_with_estimate" msgid="6548654589315074529">"Batareya <xliff:g id="PERCENTAGE">%1$d</xliff:g> foiz, <xliff:g id="TIME">%2$s</xliff:g> yetadi."</string>
<string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Batareya quvvat olmoqda, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> foiz."</string>
- <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"Batareya <xliff:g id="PERCENTAGE">%d</xliff:g> foiz, batareya himoyasi uchun quvvatlash toʻxtatildi."</string>
- <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"Batareya <xliff:g id="PERCENTAGE">%1$d</xliff:g> foiz, <xliff:g id="TIME">%2$s</xliff:g> yetadi, batareya himoyasi uchun quvvatlash toʻxtatildi."</string>
+ <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"Batareya <xliff:g id="PERCENTAGE">%d</xliff:g> foiz, batareya himoyasi uchun quvvatlash pauza qilindi."</string>
+ <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"Batareya <xliff:g id="PERCENTAGE">%1$d</xliff:g> foiz, <xliff:g id="TIME">%2$s</xliff:g>, batareya himoyasi uchun quvvatlash pauza qilindi."</string>
<string name="accessibility_overflow_action" msgid="8555835828182509104">"Barcha bildirishnomalarni ko‘rish"</string>
<string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter yoqildi."</string>
<string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Vibratsiyali qo‘ng‘iroq"</string>
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Xabarnoma soyasi."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Tezkor sozlamalar."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Tezkor sozlamalar va eslatma soyasi."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Qulflash ekrani."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ishchi ekran qulfi"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Yopish"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Yorqinlik"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Ranglarni akslantirish"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Ranglarni tuzatish"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Shrift oʻlchami"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Foydalanuvchilarni boshqarish"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Tayyor"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Yopish"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Bildirishnomalar"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Tezkor tugmalar"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Klaviatura terilmasini almashtirish"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Matnni tozalash"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Tezkor tugmalar"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Tezkor tugmalar qidiruvi"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Tezkor tugmalar topilmadi"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Tizim"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Kiritish"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Ochiq ilovalar"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Joriy ilova"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Bildirishnoma soyasiga ruxsat"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Butun skrinshot olish"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Tizim va ilovalar tezkor tugmalari roʻyxatiga ruxsat"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Orqaga: avvalgi holatga qaytish (orqaga tugmasi)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Bosh ekranga ruxsat"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Ochiq ilovalar bilan tanishish"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Oxirgi ilovalarni varaqlash (faol rejimda)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Oxirgi ilovalarni varaqlash (fonda)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Barcha ilovalar va qidiruv roʻyxatiga ruxsat (Qidiruv/Launcher kabi)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Vazifalar panelini ochish va yopish"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Tizim sozlamalariga ruxsat"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Google Assistentga ruxsat"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Ekran qulfi"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Tezkor eslatma uchun Qaydlar ilovasini ochish"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Tizimdagi multi-vazifalik"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Oʻng tomondagi ajratilgan ekran rejimiga kirish"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Chap tomondagi ajratilgan ekran rejimiga kirish"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Ajratilgan ekran rejimidan butun ekranga qaytish"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Ajratilgan rejimda ilovalarni oʻzaro almashtirish"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Kiritish"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Kiritish tili tugmasi (keyingi til)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Kiritish tili tugmasi (avvalgi til)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Emojilarga ruxsat"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Ovoz bilan yozishga ruxsat"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Ilovalar"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Yordamchi"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Brauzer"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Brauzer (birlamchisi Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Kontaktlar"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Email"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Email (birlamchisi Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Musiqa"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Taqvim"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Kalkulyator"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Xaritalar"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Bezovta qilinmasin"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Ovoz balandligini boshqarish tugmalari"</string>
<string name="battery" msgid="769686279459897127">"Batareya"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ekranni yozuvi"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Nomsiz"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Kutib turing"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Shrift oʻlchami"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Kichiklashtirish"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Kattalashtirish"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Kattalashtirish oynasi"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kattalashtirish oynasi sozlamalari"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Yaqinlashtirish"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Uzatilmadi"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Saqlanmadi. Qayta urining."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Saqlanmadi."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Parolga kamida 4 ta belgi kiriting."</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Kiritiladigan belgilar 16 tadan oshmasin"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Nashr raqami"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Nashr raqami vaqtinchalik xotiraga nusxalandi."</string>
<string name="basic_status" msgid="2315371112182658176">"Suhbatni ochish"</string>
@@ -1043,8 +1080,8 @@
<string name="bt_le_audio_broadcast_dialog_unknown_name" msgid="3791472237793443044">"Noaniq"</string>
<string name="dream_time_complication_12_hr_time_format" msgid="4691197486690291529">"s:dd"</string>
<string name="dream_time_complication_24_hr_time_format" msgid="6248280719733640813">"kk:mm"</string>
- <string name="log_access_confirmation_title" msgid="4843557604739943395">"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> ilovasining qurilmadagi barcha jurnallarga kirishiga ruxsat berilsinmi?"</string>
- <string name="log_access_confirmation_allow" msgid="752147861593202968">"Bir matalik foydalanishga ruxsat berish"</string>
+ <string name="log_access_confirmation_title" msgid="4843557604739943395">"<xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g> uchun qurilmadagi barcha jurnallarga kirish ruxsati berilsinmi?"</string>
+ <string name="log_access_confirmation_allow" msgid="752147861593202968">"Bir martalik ruxsat berish"</string>
<string name="log_access_confirmation_deny" msgid="2389461495803585795">"Rad etish"</string>
<string name="log_access_confirmation_body" msgid="6883031912003112634">"Qurilma jurnaliga qurilma bilan yuz bergan hodisalar qaydlari yoziladi. Ilovalar bu jurnal qaydlari yordamida muammolarni topishi va bartaraf qilishi mumkin.\n\nAyrim jurnal qaydlarida maxfiy axborotlar yozilishi mumkin, shu sababli qurilmadagi barcha jurnal qaydlariga ruxsatni faqat ishonchli ilovalarga bering. \n\nBu ilovaga qurilmadagi barcha jurnal qaydlariga ruxsat berilmasa ham, u oʻzining jurnalini ocha oladi. Qurilma ishlab chiqaruvchisi ham ayrim jurnallar yoki qurilma haqidagi axborotlarni ocha oladi."</string>
<string name="log_access_confirmation_learn_more" msgid="3134565480986328004">"Batafsil"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Kamida bitta qurilma mavjud"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Bosib turish yorligʻi"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Bekor qilish"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Almashtirish"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Yaxshiroq selfi olish uchun telefonni yoying"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Yaxshiroq selfi uchun old ekranga almashilsinmi?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Keng burchakli va yuqori aniqlikda suratga olish uchun orqa kameradan foydalaning."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Bu ekran oʻchiriladi"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Ekranlarni hozir almashtirish"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Telefonni yoying"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Ekranlar almashtirilsinmi?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Yuqori aniqlik uchun orqa kameradan foydalaning"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Yuqori aniqlik uchun telefonni aylantiring"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Buklanadigan qurilma ochilmoqda"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Buklanadigan qurilma aylantirilmoqda"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Batareya quvvati: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Ish profiliga almashish"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Yopish"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Qulflangan ekran sozlamalari"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi mavjud emas"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera bloklangan"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera va mikrofon bloklangan"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon bloklangan"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Imtiyozli rejim yoniq"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistent diqqati yoniq"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uz/tiles_states_strings.xml b/packages/SystemUI/res/values-uz/tiles_states_strings.xml
index a84f7698d861..4a45f03f4cbe 100644
--- a/packages/SystemUI/res/values-uz/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-uz/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Oʻchiq"</item>
<item msgid="5966994759929723339">"Yoniq"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Mavjud emas"</item>
+ <item msgid="2478289035899842865">"Oʻchiq"</item>
+ <item msgid="5137565285664080143">"Yoniq"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 558cfdb06e27..0b488f8fb0cd 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Bóng thông báo."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Cài đặt nhanh."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Cài đặt nhanh và ngăn thông báo."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Màn hình khóa."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Màn hình khóa công việc"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Đóng"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Độ sáng"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Đảo màu"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Chỉnh màu"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Cỡ chữ"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Quản lý người dùng"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Xong"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Đóng"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Thông báo"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Phím tắt"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Chuyển đổi bố cục bàn phím"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Xoá văn bản"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Lối tắt"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Lối tắt tìm kiếm"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Không tìm thấy lối tắt"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Hệ thống"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Đầu vào"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Ứng dụng đang mở"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Ứng dụng hiện tại"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Truy cập ngăn thông báo"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Chụp toàn màn hình"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Danh sách truy cập lối tắt ứng dụng/hệ thống"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Quay lại: quay lại trạng thái trước đó (nút quay lại)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Truy cập màn hình khoá"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Tổng quan về những ứng dụng đang mở"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Xoay vòng qua các ứng dụng gần đây (xuôi)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Xoay vòng qua các ứng dụng gần đây (ngược)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"D.sách truy cập mọi ứng dụng/n.dung tìm kiếm (VD: Tìm kiếm/Trình chạy)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Ẩn và hiện (lại) thanh tác vụ"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Truy cập chế độ cài đặt hệ thống"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Truy cập Trợ lý Google"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Màn hình khoá"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Mở ứng dụng Ghi chú để ghi chú nhanh"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Xử lý đa nhiệm trong hệ thống"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Vào chế độ Chia đôi màn hình, ứng dụng hiện tại sang màn hình bên phải"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Vào chế độ Chia đôi màn hình, ứng dụng hiện tại sang màn hình bên trái"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Chuyển từ chế độ Chia đôi màn hình sang chế độ toàn màn hình"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Trong chế độ Chia đôi màn hình: thay ứng dụng này bằng ứng dụng khác"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Đầu vào"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Chuyển ngôn ngữ nhập (ngôn ngữ tiếp theo)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Chuyển ngôn ngữ nhập (ngôn ngữ trước đó)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Truy cập biểu tượng cảm xúc"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Truy cập tính năng nhập liệu bằng giọng nói"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Ứng dụng"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Trợ lý"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Trình duyệt"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Trình duyệt (mặc định là Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Danh bạ"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"Email"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Email (mặc định là Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Âm nhạc"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Lịch"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Máy tính"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Bản đồ"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Không làm phiền"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Phím tắt các nút âm lượng"</string>
<string name="battery" msgid="769686279459897127">"Pin"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ghi màn hình"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Không có tiêu đề"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Chế độ chờ"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Cỡ chữ"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Thu nhỏ"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Phóng to"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Cửa sổ phóng to"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Các tùy chọn điều khiển cửa sổ phóng to"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Phóng to"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"Đã xảy ra lỗi. Hãy thử lại."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Đang tải"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"máy tính bảng"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"Truyền nội dung đa phương tiện"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"Đang truyền <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Không hoạt động, hãy kiểm tra ứng dụng"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Không tìm thấy"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Không có chức năng điều khiển"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Không thể truyền"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Không lưu được. Hãy thử lại."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Không lưu được."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Sử dụng ít nhất 4 ký tự"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Sử dụng ít hơn 16 ký tự"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Số bản dựng"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Đã sao chép số bản dựng vào bảng nhớ tạm."</string>
<string name="basic_status" msgid="2315371112182658176">"Mở cuộc trò chuyện"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Có ít nhất một thiết bị đang hoạt động"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Chạm và giữ phím tắt"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Huỷ"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Lật ngay"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Mở điện thoại ra để tự chụp ảnh chân dung đẹp hơn"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Lật sang màn hình ngoài để tự chụp ảnh chân dung đẹp hơn?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Sử dụng máy ảnh sau để chụp ảnh góc rộng hơn với độ phân giải cao hơn."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Màn hình này sẽ tắt"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Chuyển đổi màn hình ngay"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Mở điện thoại"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Chuyển đổi màn hình?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Để có độ phân giải cao hơn, hãy dùng máy ảnh sau"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Để có độ phân giải cao hơn, hãy lật điện thoại"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Thiết bị có thể gập lại đang được mở ra"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Thiết bị có thể gập lại đang được lật ngược"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Còn <xliff:g id="PERCENTAGE">%s</xliff:g> pin"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Chuyển sang hồ sơ công việc"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Đóng"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Cài đặt màn hình khoá"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Không có Wi-Fi"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Máy ảnh bị chặn"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Máy ảnh và micrô bị chặn"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Micrô bị chặn"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Chế độ ưu tiên đang bật"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Trợ lý đang bật"</string>
</resources>
diff --git a/packages/SystemUI/res/values-vi/tiles_states_strings.xml b/packages/SystemUI/res/values-vi/tiles_states_strings.xml
index 482a32f902b4..201a45b3d445 100644
--- a/packages/SystemUI/res/values-vi/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-vi/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Tắt"</item>
<item msgid="5966994759929723339">"Đang bật"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Không có sẵn"</item>
+ <item msgid="2478289035899842865">"Đang tắt"</item>
+ <item msgid="5137565285664080143">"Đang bật"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 6ac74ad964a6..b5d0e01d1c91 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"通知栏。"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"快捷设置。"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"快捷设置和通知栏。"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"锁定屏幕。"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"工作锁定屏幕"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"关闭"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"亮度"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"颜色反转"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"色彩校正"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"字号"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"管理用户"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"完成"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"关闭"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"通知"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"键盘快捷键"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"切换键盘布局"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"清除文字"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"快捷键"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"搜索快捷键"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"未找到任何快捷键"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"系统"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"输入"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"打开的应用"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"当前应用"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"访问通知栏"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"截取全屏"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"访问系统/应用快捷方式的列表"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"返回:返回到上一个状态(返回按钮)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"访问主屏幕"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"已打开应用的概览"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"循环浏览近期使用的应用(向前)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"循环浏览近期使用的应用(向后)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"访问所有应用的列表并搜索所需应用(即搜索/启动器)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"隐藏和重新显示任务栏"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"访问系统设置"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"访问 Google 助理"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"锁定屏幕"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"调出记事应用快速做记录"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"系统多任务处理"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"进入分屏模式,当前应用显示于右侧"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"进入分屏模式,当前应用显示于左侧"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"从分屏模式切换为全屏"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"在分屏期间:将一个应用替换为另一个应用"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"输入"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"切换输入语言(下一种语言)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"切换输入语言(上一种语言)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"访问表情符号"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"访问语音输入"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"应用"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"助理"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"浏览器"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"浏览器(默认为 Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"通讯录"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"电子邮件"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"电子邮件(默认为 Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"短信"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"音乐"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"日历"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"计算器"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"地图"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"勿扰"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"音量按钮快捷键"</string>
<string name="battery" msgid="769686279459897127">"电池"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"屏幕录制"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"无标题"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"待机"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"字体大小"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"缩小"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"放大"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"放大窗口"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"放大窗口控件"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"放大"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"无法广播"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"无法保存,请重试。"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"无法保存。"</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"必须至少 4 个字符"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"必须少于 16 个字符"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"版本号"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"已将版本号复制到剪贴板。"</string>
<string name="basic_status" msgid="2315371112182658176">"开放式对话"</string>
@@ -981,7 +1018,7 @@
<string name="mobile_data_settings_title" msgid="3955246641380064901">"移动数据网络"</string>
<string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"已连接"</string>
- <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"暂时已连接"</string>
+ <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"已暂时连接"</string>
<string name="mobile_data_poor_connection" msgid="819617772268371434">"连接状况不佳"</string>
<string name="mobile_data_off_summary" msgid="3663995422004150567">"系统将不会自动连接到移动数据网络"</string>
<string name="mobile_data_no_connection" msgid="1713872434869947377">"无网络连接"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• 至少有一台设备可用"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"轻触并按住快捷方式"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"取消"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"立即翻转"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"展开手机可拍出更好的自拍照"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"翻转到外屏后自拍效果更好,要试试吗?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"您可以使用后置摄像头拍摄视角更广、分辨率更高的照片。"</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ 此屏幕将会关闭"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"立即切换屏幕"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"展开手机"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"切换屏幕?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"若要获得更高的分辨率,请使用后置摄像头"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"若要获得更高的分辨率,请翻转手机"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"正在展开可折叠设备"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"正在翻转可折叠设备"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"电池还剩 <xliff:g id="PERCENTAGE">%s</xliff:g> 的电量"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"切换到工作资料"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"关闭"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"锁屏设置"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"没有 WLAN 连接"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"已禁用摄像头"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"已禁用摄像头和麦克风"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"已禁用麦克风"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"已开启优先模式"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"已开启 Google 助理感知功能"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml b/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml
index 6ce948def69e..3ab2d7a3d1c7 100644
--- a/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"关闭"</item>
<item msgid="5966994759929723339">"已开启"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"不可用"</item>
+ <item msgid="2478289035899842865">"已关闭"</item>
+ <item msgid="5137565285664080143">"已开启"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index e0b042b9c555..cacf20530642 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -188,8 +188,8 @@
<string name="accessibility_battery_level" msgid="5143715405241138822">"電池電量為百分之 <xliff:g id="NUMBER">%d</xliff:g>。"</string>
<string name="accessibility_battery_level_with_estimate" msgid="6548654589315074529">"目前電池電量為 <xliff:g id="PERCENTAGE">%1$d</xliff:g>,剩餘使用時間為 <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="accessibility_battery_level_charging" msgid="8892191177774027364">"正在充電:<xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%。"</string>
- <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"目前電池電量為 <xliff:g id="PERCENTAGE">%d</xliff:g>。為保護電池,系統已暫停充電。"</string>
- <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"目前電池電量為 <xliff:g id="PERCENTAGE">%1$d</xliff:g>,剩餘使用時間為 <xliff:g id="TIME">%2$s</xliff:g>。為保護電池,系統已暫停充電。"</string>
+ <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"目前電池電量為百分之 <xliff:g id="PERCENTAGE">%d</xliff:g>。為保護電池,系統已暫停充電。"</string>
+ <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"目前電池電量為百分之 <xliff:g id="PERCENTAGE">%1$d</xliff:g>,剩餘使用時間為 <xliff:g id="TIME">%2$s</xliff:g>。為保護電池,系統已暫停充電。"</string>
<string name="accessibility_overflow_action" msgid="8555835828182509104">"睇所有通知"</string>
<string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter (TTY) 已啟用。"</string>
<string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"鈴聲震動。"</string>
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"通知欄。"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"快速設定。"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"快速設定和通知欄。"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"上鎖畫面。"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"工作螢幕鎖定"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"關閉"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"亮度"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"色彩反轉"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"色彩校正"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"字型大小"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"管理使用者"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"完成"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"關閉"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"通知"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"鍵盤快速鍵"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"切換鍵盤配置"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"清除文字"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"快速鍵"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"搜尋快速鍵"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"找不到快速鍵"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"系統"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"輸入"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"已開啟的應用程式"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"目前的應用程式"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"存取通知欄"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"擷取全螢幕截圖"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"存取系統/應用程式捷徑清單"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"返回:回到先前的狀態 (返回按鈕)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"存取主畫面"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"「已開啟的應用程式」概覽"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"輪流切換最近使用的應用程式 (前進)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"輪流切換最近使用的應用程式 (返回)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"存取所有應用程式的清單並搜尋 (即搜尋/啟動器)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"隱藏和顯示/重新顯示工作列"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"存取系統設定"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"存取「Google 助理」"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"上鎖畫面"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"開啟「筆記」應用程式快速寫筆記"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"系統多工處理"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"進入分割螢幕模式,並將目前的應用程式顯示在右側"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"進入分割螢幕模式,並將目前的應用程式顯示在左側"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"將分割螢幕切換為全螢幕"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"使用分割螢幕期間:更換應用程式"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"輸入"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"切換輸入語言 (下一個語言)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"切換輸入語言 (上一個語言)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"存取 Emoji"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"存取語音輸入內容"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"應用程式"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"小幫手"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"瀏覽器"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"瀏覽器 (預設為 Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"通訊錄"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"電郵"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"電郵 (預設為 Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"短訊"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"音樂"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"日曆"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"計算機"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"地圖"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"請勿騷擾"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"音量按鈕快速鍵"</string>
<string name="battery" msgid="769686279459897127">"電池"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"錄製螢幕畫面"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"無標題"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"待機"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"字型大小"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"縮小"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"放大"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"放大視窗"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"放大視窗控制項"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"放大"</string>
@@ -815,8 +854,8 @@
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"㩒一下就可以開無障礙功能。喺「設定」度自訂或者取代呢個按鈕。\n\n"<annotation id="link">"查看設定"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"將按鈕移到邊緣即可暫時隱藏"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"復原"</string>
- <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"已移除「<xliff:g id="FEATURE_NAME">%s</xliff:g>」快速鍵"</string>
- <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{已移除 # 個快速鍵}other{已移除 # 個快速鍵}}"</string>
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"已移除「<xliff:g id="FEATURE_NAME">%s</xliff:g>」捷徑"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{已移除 # 個捷徑}other{已移除 # 個捷徑}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"移去左上方"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"移去右上方"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"移到左下方"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"發生錯誤,請再試一次。"</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"正在載入"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"平板電腦"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"投放媒體"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"投放 <xliff:g id="APP_LABEL">%1$s</xliff:g> 內容"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"已停用,請檢查應用程式"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"找不到"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"無法使用控制功能"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"無法廣播"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"無法儲存,請再試一次。"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"無法儲存。"</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"請至少使用 4 個字元"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"請使用少於 16 個字元"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"版本號碼"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"版本號碼已複製到剪貼簿。"</string>
<string name="basic_status" msgid="2315371112182658176">"開啟對話"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• 至少一部裝置可用"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"輕觸並按住快速鍵"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"取消"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"立即翻轉"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"打開手機,即可拍攝更出色的自拍"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"要翻轉至前方螢幕拍攝更出色的自拍嗎?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"使用後置鏡頭,拍攝更廣角、解像度更高的相片。"</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ 此螢幕將關閉"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"立即切換螢幕"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"打開手機"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"要切換螢幕嗎?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"如要提高解像度,請使用後置鏡頭"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"如要提高解像度,請切換至手機後置鏡頭"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"正在展開折疊式裝置"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"正在翻轉折疊式裝置"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"剩餘電量:<xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"切換至工作設定檔"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"關閉"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"上鎖畫面設定"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"無法連線至 Wi-Fi"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"已封鎖相機"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"已封鎖相機和麥克風"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"已封鎖麥克風"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"優先模式已開啟"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"「Google 助理」感應功能已開啟"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml b/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml
index ab8e961a1f47..89d66284ede6 100644
--- a/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"已關閉"</item>
<item msgid="5966994759929723339">"已開啟"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"無法使用"</item>
+ <item msgid="2478289035899842865">"關閉"</item>
+ <item msgid="5137565285664080143">"開啟"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index dff61697b9a4..3fbdd487534d 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"通知欄。"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"快捷設定。"</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"快速設定和通知欄。"</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"螢幕鎖定。"</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Work 螢幕鎖定"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"關閉"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"亮度"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"色彩反轉"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"色彩校正"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"字型大小"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"管理使用者"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"完成"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"關閉"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"通知"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"鍵盤快速鍵"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"切換鍵盤配置"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"清除文字"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"快速鍵"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"搜尋快速鍵"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"找不到快速鍵"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"系統"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"輸入"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"已開啟的應用程式"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"目前的應用程式"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"存取通知欄"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"拍攝全螢幕截圖"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"存取系統/應用程式捷徑清單"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"返回:回到先前的狀態 (返回按鈕)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"存取主畫面"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"「已開啟的應用程式」總覽"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"循環切換最近使用的應用程式 (前進)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"循環切換最近使用的應用程式 (返回)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"存取所有應用程式的清單並進行搜尋 (即搜尋/啟動器)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"隱藏和顯示/重新顯示工作列"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"存取系統設定"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"存取 Google 助理"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"螢幕鎖定"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"打開「記事」應用程式快速做筆記"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"系統多工處理"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"進入分割畫面模式,並將目前的應用程式顯示於右側"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"進入分割畫面模式,並將目前的應用程式顯示於左側"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"從分割畫面切換到完整畫面"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"使用分割畫面期間:更換應用程式"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"輸入"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"切換輸入語言 (下一個語言)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"切換輸入語言 (上一個語言)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"存取表情符號"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"存取語音輸入內容"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"應用程式"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"小幫手"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"瀏覽器"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"瀏覽器 (預設為 Chrome)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"聯絡人"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"電子郵件"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"電子郵件 (預設為 Gmail)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"簡訊"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"音樂"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"日曆"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"計算機"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"地圖"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"零打擾"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"音量按鈕快速鍵"</string>
<string name="battery" msgid="769686279459897127">"電池"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"錄製螢幕畫面"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"無標題"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"待機"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"字型大小"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"縮小"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"放大"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"放大視窗"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"放大視窗控制項"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"放大"</string>
@@ -889,10 +928,8 @@
<string name="media_transfer_failed" msgid="7955354964610603723">"發生錯誤,請再試一次。"</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"載入中"</string>
<string name="media_ttt_default_device_type" msgid="4457646436153370169">"平板電腦"</string>
- <!-- no translation found for media_transfer_receiver_content_description_unknown_app (7381771464846263667) -->
- <skip />
- <!-- no translation found for media_transfer_receiver_content_description_with_app_name (8555975056850659389) -->
- <skip />
+ <string name="media_transfer_receiver_content_description_unknown_app" msgid="7381771464846263667">"投放媒體"</string>
+ <string name="media_transfer_receiver_content_description_with_app_name" msgid="8555975056850659389">"投放「<xliff:g id="APP_LABEL">%1$s</xliff:g>」的內容"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"無效,請查看應用程式"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"找不到控制項"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"無法使用控制項"</string>
@@ -929,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"無法廣播"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"無法儲存,請再試一次。"</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"無法儲存。"</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"至少要有 4 個半形字元"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"不得超過 16 個半形字元"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"版本號碼"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"已將版本號碼複製到剪貼簿。"</string>
<string name="basic_status" msgid="2315371112182658176">"開放式對話"</string>
@@ -1059,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• 至少要有一部可用裝置"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"按住快速鍵"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"取消"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"立即翻轉"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"打開手機自拍效果較佳"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"要翻轉到前螢幕拍攝更優質的自拍照嗎?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"使用後置鏡頭可拍攝視角較寬廣、解析度較高的相片。"</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ 這麼做會關閉這個螢幕"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"立即切換螢幕"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"展開手機"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"要切換螢幕嗎?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"如要提高解析度,請使用後置鏡頭"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"如要提高解析度,請切換至手機後置鏡頭"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"正在展開的折疊式裝置"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"正在翻轉折疊式裝置"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"剩餘電量:<xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
@@ -1075,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"切換至工作資料夾"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"關閉"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"螢幕鎖定設定"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"無法連上 Wi-Fi"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"已封鎖攝影機"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"已封鎖攝影機和麥克風"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"已封鎖麥克風"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"優先模式已開啟"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Google 助理感知功能已開啟"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml b/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml
index 3d6a546e6103..a046e3354729 100644
--- a/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"已關閉"</item>
<item msgid="5966994759929723339">"已開啟"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"無法使用"</item>
+ <item msgid="2478289035899842865">"關閉"</item>
+ <item msgid="5137565285664080143">"開啟"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 3e8a5f988fb6..8039ca14ad3a 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -198,6 +198,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Umthunzi wesaziso."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Izilingiselelo ezisheshayo."</string>
+ <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Amasethingi asheshayo Nomthunzi wezaziso."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Khiya isikrini."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ukukhiya isikrini somsebenzi"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"Vala"</string>
@@ -258,6 +259,7 @@
<string name="quick_settings_brightness_dialog_title" msgid="4980669966716685588">"Ukugqama"</string>
<string name="quick_settings_inversion_label" msgid="3501527749494755688">"Ukuguqulwa kombala"</string>
<string name="quick_settings_color_correction_label" msgid="5636617913560474664">"Ukulungiswa kombala"</string>
+ <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"Usayizi wefonti"</string>
<string name="quick_settings_more_user_settings" msgid="7634653308485206306">"Phatha abasebenzisi"</string>
<string name="quick_settings_done" msgid="2163641301648855793">"Kwenziwe"</string>
<string name="quick_settings_close_user_panel" msgid="5599724542275896849">"Vala"</string>
@@ -613,14 +615,48 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Izaziso"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Izinqamulelo Zekhibhodi"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Shintsha isakhiwo sekhibhodi"</string>
+ <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Sula umbhalo"</string>
+ <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Izinqamuleli"</string>
+ <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Sesha izinqamuleli"</string>
+ <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Azikho izinqamuleli ezitholakele"</string>
+ <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Isistimu"</string>
+ <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Okokufaka"</string>
+ <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Vula ama-app"</string>
+ <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"I-app yamanje"</string>
+ <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Finyelela umthunzi wesaziso"</string>
+ <string name="group_system_full_screenshot" msgid="7389040853798023211">"Thatha isithombe-skrini esigcwele"</string>
+ <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Uhlu lokufinyelela lwezinqamuleli zesistimu / zama-app"</string>
+ <string name="group_system_go_back" msgid="8838454003680364227">"Emuva: buyela esimweni sangaphambilini (inkinobho yokubuyela emuva)"</string>
+ <string name="group_system_access_home_screen" msgid="1857344316928441909">"Finyelela isikrini sasekhaya"</string>
+ <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Amazwibela ama-app avuliwe"</string>
+ <string name="group_system_cycle_forward" msgid="9202444850838205990">"Zungeza ama-app akamuva (phambili)"</string>
+ <string name="group_system_cycle_back" msgid="5163464503638229131">"Zungeza ama-app akamuva (emuva)"</string>
+ <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Uhlu lokufinyelela lawo wonke ama-app nokusesha (isb, Sesha/Isiqalisa)"</string>
+ <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Fihla futhi ubonise(kabusha) ibha yomsebenzi"</string>
+ <string name="group_system_access_system_settings" msgid="7961639365383008053">"Finyelela amasethingi esistimu"</string>
+ <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Finyelela ku-Google Assistant"</string>
+ <string name="group_system_lock_screen" msgid="7391191300363416543">"Khiya isikrini"</string>
+ <string name="group_system_quick_memo" msgid="2914234890158583919">"Donsela phezulu i-app yamanothi ukuze uthole imemo esheshayo"</string>
+ <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Ukwenza imisebenzi eminingi yesistimu"</string>
+ <string name="system_multitasking_rhs" msgid="6593269428880305699">"Faka Ukuhlukanisa isikrini nge-app yamanje kuya ku-RHS"</string>
+ <string name="system_multitasking_lhs" msgid="8839380725557952846">"Faka Ukuhlukanisa isikrini nge-app yamanje kuya ku-LHS"</string>
+ <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Shintsha usuka Ekuhlukaniseni isikrini uye kusikrini esigcwele"</string>
+ <string name="system_multitasking_replace" msgid="844285282472557186">"Ngesikhathi sokuhlukaniswa kwesikrini: shintsha i-app ngenye"</string>
+ <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Okokufaka"</string>
+ <string name="input_switch_input_language_next" msgid="3394291576873633793">"Shintsha ulimi lokokufaka (ulimi olulandelayo)"</string>
+ <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Shintsha ulimi lokokufaka (ulimi lwangaphambilini)"</string>
+ <string name="input_access_emoji" msgid="8105642858900406351">"Finyelela i-emoji"</string>
+ <string name="input_access_voice_typing" msgid="7291201476395326141">"Finyelela ukuthayipha ngezwi"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Izinhlelo zokusebenza"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Siza"</string>
- <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"Isiphequluli"</string>
+ <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Ibhrawuza (i-Chrome yokuzenzakalelayo)"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Oxhumana nabo"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"I-imeyili"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"I-imeyili (i-Gmail yokuzenzakalelayo)"</string>
<string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"I-SMS"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Umculo"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Ikhalenda"</string>
+ <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Isibali"</string>
+ <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"I-Maps"</string>
<string name="volume_and_do_not_disturb" msgid="502044092739382832">"Ungaphazamisi"</string>
<string name="volume_dnd_silent" msgid="4154597281458298093">"Izinqamuleli zezinkinobho zevolomu"</string>
<string name="battery" msgid="769686279459897127">"Ibhethri"</string>
@@ -783,6 +819,9 @@
<string name="privacy_type_media_projection" msgid="8136723828804251547">"ukurekhoda isikrini"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Asikho isihloko"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Ilindile"</string>
+ <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Usayizi Wefonti"</string>
+ <string name="font_scaling_smaller" msgid="1012032217622008232">"Yenza kube kuncane"</string>
+ <string name="font_scaling_larger" msgid="5476242157436806760">"Yenza kube kukhulu"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Iwindi Lesikhulisi"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Izilawuli Zewindi Lesikhulisi"</string>
<string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Sondeza"</string>
@@ -927,10 +966,8 @@
<string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Ayikwazi ukusakaza"</string>
<string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Ayikwazi ukulondoloza. Zama futhi."</string>
<string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Ayikwazi ukulondoloza."</string>
- <!-- no translation found for media_output_broadcast_code_hint_no_less_than_min (4663836092607696185) -->
- <skip />
- <!-- no translation found for media_output_broadcast_code_hint_no_more_than_max (9181869364856175638) -->
- <skip />
+ <string name="media_output_broadcast_code_hint_no_less_than_min" msgid="4663836092607696185">"Sebenzisa okungenani izinhlamvu ezi-4"</string>
+ <string name="media_output_broadcast_code_hint_no_more_than_max" msgid="9181869364856175638">"Sebenzisa isinhlamvu ezimbalwa kuneziyi-16"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Yakha inombolo"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Yakha inombolo ekopishelwe kubhodi yokunamathisela."</string>
<string name="basic_status" msgid="2315371112182658176">"Vula ingxoxo"</string>
@@ -1057,11 +1094,11 @@
<string name="keyguard_affordance_enablement_dialog_home_instruction_2" msgid="8308525385889021652">"• Okungenani idivayisi eyodwa iyatholakala"</string>
<string name="keyguard_affordance_press_too_short" msgid="8145437175134998864">"Thinta futhi ubambe isinqamuleli"</string>
<string name="rear_display_bottom_sheet_cancel" msgid="3461468855493357248">"Khansela"</string>
- <string name="rear_display_bottom_sheet_confirm" msgid="4383356544661421206">"Phendula manje"</string>
- <string name="rear_display_fold_bottom_sheet_title" msgid="6081542277622721548">"Vula ifoni ukuze ube nesithombe ozishuthe sona esingcono"</string>
- <string name="rear_display_unfold_bottom_sheet_title" msgid="2137403802960396357">"Phendulela kwisibonisi sangaphambili ukuba nesithombe ozishuthe sona esingcono?"</string>
- <string name="rear_display_bottom_sheet_description" msgid="1852662982816810352">"Sebenzisa ikhamera ebheke ngemuva ukuze uthole isithombe esibanzi esinokucaca okuphezulu."</string>
- <string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Lesi sikrini sizovala"</b></string>
+ <string name="rear_display_bottom_sheet_confirm" msgid="1507591562761552899">"Shintsha izikrini manje"</string>
+ <string name="rear_display_folded_bottom_sheet_title" msgid="3930008746560711990">"Vula ifoni"</string>
+ <string name="rear_display_unfolded_bottom_sheet_title" msgid="6291111173057304055">"Shintsha izikrini?"</string>
+ <string name="rear_display_folded_bottom_sheet_description" msgid="6842767125783222695">"Ukuze uthole ukulungiswa okuphezulu, sebenzisa ikhamera yangemuva"</string>
+ <string name="rear_display_unfolded_bottom_sheet_description" msgid="7229961336309960201">"Ukuze uthole ukulungiswa okuphezulu, phendula ifoni"</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Idivayisi egoqekayo iyembulwa"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Idivayisi egoqekayo iphendulwa nxazonke"</string>
<string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> ibhethri elisele"</string>
@@ -1073,4 +1110,10 @@
<string name="call_from_work_profile_action" msgid="2937701298133010724">"Shintshela kuphrofayela yomsebenzi"</string>
<string name="call_from_work_profile_close" msgid="7927067108901068098">"Vala"</string>
<string name="lock_screen_settings" msgid="9197175446592718435">"Amasethingi okukhiya isikrini"</string>
+ <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"I-Wi-Fi ayitholakali"</string>
+ <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Ikhamera ivinjiwe"</string>
+ <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Ikhamera nemakrofoni zivinjiwe"</string>
+ <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Imakrofoni ivinjiwe"</string>
+ <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Imodi ebalulekile ivuliwe"</string>
+ <string name="assistant_attention_content_description" msgid="6830215897604642875">"Ukunaka kwe-Assistant kuvuliwe"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zu/tiles_states_strings.xml b/packages/SystemUI/res/values-zu/tiles_states_strings.xml
index 81c46364a9fd..e35840b85ab4 100644
--- a/packages/SystemUI/res/values-zu/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-zu/tiles_states_strings.xml
@@ -176,4 +176,9 @@
<item msgid="8014986104355098744">"Valiwe"</item>
<item msgid="5966994759929723339">"Vuliwe"</item>
</string-array>
+ <string-array name="tile_states_font_scaling">
+ <item msgid="3173069902082305985">"Ayitholakali"</item>
+ <item msgid="2478289035899842865">"Valiwe"</item>
+ <item msgid="5137565285664080143">"Vuliwe"</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 738cfd7c95bf..e65c327736e1 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -500,8 +500,8 @@
space -->
<bool name="config_showBatteryEstimateQSBH">false</bool>
- <!-- Whether to show a severe low battery dialog. -->
- <bool name="config_severe_battery_dialog">false</bool>
+ <!-- Whether to show extra battery saver confirmation dialog. -->
+ <bool name="config_extra_battery_saver_confirmation">false</bool>
<!-- A path representing a shield. Will sometimes be displayed with the battery icon when
needed. This path is a 10px wide and 13px tall. -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 4afe9d52d596..aba3fc4615c9 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -257,9 +257,6 @@
<!-- Radius for notifications corners with adjacent notifications -->
<dimen name="notification_corner_radius_small">4dp</dimen>
- <!-- Vertical padding of the FSI container -->
- <dimen name="fsi_chrome_vertical_padding">80dp</dimen>
-
<!-- the padding of the shelf icon container -->
<dimen name="shelf_icon_container_padding">13dp</dimen>
@@ -576,7 +573,7 @@
<dimen name="qs_tile_margin_horizontal">8dp</dimen>
<dimen name="qs_tile_margin_vertical">@dimen/qs_tile_margin_horizontal</dimen>
<dimen name="qs_tile_margin_top_bottom">4dp</dimen>
- <dimen name="qs_brightness_margin_top">12dp</dimen>
+ <dimen name="qs_brightness_margin_top">8dp</dimen>
<dimen name="qs_brightness_margin_bottom">16dp</dimen>
<dimen name="qqs_layout_margin_top">16dp</dimen>
<dimen name="qqs_layout_padding_bottom">24dp</dimen>
@@ -616,8 +613,7 @@
<dimen name="qs_dual_tile_padding_horizontal">6dp</dimen>
<dimen name="qs_panel_elevation">4dp</dimen>
<dimen name="qs_panel_padding_bottom">@dimen/footer_actions_height</dimen>
- <dimen name="qs_panel_padding_top">48dp</dimen>
- <dimen name="qs_panel_padding_top_combined_headers">80dp</dimen>
+ <dimen name="qs_panel_padding_top">80dp</dimen>
<dimen name="qs_data_usage_text_size">14sp</dimen>
<dimen name="qs_data_usage_usage_text_size">36sp</dimen>
@@ -629,7 +625,7 @@
<dimen name="qs_header_row_min_height">48dp</dimen>
<dimen name="qs_header_non_clickable_element_height">24dp</dimen>
- <dimen name="new_qs_header_non_clickable_element_height">20dp</dimen>
+ <dimen name="new_qs_header_non_clickable_element_height">24dp</dimen>
<dimen name="qs_footer_padding">20dp</dimen>
<dimen name="qs_security_footer_height">88dp</dimen>
@@ -1196,11 +1192,13 @@
<!-- Home Controls -->
<dimen name="controls_header_menu_size">48dp</dimen>
+ <dimen name="controls_header_menu_button_size">48dp</dimen>
<dimen name="controls_header_bottom_margin">16dp</dimen>
+ <dimen name="controls_header_horizontal_padding">12dp</dimen>
<dimen name="controls_header_app_icon_size">24dp</dimen>
<dimen name="controls_top_margin">48dp</dimen>
- <dimen name="controls_padding_horizontal">0dp</dimen>
- <dimen name="control_header_text_size">20sp</dimen>
+ <dimen name="controls_content_margin_horizontal">0dp</dimen>
+ <dimen name="control_header_text_size">24sp</dimen>
<dimen name="control_item_text_size">16sp</dimen>
<dimen name="control_menu_item_text_size">16sp</dimen>
<dimen name="control_menu_item_min_height">56dp</dimen>
@@ -1231,6 +1229,8 @@
<item name="controls_task_view_width_percentage" translatable="false" format="float" type="dimen">1.0</item>
<dimen name="controls_task_view_right_margin">0dp</dimen>
+ <dimen name="controls_panel_corner_radius">42dp</dimen>
+
<!-- Home Controls activity view detail panel-->
<dimen name="controls_activity_view_corner_radius">@*android:dimen/config_bottomDialogCornerRadius</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 3ebaae0ca99d..f4b3b87aab16 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -407,8 +407,6 @@
<!-- Message shown when the system-provided fingerprint dialog is shown, asking for authentication -->
<string name="fingerprint_dialog_touch_sensor">Touch the fingerprint sensor</string>
- <!-- Content description of the fingerprint icon when the system-provided fingerprint dialog is showing, for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_fingerprint_dialog_fingerprint_icon">Fingerprint icon</string>
<!-- Message shown to inform the user a face cannot be recognized and fingerprint should instead be used.[CHAR LIMIT=50] -->
<string name="fingerprint_dialog_use_fingerprint_instead">Can\u2019t recognize face. Use fingerprint instead.</string>
<!-- Message shown to inform the user a face cannot be recognized and fingerprint should instead be used.[CHAR LIMIT=50] -->
@@ -1721,13 +1719,13 @@
<string name="keyboard_shortcut_search_list_hint">Search shortcuts</string>
<!-- The description for no shortcuts results [CHAR LIMIT=25] -->
<string name="keyboard_shortcut_search_list_no_result">No shortcuts found</string>
- <!-- The title of system category in shortcut search list. [CHAR LIMIT=15] -->
+ <!-- The title of system category in shortcut search list. [CHAR LIMIT=25] -->
<string name="keyboard_shortcut_search_category_system">System</string>
- <!-- The title of input category in shortcut search list. [CHAR LIMIT=15] -->
+ <!-- The title of input category in shortcut search list. [CHAR LIMIT=25] -->
<string name="keyboard_shortcut_search_category_input">Input</string>
- <!-- The title of open apps category in shortcut search list. [CHAR LIMIT=15] -->
+ <!-- The title of open apps category in shortcut search list. [CHAR LIMIT=25] -->
<string name="keyboard_shortcut_search_category_open_apps">Open apps</string>
- <!-- The title of current app category in shortcut search list. [CHAR LIMIT=15] -->
+ <!-- The title of current app category in shortcut search list. [CHAR LIMIT=25] -->
<string name="keyboard_shortcut_search_category_current_app">Current app</string>
<!-- User visible title for the keyboard shortcut that triggers the notification shade. [CHAR LIMIT=70] -->
@@ -2339,6 +2337,8 @@
<string name="magnification_mode_switch_state_window">Magnify part of screen</string>
<!-- Click action label for magnification switch. [CHAR LIMIT=NONE] -->
<string name="magnification_mode_switch_click_label">Switch</string>
+ <!-- Click action label for magnification settings panel. [CHAR LIMIT=NONE] -->
+ <string name="magnification_open_settings_click_label">Open magnification settings</string>
<!-- Label of the corner of a rectangle that you can tap and drag to resize the magnification area. [CHAR LIMIT=NONE] -->
<string name="magnification_drag_corner_to_resize">Drag corner to resize</string>
@@ -2360,6 +2360,8 @@
<!-- Description of the window magnification Bottom handle [CHAR LIMIT=NONE]-->
<string name="accessibility_magnification_bottom_handle">Bottom handle</string>
+ <!-- Description of the window magnification panel [CHAR LIMIT=NONE]-->
+ <string name="accessibility_magnification_settings_panel_description">Magnification settings</string>
<!-- Title of the window magnification panel option Magnifier size [CHAR LIMIT=NONE]-->
<string name="accessibility_magnifier_size">Magnifier size</string>
<!-- Title of the window magnification panel option Zoom [CHAR LIMIT=NONE]-->
@@ -2431,6 +2433,10 @@
panel (embedded activity) instead of controls rendered by SystemUI [CHAR LIMIT=NONE] -->
<string name="controls_panel_authorization">When you add <xliff:g id="appName" example="My app">%s</xliff:g>, it can add controls and content to this panel. In some apps, you can choose which controls show up here.</string>
+ <!-- Shows in a dialog presented to the user to authorize this app removal from a Device
+ controls panel [CHAR LIMIT=NONE] -->
+ <string name="controls_panel_remove_app_authorization">Remove controls for <xliff:g example="My app" id="appName">%s</xliff:g>?</string>
+
<!-- a11y state description for a control that is currently favorited [CHAR LIMIT=NONE] -->
<string name="accessibility_control_favorite">Favorited</string>
<!-- a11y state description for a control that is currently favorited with its position [CHAR LIMIT=NONE] -->
@@ -2471,6 +2477,8 @@
<string name="controls_dialog_title">Add to device controls</string>
<!-- Controls dialog add to favorites [CHAR LIMIT=40] -->
<string name="controls_dialog_ok">Add</string>
+ <!-- Controls dialog remove app from a panel [CHAR LIMIT=40] -->
+ <string name="controls_dialog_remove">Remove</string>
<!-- Controls dialog message. Indicates app that suggested this control [CHAR LIMIT=NONE] -->
<string name="controls_dialog_message">Suggested by <xliff:g id="app" example="System UI">%s</xliff:g></string>
<!-- Controls tile secondary label when device is locked and user does not want access to controls from lockscreen [CHAR LIMIT=20] -->
@@ -2588,6 +2596,8 @@
<string name="controls_menu_edit">Edit controls</string>
<!-- Controls menu, add another app [CHAR LIMIT=30] -->
<string name="controls_menu_add_another_app">Add app</string>
+ <!-- Controls menu, remove app [CHAR_LIMIT=30] -->
+ <string name="controls_menu_remove">Remove app</string>
<!-- Title for the media output dialog with media related devices [CHAR LIMIT=50] -->
<string name="media_output_dialog_add_output">Add outputs</string>
diff --git a/packages/SystemUI/screenshot/AndroidManifest.xml b/packages/SystemUI/screenshot/AndroidManifest.xml
index a405836bd77f..ba3dc8c53fff 100644
--- a/packages/SystemUI/screenshot/AndroidManifest.xml
+++ b/packages/SystemUI/screenshot/AndroidManifest.xml
@@ -20,6 +20,7 @@
<application>
<activity
android:name="com.android.systemui.testing.screenshot.ScreenshotActivity"
+ android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize"
android:exported="true"
android:theme="@style/Theme.SystemUI.Screenshot" />
</application>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimator.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimator.kt
index 12e0b9ab835a..c5979cc50c3c 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimator.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimator.kt
@@ -65,35 +65,40 @@ class UnfoldConstantTranslateAnimator(
} else {
1
}
- viewsToTranslate.forEach { (view, direction, shouldBeAnimated) ->
- if (shouldBeAnimated()) {
- view.get()?.translationX = xTrans * direction.multiplier * rtlMultiplier
- }
+ viewsToTranslate.forEach { (view, direction) ->
+ view.get()?.translationX = xTrans * direction.multiplier * rtlMultiplier
}
}
/** Finds in [parent] all views specified by [ids] and register them for the animation. */
private fun registerViewsForAnimation(parent: ViewGroup, ids: Set<ViewIdToTranslate>) {
viewsToTranslate =
- ids.mapNotNull { (id, dir, pred) ->
- parent.findViewById<View>(id)?.let { view ->
- ViewToTranslate(WeakReference(view), dir, pred)
+ ids.asSequence()
+ .filter { it.shouldBeAnimated() }
+ .mapNotNull {
+ parent.findViewById<View>(it.viewId)?.let { view ->
+ ViewToTranslate(WeakReference(view), it.direction)
+ }
}
- }
+ .toList()
}
- /** Represents a view to animate. [rootView] should contain a view with [viewId] inside. */
+ /**
+ * Represents a view to animate. [rootView] should contain a view with [viewId] inside.
+ * [shouldBeAnimated] is only evaluated when the viewsToTranslate is registered in
+ * [registerViewsForAnimation].
+ */
data class ViewIdToTranslate(
val viewId: Int,
val direction: Direction,
val shouldBeAnimated: () -> Boolean = { true }
)
- private data class ViewToTranslate(
- val view: WeakReference<View>,
- val direction: Direction,
- val shouldBeAnimated: () -> Boolean
- )
+ /**
+ * Represents a view whose animation process is in-progress. It should be immutable because the
+ * started animation should be completed.
+ */
+ private data class ViewToTranslate(val view: WeakReference<View>, val direction: Direction)
/** Direction of the animation. */
enum class Direction(val multiplier: Float) {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Evaluator.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Evaluator.kt
index 23742c503ed3..454294f36d2a 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Evaluator.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Evaluator.kt
@@ -87,7 +87,7 @@ internal object Evaluator {
* Helper for evaluating 3-valued logical AND/OR.
*
* @param returnValueIfAnyMatches AND returns false if any value is false. OR returns true if
- * any value is true.
+ * any value is true.
*/
private fun threeValuedAndOrOr(
conditions: Collection<Condition>,
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
index a71fb5611bd9..4bc949116807 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
@@ -104,4 +104,9 @@ oneway interface IOverviewProxy {
* Sent when the surface for navigation bar is created or changed
*/
void onNavigationBarSurface(in SurfaceControl surface) = 26;
+
+ /**
+ * Sent when the task bar stash state is toggled.
+ */
+ void onTaskbarToggled() = 27;
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java
index b92715516a75..8690b36c12d7 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java
@@ -62,7 +62,7 @@ public class PreviewPositionHelper {
*/
public void updateThumbnailMatrix(Rect thumbnailBounds, ThumbnailData thumbnailData,
int canvasWidth, int canvasHeight, int screenWidthPx, int screenHeightPx,
- int taskbarSize, boolean isTablet,
+ int taskbarSize, boolean isLargeScreen,
int currentRotation, boolean isRtl) {
boolean isRotated = false;
boolean isOrientationDifferent;
@@ -95,7 +95,7 @@ public class PreviewPositionHelper {
canvasScreenRatio = (float) canvasWidth / screenWidthPx;
}
scaledTaskbarSize = taskbarSize * canvasScreenRatio;
- thumbnailClipHint.bottom = isTablet ? scaledTaskbarSize : 0;
+ thumbnailClipHint.bottom = isLargeScreen ? scaledTaskbarSize : 0;
float scale = thumbnailData.scale;
final float thumbnailScale;
@@ -103,7 +103,7 @@ public class PreviewPositionHelper {
// Landscape vs portrait change.
// Note: Disable rotation in grid layout.
boolean windowingModeSupportsRotation =
- thumbnailData.windowingMode == WINDOWING_MODE_FULLSCREEN && !isTablet;
+ thumbnailData.windowingMode == WINDOWING_MODE_FULLSCREEN && !isLargeScreen;
isOrientationDifferent = isOrientationChange(deltaRotate)
&& windowingModeSupportsRotation;
if (canvasWidth == 0 || canvasHeight == 0 || scale == 0) {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java
index 77a13bd91b90..751a3f8458bd 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java
@@ -137,7 +137,7 @@ public class Utilities {
/** @return whether or not {@param context} represents that of a large screen device or not */
@TargetApi(Build.VERSION_CODES.R)
- public static boolean isTablet(Context context) {
+ public static boolean isLargeScreen(Context context) {
final WindowManager windowManager = context.getSystemService(WindowManager.class);
final Rect bounds = windowManager.getCurrentWindowMetrics().getBounds();
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
index 7d39c4aaacbf..dd60647021ff 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
@@ -23,6 +23,7 @@ import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
import android.annotation.IntDef;
import android.content.Context;
import android.content.res.Resources;
+import android.os.SystemProperties;
import android.view.ViewConfiguration;
import android.view.WindowManagerPolicyConstants;
@@ -115,6 +116,9 @@ public class QuickStepContract {
public static final int SYSUI_STATE_FREEFORM_ACTIVE_IN_DESKTOP_MODE = 1 << 26;
// Device dreaming state
public static final int SYSUI_STATE_DEVICE_DREAMING = 1 << 27;
+ // Whether the back gesture is allowed (or ignored) by the Shade
+ public static final boolean ALLOW_BACK_GESTURE_IN_SHADE = SystemProperties.getBoolean(
+ "persist.wm.debug.shade_allow_back_gesture", false);
@Retention(RetentionPolicy.SOURCE)
@IntDef({SYSUI_STATE_SCREEN_PINNING,
@@ -243,9 +247,14 @@ public class QuickStepContract {
sysuiStateFlags &= ~SYSUI_STATE_NAV_BAR_HIDDEN;
}
// Disable when in immersive, or the notifications are interactive
- int disableFlags = SYSUI_STATE_NAV_BAR_HIDDEN
- | SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED
- | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
+ int disableFlags = SYSUI_STATE_NAV_BAR_HIDDEN | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
+
+ // EdgeBackGestureHandler ignores Back gesture when SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED.
+ // To allow Shade to respond to Back, we're bypassing this check (behind a flag).
+ if (!ALLOW_BACK_GESTURE_IN_SHADE) {
+ disableFlags |= SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
+ }
+
return (sysuiStateFlags & disableFlags) != 0;
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
index 90f44a75b005..44f9d43f5470 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
@@ -16,36 +16,14 @@
package com.android.systemui.shared.system;
-import static android.app.ActivityTaskManager.INVALID_TASK_ID;
-import static android.view.RemoteAnimationTarget.MODE_CHANGING;
-import static android.view.RemoteAnimationTarget.MODE_CLOSING;
-import static android.view.RemoteAnimationTarget.MODE_OPENING;
-import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
-import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
-import static android.view.WindowManager.TRANSIT_CLOSE;
-import static android.view.WindowManager.TRANSIT_OPEN;
-import static android.view.WindowManager.TRANSIT_TO_BACK;
-import static android.view.WindowManager.TRANSIT_TO_FRONT;
-import static android.window.TransitionInfo.FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY;
-import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
-import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
-
-import static com.android.wm.shell.common.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SuppressLint;
-import android.app.ActivityManager;
-import android.app.WindowConfiguration;
-import android.graphics.Rect;
import android.util.ArrayMap;
-import android.util.SparseBooleanArray;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
-import android.view.WindowManager;
import android.window.TransitionInfo;
import android.window.TransitionInfo.Change;
+import com.android.wm.shell.util.TransitionUtil;
+
import java.util.ArrayList;
import java.util.function.Predicate;
@@ -54,156 +32,6 @@ import java.util.function.Predicate;
*/
public class RemoteAnimationTargetCompat {
- private static int newModeToLegacyMode(int newMode) {
- switch (newMode) {
- case WindowManager.TRANSIT_OPEN:
- case WindowManager.TRANSIT_TO_FRONT:
- return MODE_OPENING;
- case WindowManager.TRANSIT_CLOSE:
- case WindowManager.TRANSIT_TO_BACK:
- return MODE_CLOSING;
- default:
- return MODE_CHANGING;
- }
- }
-
- /**
- * Almost a copy of Transitions#setupStartState.
- * TODO: remove when there is proper cross-process transaction sync.
- */
- @SuppressLint("NewApi")
- private static void setupLeash(@NonNull SurfaceControl leash,
- @NonNull TransitionInfo.Change change, int layer,
- @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t) {
- boolean isOpening = info.getType() == TRANSIT_OPEN || info.getType() == TRANSIT_TO_FRONT;
- // Put animating stuff above this line and put static stuff below it.
- int zSplitLine = info.getChanges().size();
- // changes should be ordered top-to-bottom in z
- final int mode = change.getMode();
-
- t.reparent(leash, info.getRootLeash());
- final Rect absBounds =
- (mode == TRANSIT_OPEN) ? change.getEndAbsBounds() : change.getStartAbsBounds();
- t.setPosition(leash, absBounds.left - info.getRootOffset().x,
- absBounds.top - info.getRootOffset().y);
-
- // Put all the OPEN/SHOW on top
- if (mode == TRANSIT_OPEN || mode == TRANSIT_TO_FRONT) {
- if (isOpening) {
- t.setLayer(leash, zSplitLine + info.getChanges().size() - layer);
- if ((change.getFlags() & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) == 0) {
- // if transferred, it should be left visible.
- t.setAlpha(leash, 0.f);
- }
- } else {
- // put on bottom and leave it visible
- t.setLayer(leash, zSplitLine - layer);
- }
- } else if (mode == TRANSIT_CLOSE || mode == TRANSIT_TO_BACK) {
- if (isOpening) {
- // put on bottom and leave visible
- t.setLayer(leash, zSplitLine - layer);
- } else {
- // put on top
- t.setLayer(leash, zSplitLine + info.getChanges().size() - layer);
- }
- } else { // CHANGE
- t.setLayer(leash, zSplitLine + info.getChanges().size() - layer);
- }
- }
-
- @SuppressLint("NewApi")
- private static SurfaceControl createLeash(TransitionInfo info, TransitionInfo.Change change,
- int order, SurfaceControl.Transaction t) {
- // TODO: once we can properly sync transactions across process, then get rid of this leash.
- if (change.getParent() != null && (change.getFlags() & FLAG_IS_WALLPAPER) != 0) {
- // Special case for wallpaper atm. Normally these are left alone; but, a quirk of
- // making leashes means we have to handle them specially.
- return change.getLeash();
- }
- SurfaceControl leashSurface = new SurfaceControl.Builder()
- .setName(change.getLeash().toString() + "_transition-leash")
- .setContainerLayer()
- // Initial the surface visible to respect the visibility of the original surface.
- .setHidden(false)
- .setParent(info.getRootLeash())
- .build();
- // Copied Transitions setup code (which expects bottom-to-top order, so we swap here)
- setupLeash(leashSurface, change, info.getChanges().size() - order, info, t);
- t.reparent(change.getLeash(), leashSurface);
- t.setAlpha(change.getLeash(), 1.0f);
- t.show(change.getLeash());
- t.setPosition(change.getLeash(), 0, 0);
- t.setLayer(change.getLeash(), 0);
- return leashSurface;
- }
-
- /**
- * Creates a new RemoteAnimationTarget from the provided change info
- */
- public static RemoteAnimationTarget newTarget(TransitionInfo.Change change, int order,
- TransitionInfo info, SurfaceControl.Transaction t,
- @Nullable ArrayMap<SurfaceControl, SurfaceControl> leashMap) {
- final SurfaceControl leash = createLeash(info, change, order, t);
- if (leashMap != null) {
- leashMap.put(change.getLeash(), leash);
- }
- return newTarget(change, order, leash);
- }
-
- /**
- * Creates a new RemoteAnimationTarget from the provided change and leash
- */
- public static RemoteAnimationTarget newTarget(TransitionInfo.Change change, int order,
- SurfaceControl leash) {
- int taskId;
- boolean isNotInRecents;
- ActivityManager.RunningTaskInfo taskInfo;
- WindowConfiguration windowConfiguration;
-
- taskInfo = change.getTaskInfo();
- if (taskInfo != null) {
- taskId = taskInfo.taskId;
- isNotInRecents = !taskInfo.isRunning;
- windowConfiguration = taskInfo.configuration.windowConfiguration;
- } else {
- taskId = INVALID_TASK_ID;
- isNotInRecents = true;
- windowConfiguration = new WindowConfiguration();
- }
-
- Rect localBounds = new Rect(change.getEndAbsBounds());
- localBounds.offsetTo(change.getEndRelOffset().x, change.getEndRelOffset().y);
-
- RemoteAnimationTarget target = new RemoteAnimationTarget(
- taskId,
- newModeToLegacyMode(change.getMode()),
- // TODO: once we can properly sync transactions across process,
- // then get rid of this leash.
- leash,
- (change.getFlags() & TransitionInfo.FLAG_TRANSLUCENT) != 0,
- null,
- // TODO(shell-transitions): we need to send content insets? evaluate how its used.
- new Rect(0, 0, 0, 0),
- order,
- null,
- localBounds,
- new Rect(change.getEndAbsBounds()),
- windowConfiguration,
- isNotInRecents,
- null,
- new Rect(change.getStartAbsBounds()),
- taskInfo,
- change.getAllowEnterPip(),
- (change.getFlags() & FLAG_IS_DIVIDER_BAR) != 0
- ? TYPE_DOCK_DIVIDER : INVALID_WINDOW_TYPE
- );
- target.setWillShowImeOnTarget(
- (change.getFlags() & TransitionInfo.FLAG_WILL_IME_SHOWN) != 0);
- target.setRotationChange(change.getEndRotation() - change.getStartRotation());
- return target;
- }
-
/**
* Represents a TransitionInfo object as an array of old-style app targets
*
@@ -212,7 +40,7 @@ public class RemoteAnimationTargetCompat {
*/
public static RemoteAnimationTarget[] wrapApps(TransitionInfo info,
SurfaceControl.Transaction t, ArrayMap<SurfaceControl, SurfaceControl> leashMap) {
- return wrap(info, t, leashMap, new LeafTaskFilter());
+ return wrap(info, t, leashMap, new TransitionUtil.LeafTaskFilter());
}
/**
@@ -225,8 +53,8 @@ public class RemoteAnimationTargetCompat {
*/
public static RemoteAnimationTarget[] wrapNonApps(TransitionInfo info, boolean wallpapers,
SurfaceControl.Transaction t, ArrayMap<SurfaceControl, SurfaceControl> leashMap) {
- return wrap(info, t, leashMap, (change) ->
- (wallpapers ? isWallpaper(change) : isNonApp(change)));
+ return wrap(info, t, leashMap, (change) -> (wallpapers
+ ? TransitionUtil.isWallpaper(change) : TransitionUtil.isNonApp(change)));
}
private static RemoteAnimationTarget[] wrap(TransitionInfo info,
@@ -236,45 +64,10 @@ public class RemoteAnimationTargetCompat {
for (int i = 0; i < info.getChanges().size(); i++) {
TransitionInfo.Change change = info.getChanges().get(i);
if (filter.test(change)) {
- out.add(newTarget(change, info.getChanges().size() - i, info, t, leashMap));
+ out.add(TransitionUtil.newTarget(
+ change, info.getChanges().size() - i, info, t, leashMap));
}
}
return out.toArray(new RemoteAnimationTarget[out.size()]);
}
-
- /** Returns `true` if `change` is a wallpaper. */
- public static boolean isWallpaper(Change change) {
- return (change.getTaskInfo() == null)
- && change.hasFlags(FLAG_IS_WALLPAPER)
- && !change.hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY);
- }
-
- /** Returns `true` if `change` is not an app window or wallpaper. */
- public static boolean isNonApp(Change change) {
- return (change.getTaskInfo() == null)
- && !change.hasFlags(FLAG_IS_WALLPAPER)
- && !change.hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY);
- }
-
- /**
- * Filter that selects leaf-tasks only. THIS IS ORDER-DEPENDENT! For it to work properly, you
- * MUST call `test` in the same order that the changes appear in the TransitionInfo.
- */
- public static class LeafTaskFilter implements Predicate<Change> {
- private final SparseBooleanArray mChildTaskTargets = new SparseBooleanArray();
-
- @Override
- public boolean test(Change change) {
- final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
- // Children always come before parent since changes are in top-to-bottom z-order.
- if ((taskInfo == null) || mChildTaskTargets.get(taskInfo.taskId)) {
- // has children, so not a leaf. Skip.
- return false;
- }
- if (taskInfo.hasParentTask()) {
- mChildTaskTargets.put(taskInfo.parentTaskId, true);
- }
- return true;
- }
- }
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
index 2a37bd370b7c..6f7d66d03cab 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
@@ -19,13 +19,8 @@ package com.android.systemui.shared.system;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.view.WindowManager.TRANSIT_CHANGE;
-import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_LOCKED;
-import static android.view.WindowManager.TRANSIT_OPEN;
-import static android.view.WindowManager.TRANSIT_TO_BACK;
-import static android.view.WindowManager.TRANSIT_TO_FRONT;
-
-import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.newTarget;
+import static android.view.WindowManager.TRANSIT_SLEEP;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
@@ -36,7 +31,6 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.ArrayMap;
import android.util.Log;
-import android.util.SparseArray;
import android.view.IRecentsAnimationController;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
@@ -50,9 +44,10 @@ import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.shared.recents.model.ThumbnailData;
+import com.android.wm.shell.util.TransitionUtil;
import java.util.ArrayList;
+import java.util.HashMap;
/**
* Helper class to build {@link RemoteTransition} objects
@@ -62,7 +57,7 @@ public class RemoteTransitionCompat {
/** Constructor specifically for recents animation */
public static RemoteTransition newRemoteTransition(RecentsAnimationListener recents,
- RecentsAnimationControllerCompat controller, IApplicationThread appThread) {
+ IApplicationThread appThread) {
IRemoteTransition remote = new IRemoteTransition.Stub() {
final RecentsControllerWrap mRecentsSession = new RecentsControllerWrap();
IBinder mToken = null;
@@ -73,7 +68,7 @@ public class RemoteTransitionCompat {
IRemoteTransitionFinishedCallback finishedCallback) {
// TODO(b/177438007): Move this set-up logic into launcher's animation impl.
mToken = transition;
- mRecentsSession.start(controller, recents, mToken, info, t, finishedCallback);
+ mRecentsSession.start(recents, mToken, info, t, finishedCallback);
}
@Override
@@ -102,16 +97,27 @@ public class RemoteTransitionCompat {
* TODO(b/177438007): Remove this once Launcher handles shell transitions directly.
*/
@VisibleForTesting
- static class RecentsControllerWrap extends RecentsAnimationControllerCompat {
+ static class RecentsControllerWrap extends IRecentsAnimationController.Default {
private RecentsAnimationListener mListener = null;
- private RecentsAnimationControllerCompat mWrapped = null;
private IRemoteTransitionFinishedCallback mFinishCB = null;
+
+ /**
+ * List of tasks that we are switching away from via this transition. Upon finish, these
+ * pausing tasks will become invisible.
+ * These need to be ordered since the order must be restored if there is no task-switch.
+ */
private ArrayList<TaskState> mPausingTasks = null;
+
+ /**
+ * List of tasks that we are switching to. Upon finish, these will remain visible and
+ * on top.
+ */
+ private ArrayList<TaskState> mOpeningTasks = null;
+
private WindowContainerToken mPipTask = null;
private WindowContainerToken mRecentsTask = null;
private int mRecentsTaskId = 0;
private TransitionInfo mInfo = null;
- private ArrayList<SurfaceControl> mOpeningLeashes = null;
private boolean mOpeningSeparateHome = false;
private ArrayMap<SurfaceControl, SurfaceControl> mLeashMap = null;
private PictureInPictureSurfaceTransaction mPipTransaction = null;
@@ -120,7 +126,16 @@ public class RemoteTransitionCompat {
private RemoteAnimationTarget[] mAppearedTargets;
private boolean mWillFinishToHome = false;
- void start(RecentsAnimationControllerCompat wrapped, RecentsAnimationListener listener,
+ /** The animation is idle, waiting for the user to choose a task to switch to. */
+ private static final int STATE_NORMAL = 0;
+
+ /** The user chose a new task to switch to and the animation is animating to it. */
+ private static final int STATE_NEW_TASK = 1;
+
+ /** The latest state that the recents animation is operating in. */
+ private int mState = STATE_NORMAL;
+
+ void start(RecentsAnimationListener listener,
IBinder transition, TransitionInfo info, SurfaceControl.Transaction t,
IRemoteTransitionFinishedCallback finishedCallback) {
if (mInfo != null) {
@@ -128,29 +143,29 @@ public class RemoteTransitionCompat {
+ " recents is already active.");
}
mListener = listener;
- mWrapped = wrapped;
mInfo = info;
mFinishCB = finishedCallback;
mPausingTasks = new ArrayList<>();
+ mOpeningTasks = new ArrayList<>();
mPipTask = null;
mRecentsTask = null;
mRecentsTaskId = -1;
mLeashMap = new ArrayMap<>();
mTransition = transition;
mKeyguardLocked = (info.getFlags() & TRANSIT_FLAG_KEYGUARD_LOCKED) != 0;
+ mState = STATE_NORMAL;
final ArrayList<RemoteAnimationTarget> apps = new ArrayList<>();
final ArrayList<RemoteAnimationTarget> wallpapers = new ArrayList<>();
- RemoteAnimationTargetCompat.LeafTaskFilter leafTaskFilter =
- new RemoteAnimationTargetCompat.LeafTaskFilter();
+ TransitionUtil.LeafTaskFilter leafTaskFilter = new TransitionUtil.LeafTaskFilter();
// About layering: we divide up the "layer space" into 3 regions (each the size of
// the change count). This lets us categorize things into above/below/between
// while maintaining their relative ordering.
for (int i = 0; i < info.getChanges().size(); ++i) {
final TransitionInfo.Change change = info.getChanges().get(i);
final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
- if (RemoteAnimationTargetCompat.isWallpaper(change)) {
- final RemoteAnimationTarget target = newTarget(change,
+ if (TransitionUtil.isWallpaper(change)) {
+ final RemoteAnimationTarget target = TransitionUtil.newTarget(change,
// wallpapers go into the "below" layer space
info.getChanges().size() - i, info, t, mLeashMap);
wallpapers.add(target);
@@ -158,10 +173,10 @@ public class RemoteTransitionCompat {
t.setAlpha(target.leash, 1);
} else if (leafTaskFilter.test(change)) {
// start by putting everything into the "below" layer space.
- final RemoteAnimationTarget target = newTarget(change,
+ final RemoteAnimationTarget target = TransitionUtil.newTarget(change,
info.getChanges().size() - i, info, t, mLeashMap);
apps.add(target);
- if (change.getMode() == TRANSIT_CLOSE || change.getMode() == TRANSIT_TO_BACK) {
+ if (TransitionUtil.isClosingType(change.getMode())) {
// raise closing (pausing) task to "above" layer so it isn't covered
t.setLayer(target.leash, info.getChanges().size() * 3 - i);
mPausingTasks.add(new TaskState(change, target.leash));
@@ -178,47 +193,69 @@ public class RemoteTransitionCompat {
} else if (taskInfo != null && taskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
mRecentsTask = taskInfo.token;
mRecentsTaskId = taskInfo.taskId;
+ } else if (TransitionUtil.isOpeningType(change.getMode())) {
+ mOpeningTasks.add(new TaskState(change, target.leash));
}
}
}
t.apply();
- mListener.onAnimationStart(this, apps.toArray(new RemoteAnimationTarget[apps.size()]),
+ mListener.onAnimationStart(new RecentsAnimationControllerCompat(this),
+ apps.toArray(new RemoteAnimationTarget[apps.size()]),
wallpapers.toArray(new RemoteAnimationTarget[wallpapers.size()]),
new Rect(0, 0, 0, 0), new Rect());
}
@SuppressLint("NewApi")
boolean merge(TransitionInfo info, SurfaceControl.Transaction t) {
- SparseArray<TransitionInfo.Change> openingTasks = null;
+ if (info.getType() == TRANSIT_SLEEP) {
+ // A sleep event means we need to stop animations immediately, so cancel here.
+ mListener.onAnimationCanceled(new HashMap<>());
+ finish(mWillFinishToHome, false /* userLeaveHint */);
+ return false;
+ }
+ ArrayList<TransitionInfo.Change> openingTasks = null;
+ ArrayList<TransitionInfo.Change> closingTasks = null;
mAppearedTargets = null;
- boolean foundHomeOpening = false;
+ mOpeningSeparateHome = false;
+ TransitionInfo.Change recentsOpening = null;
boolean foundRecentsClosing = false;
boolean hasChangingApp = false;
- for (int i = info.getChanges().size() - 1; i >= 0; --i) {
+ final TransitionUtil.LeafTaskFilter leafTaskFilter =
+ new TransitionUtil.LeafTaskFilter();
+ for (int i = 0; i < info.getChanges().size(); ++i) {
final TransitionInfo.Change change = info.getChanges().get(i);
- if (change.getMode() == TRANSIT_OPEN || change.getMode() == TRANSIT_TO_FRONT) {
- final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
- if (taskInfo != null) {
+ final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
+ final boolean isLeafTask = leafTaskFilter.test(change);
+ if (TransitionUtil.isOpeningType(change.getMode())) {
+ if (mRecentsTask.equals(change.getContainer())) {
+ recentsOpening = change;
+ } else if (isLeafTask) {
if (taskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
// This is usually a 3p launcher
- foundHomeOpening = true;
+ mOpeningSeparateHome = true;
}
if (openingTasks == null) {
- openingTasks = new SparseArray<>();
- }
- if (taskInfo.hasParentTask()) {
- // Collects opening leaf tasks only since Launcher monitors leaf task
- // ids to perform recents animation.
- openingTasks.remove(taskInfo.parentTaskId);
+ openingTasks = new ArrayList<>();
}
- openingTasks.put(taskInfo.taskId, change);
+ openingTasks.add(change);
}
- } else if (change.getMode() == TRANSIT_CLOSE
- || change.getMode() == TRANSIT_TO_BACK) {
+ } else if (TransitionUtil.isClosingType(change.getMode())) {
if (mRecentsTask.equals(change.getContainer())) {
foundRecentsClosing = true;
+ } else if (isLeafTask) {
+ if (closingTasks == null) {
+ closingTasks = new ArrayList<>();
+ }
+ closingTasks.add(change);
}
} else if (change.getMode() == TRANSIT_CHANGE) {
+ // Finish recents animation if the display is changed, so the default
+ // transition handler can play the animation such as rotation effect.
+ if (change.hasFlags(TransitionInfo.FLAG_IS_DISPLAY)) {
+ mListener.onSwitchToScreenshot(() -> finish(false /* toHome */,
+ false /* userLeaveHint */));
+ return false;
+ }
hasChangingApp = true;
}
}
@@ -234,45 +271,73 @@ public class RemoteTransitionCompat {
}
return false;
}
- if (openingTasks == null) return false;
- int pauseMatches = 0;
- if (!foundHomeOpening) {
- for (int i = 0; i < openingTasks.size(); ++i) {
- if (TaskState.indexOf(mPausingTasks, openingTasks.valueAt(i)) >= 0) {
- ++pauseMatches;
+ if (recentsOpening != null) {
+ // the recents task re-appeared. This happens if the user gestures before the
+ // task-switch (NEW_TASK) animation finishes.
+ if (mState == STATE_NORMAL) {
+ Log.e(TAG, "Returning to recents while recents is already idle.");
+ }
+ if (closingTasks == null || closingTasks.size() == 0) {
+ Log.e(TAG, "Returning to recents without closing any opening tasks.");
+ }
+ // Setup may hide it initially since it doesn't know that overview was still active.
+ t.show(recentsOpening.getLeash());
+ t.setAlpha(recentsOpening.getLeash(), 1.f);
+ mState = STATE_NORMAL;
+ }
+ boolean didMergeThings = false;
+ if (closingTasks != null) {
+ // Cancelling a task-switch. Move the tasks back to mPausing from mOpening
+ for (int i = 0; i < closingTasks.size(); ++i) {
+ final TransitionInfo.Change change = closingTasks.get(i);
+ int openingIdx = TaskState.indexOf(mOpeningTasks, change);
+ if (openingIdx < 0) {
+ Log.e(TAG, "Back to existing recents animation from an unrecognized "
+ + "task: " + change.getTaskInfo().taskId);
+ continue;
}
+ mPausingTasks.add(mOpeningTasks.remove(openingIdx));
+ didMergeThings = true;
}
}
- if (pauseMatches > 0) {
- if (pauseMatches != mPausingTasks.size()) {
- // We are not really "returning" properly... something went wrong.
- throw new IllegalStateException("\"Concelling\" a recents transitions by "
- + "unpausing " + pauseMatches + " apps after pausing "
- + mPausingTasks.size() + " apps.");
+ if (openingTasks != null && openingTasks.size() > 0) {
+ // Switching to some new tasks, add to mOpening and remove from mPausing. Also,
+ // enter NEW_TASK state since this will start the switch-to animation.
+ final int layer = mInfo.getChanges().size() * 3;
+ final RemoteAnimationTarget[] targets =
+ new RemoteAnimationTarget[openingTasks.size()];
+ for (int i = 0; i < openingTasks.size(); ++i) {
+ final TransitionInfo.Change change = openingTasks.get(i);
+ int pausingIdx = TaskState.indexOf(mPausingTasks, change);
+ if (pausingIdx >= 0) {
+ // Something is showing/opening a previously-pausing app.
+ targets[i] = TransitionUtil.newTarget(change, layer,
+ mPausingTasks.get(pausingIdx).mLeash);
+ mOpeningTasks.add(mPausingTasks.remove(pausingIdx));
+ // Setup hides opening tasks initially, so make it visible again (since we
+ // are already showing it).
+ t.show(change.getLeash());
+ t.setAlpha(change.getLeash(), 1.f);
+ } else {
+ // We are receiving new opening tasks, so convert to onTasksAppeared.
+ targets[i] = TransitionUtil.newTarget(change, layer, info, t, mLeashMap);
+ t.reparent(targets[i].leash, mInfo.getRootLeash());
+ t.setLayer(targets[i].leash, layer);
+ mOpeningTasks.add(new TaskState(change, targets[i].leash));
+ }
}
- // In this case, we are "returning" to an already running app, so just consume
- // the merge and do nothing.
- info.releaseAllSurfaces();
- t.close();
- return true;
+ didMergeThings = true;
+ mState = STATE_NEW_TASK;
+ mAppearedTargets = targets;
}
- final int layer = mInfo.getChanges().size() * 3;
- mOpeningLeashes = new ArrayList<>();
- mOpeningSeparateHome = foundHomeOpening;
- final RemoteAnimationTarget[] targets =
- new RemoteAnimationTarget[openingTasks.size()];
- for (int i = 0; i < openingTasks.size(); ++i) {
- final TransitionInfo.Change change = openingTasks.valueAt(i);
- mOpeningLeashes.add(change.getLeash());
- // We are receiving new opening tasks, so convert to onTasksAppeared.
- targets[i] = newTarget(change, layer, info, t, mLeashMap);
- t.reparent(targets[i].leash, mInfo.getRootLeash());
- t.setLayer(targets[i].leash, layer);
+ if (!didMergeThings) {
+ // Didn't recognize anything in incoming transition so don't merge it.
+ Log.w(TAG, "Don't know how to merge this transition.");
+ return false;
}
t.apply();
// not using the incoming anim-only surfaces
info.releaseAnimSurfaces();
- mAppearedTargets = targets;
return true;
}
@@ -283,13 +348,9 @@ public class RemoteTransitionCompat {
}
}
- @Override public ThumbnailData screenshotTask(int taskId) {
+ @Override public TaskSnapshot screenshotTask(int taskId) {
try {
- final TaskSnapshot snapshot =
- ActivityTaskManager.getService().takeTaskSnapshot(taskId);
- if (snapshot != null) {
- return new ThumbnailData(snapshot);
- }
+ return ActivityTaskManager.getService().takeTaskSnapshot(taskId);
} catch (RemoteException e) {
Log.e(TAG, "Failed to screenshot task", e);
}
@@ -297,28 +358,24 @@ public class RemoteTransitionCompat {
}
@Override public void setInputConsumerEnabled(boolean enabled) {
- if (enabled) {
- // transient launches don't receive focus automatically. Since we are taking over
- // the gesture now, take focus explicitly.
- try {
- ActivityTaskManager.getService().setFocusedTask(mRecentsTaskId);
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to set focused task", e);
- }
+ if (!enabled) return;
+ // transient launches don't receive focus automatically. Since we are taking over
+ // the gesture now, take focus explicitly.
+ // This also moves recents back to top if the user gestured before a switch
+ // animation finished.
+ try {
+ ActivityTaskManager.getService().setFocusedTask(mRecentsTaskId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to set focused task", e);
}
- if (mWrapped != null) mWrapped.setInputConsumerEnabled(enabled);
}
@Override public void setAnimationTargetsBehindSystemBars(boolean behindSystemBars) {
- if (mWrapped != null) mWrapped.setAnimationTargetsBehindSystemBars(behindSystemBars);
}
@Override public void setFinishTaskTransaction(int taskId,
PictureInPictureSurfaceTransaction finishTransaction, SurfaceControl overlay) {
mPipTransaction = finishTransaction;
- if (mWrapped != null) {
- mWrapped.setFinishTaskTransaction(taskId, finishTransaction, overlay);
- }
}
@Override
@@ -328,7 +385,6 @@ public class RemoteTransitionCompat {
Log.e(TAG, "Duplicate call to finish", new RuntimeException());
return;
}
- if (mWrapped != null) mWrapped.finish(toHome, sendUserLeaveHint);
final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
final WindowContainerTransaction wct = new WindowContainerTransaction();
@@ -336,8 +392,8 @@ public class RemoteTransitionCompat {
if (toHome) wct.reorder(mRecentsTask, true /* toTop */);
else wct.restoreTransientOrder(mRecentsTask);
}
- if (!toHome && !mWillFinishToHome && mPausingTasks != null && mOpeningLeashes == null) {
- // The gesture went back to opening the app rather than continuing with
+ if (!toHome && !mWillFinishToHome && mPausingTasks != null && mState == STATE_NORMAL) {
+ // The gesture is returning to the pausing-task(s) rather than continuing with
// recents, so end the transition by moving the app back to the top (and also
// re-showing it's task).
for (int i = mPausingTasks.size() - 1; i >= 0; --i) {
@@ -349,25 +405,28 @@ public class RemoteTransitionCompat {
wct.restoreTransientOrder(mRecentsTask);
}
} else if (toHome && mOpeningSeparateHome && mPausingTasks != null) {
- // Special situaition where 3p launcher was changed during recents (this happens
+ // Special situation where 3p launcher was changed during recents (this happens
// during tapltests...). Here we get both "return to home" AND "home opening".
- // This is basically going home, but we have to restore recents order and also
- // treat the home "pausing" task properly.
- for (int i = mPausingTasks.size() - 1; i >= 0; --i) {
- final TaskState state = mPausingTasks.get(i);
+ // This is basically going home, but we have to restore the recents and home order.
+ for (int i = 0; i < mOpeningTasks.size(); ++i) {
+ final TaskState state = mOpeningTasks.get(i);
if (state.mTaskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
- // Treat as opening (see above)
+ // Make sure it is on top.
wct.reorder(state.mToken, true /* onTop */);
- t.show(state.mTaskSurface);
- } else {
- // Treat as hiding (see below)
- t.hide(state.mTaskSurface);
}
+ t.show(state.mTaskSurface);
+ }
+ for (int i = mPausingTasks.size() - 1; i >= 0; --i) {
+ t.hide(mPausingTasks.get(i).mTaskSurface);
}
if (!mKeyguardLocked && mRecentsTask != null) {
wct.restoreTransientOrder(mRecentsTask);
}
} else {
+ // The general case: committing to recents, going home, or switching tasks.
+ for (int i = 0; i < mOpeningTasks.size(); ++i) {
+ t.show(mOpeningTasks.get(i).mTaskSurface);
+ }
for (int i = 0; i < mPausingTasks.size(); ++i) {
if (!sendUserLeaveHint) {
// This means recents is not *actually* finishing, so of course we gotta
@@ -391,43 +450,40 @@ public class RemoteTransitionCompat {
try {
mFinishCB.onTransitionFinished(wct.isEmpty() ? null : wct, t);
} catch (RemoteException e) {
- Log.e("RemoteTransitionCompat", "Failed to call animation finish callback", e);
+ Log.e(TAG, "Failed to call animation finish callback", e);
t.apply();
}
// Only release the non-local created surface references. The animator is responsible
// for releasing the leashes created by local.
mInfo.releaseAllSurfaces();
// Reset all members.
- mWrapped = null;
mListener = null;
mFinishCB = null;
mPausingTasks = null;
+ mOpeningTasks = null;
mAppearedTargets = null;
mInfo = null;
- mOpeningLeashes = null;
mOpeningSeparateHome = false;
mLeashMap = null;
mTransition = null;
+ mState = STATE_NORMAL;
}
@Override public void setDeferCancelUntilNextTransition(boolean defer, boolean screenshot) {
- if (mWrapped != null) mWrapped.setDeferCancelUntilNextTransition(defer, screenshot);
}
@Override public void cleanupScreenshot() {
- if (mWrapped != null) mWrapped.cleanupScreenshot();
}
@Override public void setWillFinishToHome(boolean willFinishToHome) {
mWillFinishToHome = willFinishToHome;
- if (mWrapped != null) mWrapped.setWillFinishToHome(willFinishToHome);
}
/**
* @see IRecentsAnimationController#removeTask
*/
@Override public boolean removeTask(int taskId) {
- return mWrapped != null ? mWrapped.removeTask(taskId) : false;
+ return false;
}
/**
diff --git a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
index a25b281f807c..c5a06b48e015 100644
--- a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
+++ b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
@@ -24,7 +24,6 @@ import android.view.ViewConfiguration;
import android.widget.Button;
import com.android.internal.util.EmergencyAffordanceManager;
-import com.android.internal.widget.LockPatternUtils;
/**
* This class implements a smart emergency button that updates itself based
@@ -40,8 +39,6 @@ public class EmergencyButton extends Button {
private int mDownY;
private boolean mLongPressWasDragged;
- private LockPatternUtils mLockPatternUtils;
-
private final boolean mEnableEmergencyCallWhileSimLocked;
public EmergencyButton(Context context) {
@@ -58,7 +55,6 @@ public class EmergencyButton extends Button {
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mLockPatternUtils = new LockPatternUtils(mContext);
if (mEmergencyAffordanceManager.needsEmergencyAffordance()) {
setOnLongClickListener(v -> {
if (!mLongPressWasDragged
@@ -95,7 +91,8 @@ public class EmergencyButton extends Button {
return super.performLongClick();
}
- void updateEmergencyCallButton(boolean isInCall, boolean hasTelephonyRadio, boolean simLocked) {
+ void updateEmergencyCallButton(boolean isInCall, boolean hasTelephonyRadio, boolean simLocked,
+ boolean isSecure) {
boolean visible = false;
if (hasTelephonyRadio) {
// Emergency calling requires a telephony radio.
@@ -107,7 +104,7 @@ public class EmergencyButton extends Button {
visible = mEnableEmergencyCallWhileSimLocked;
} else {
// Only show if there is a secure screen (pin/pattern/SIM pin/SIM puk);
- visible = mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser());
+ visible = isSecure;
}
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java b/packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java
index ea808eb19b90..f7e8eb492584 100644
--- a/packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java
+++ b/packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java
@@ -18,6 +18,7 @@ package com.android.keyguard;
import static com.android.systemui.DejankUtils.whitelistIpcs;
+import android.annotation.SuppressLint;
import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
import android.content.Intent;
@@ -31,16 +32,22 @@ import android.telephony.TelephonyManager;
import android.util.Log;
import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.dagger.KeyguardBouncerScope;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.shade.ShadeController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
import com.android.systemui.util.EmergencyDialerConstants;
import com.android.systemui.util.ViewController;
+import java.util.concurrent.Executor;
+
import javax.inject.Inject;
/** View Controller for {@link com.android.keyguard.EmergencyButton}. */
@@ -57,6 +64,9 @@ public class EmergencyButtonController extends ViewController<EmergencyButton> {
private final MetricsLogger mMetricsLogger;
private EmergencyButtonCallback mEmergencyButtonCallback;
+ private LockPatternUtils mLockPatternUtils;
+ private Executor mMainExecutor;
+ private Executor mBackgroundExecutor;
private final KeyguardUpdateMonitorCallback mInfoCallback =
new KeyguardUpdateMonitorCallback() {
@@ -78,12 +88,15 @@ public class EmergencyButtonController extends ViewController<EmergencyButton> {
}
};
- private EmergencyButtonController(@Nullable EmergencyButton view,
+ @VisibleForTesting
+ public EmergencyButtonController(@Nullable EmergencyButton view,
ConfigurationController configurationController,
KeyguardUpdateMonitor keyguardUpdateMonitor, TelephonyManager telephonyManager,
PowerManager powerManager, ActivityTaskManager activityTaskManager,
ShadeController shadeController,
- @Nullable TelecomManager telecomManager, MetricsLogger metricsLogger) {
+ @Nullable TelecomManager telecomManager, MetricsLogger metricsLogger,
+ LockPatternUtils lockPatternUtils,
+ Executor mainExecutor, Executor backgroundExecutor) {
super(view);
mConfigurationController = configurationController;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
@@ -93,6 +106,9 @@ public class EmergencyButtonController extends ViewController<EmergencyButton> {
mShadeController = shadeController;
mTelecomManager = telecomManager;
mMetricsLogger = metricsLogger;
+ mLockPatternUtils = lockPatternUtils;
+ mMainExecutor = mainExecutor;
+ mBackgroundExecutor = backgroundExecutor;
}
@Override
@@ -113,13 +129,27 @@ public class EmergencyButtonController extends ViewController<EmergencyButton> {
mConfigurationController.removeCallback(mConfigurationListener);
}
- private void updateEmergencyCallButton() {
+ /**
+ * Updates the visibility of the emergency button.
+ *
+ * This method runs binder calls in a background thread.
+ */
+ @VisibleForTesting
+ @SuppressLint("MissingPermission")
+ public void updateEmergencyCallButton() {
if (mView != null) {
- mView.updateEmergencyCallButton(
- mTelecomManager != null && mTelecomManager.isInCall(),
- getContext().getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_TELEPHONY),
- mKeyguardUpdateMonitor.isSimPinVoiceSecure());
+ // Run in bg thread to avoid throttling the main thread with binder call.
+ mBackgroundExecutor.execute(() -> {
+ boolean isInCall = mTelecomManager != null && mTelecomManager.isInCall();
+ boolean isSecure = mLockPatternUtils
+ .isSecure(KeyguardUpdateMonitor.getCurrentUser());
+ mMainExecutor.execute(() -> mView.updateEmergencyCallButton(
+ /* isInCall= */ isInCall,
+ /* hasTelephonyRadio= */ getContext().getPackageManager()
+ .hasSystemFeature(PackageManager.FEATURE_TELEPHONY),
+ /* simLocked= */ mKeyguardUpdateMonitor.isSimPinVoiceSecure(),
+ /* isSecure= */ isSecure));
+ });
}
}
@@ -129,6 +159,7 @@ public class EmergencyButtonController extends ViewController<EmergencyButton> {
/**
* Shows the emergency dialer or returns the user to the existing call.
*/
+ @SuppressLint("MissingPermission")
public void takeEmergencyCallAction() {
mMetricsLogger.action(MetricsEvent.ACTION_EMERGENCY_CALL);
if (mPowerManager != null) {
@@ -136,29 +167,35 @@ public class EmergencyButtonController extends ViewController<EmergencyButton> {
}
mActivityTaskManager.stopSystemLockTaskMode();
mShadeController.collapseShade(false);
- if (mTelecomManager != null && mTelecomManager.isInCall()) {
- mTelecomManager.showInCallScreen(false);
- if (mEmergencyButtonCallback != null) {
- mEmergencyButtonCallback.onEmergencyButtonClickedWhenInCall();
- }
- } else {
- mKeyguardUpdateMonitor.reportEmergencyCallAction(true /* bypassHandler */);
- if (mTelecomManager == null) {
- Log.wtf(LOG_TAG, "TelecomManager was null, cannot launch emergency dialer");
- return;
- }
- Intent emergencyDialIntent =
- mTelecomManager.createLaunchEmergencyDialerIntent(null /* number*/)
- .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
- | Intent.FLAG_ACTIVITY_CLEAR_TOP)
- .putExtra(EmergencyDialerConstants.EXTRA_ENTRY_TYPE,
- EmergencyDialerConstants.ENTRY_TYPE_LOCKSCREEN_BUTTON);
-
- getContext().startActivityAsUser(emergencyDialIntent,
- ActivityOptions.makeCustomAnimation(getContext(), 0, 0).toBundle(),
- new UserHandle(KeyguardUpdateMonitor.getCurrentUser()));
- }
+ // Run in bg thread to avoid throttling the main thread with binder call.
+ mBackgroundExecutor.execute(() -> {
+ boolean isInCall = mTelecomManager != null && mTelecomManager.isInCall();
+ mMainExecutor.execute(() -> {
+ if (isInCall) {
+ mTelecomManager.showInCallScreen(false);
+ if (mEmergencyButtonCallback != null) {
+ mEmergencyButtonCallback.onEmergencyButtonClickedWhenInCall();
+ }
+ } else {
+ mKeyguardUpdateMonitor.reportEmergencyCallAction(true /* bypassHandler */);
+ if (mTelecomManager == null) {
+ Log.wtf(LOG_TAG, "TelecomManager was null, cannot launch emergency dialer");
+ return;
+ }
+ Intent emergencyDialIntent =
+ mTelecomManager.createLaunchEmergencyDialerIntent(null /* number*/)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
+ | Intent.FLAG_ACTIVITY_CLEAR_TOP)
+ .putExtra(EmergencyDialerConstants.EXTRA_ENTRY_TYPE,
+ EmergencyDialerConstants.ENTRY_TYPE_LOCKSCREEN_BUTTON);
+
+ getContext().startActivityAsUser(emergencyDialIntent,
+ ActivityOptions.makeCustomAnimation(getContext(), 0, 0).toBundle(),
+ new UserHandle(KeyguardUpdateMonitor.getCurrentUser()));
+ }
+ });
+ });
}
/** */
@@ -178,13 +215,19 @@ public class EmergencyButtonController extends ViewController<EmergencyButton> {
@Nullable
private final TelecomManager mTelecomManager;
private final MetricsLogger mMetricsLogger;
+ private final LockPatternUtils mLockPatternUtils;
+ private final Executor mMainExecutor;
+ private final Executor mBackgroundExecutor;
@Inject
public Factory(ConfigurationController configurationController,
KeyguardUpdateMonitor keyguardUpdateMonitor, TelephonyManager telephonyManager,
PowerManager powerManager, ActivityTaskManager activityTaskManager,
ShadeController shadeController,
- @Nullable TelecomManager telecomManager, MetricsLogger metricsLogger) {
+ @Nullable TelecomManager telecomManager, MetricsLogger metricsLogger,
+ LockPatternUtils lockPatternUtils,
+ @Main Executor mainExecutor,
+ @Background Executor backgroundExecutor) {
mConfigurationController = configurationController;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
@@ -194,14 +237,17 @@ public class EmergencyButtonController extends ViewController<EmergencyButton> {
mShadeController = shadeController;
mTelecomManager = telecomManager;
mMetricsLogger = metricsLogger;
+ mLockPatternUtils = lockPatternUtils;
+ mMainExecutor = mainExecutor;
+ mBackgroundExecutor = backgroundExecutor;
}
/** Construct an {@link com.android.keyguard.EmergencyButtonController}. */
public EmergencyButtonController create(EmergencyButton view) {
return new EmergencyButtonController(view, mConfigurationController,
mKeyguardUpdateMonitor, mTelephonyManager, mPowerManager, mActivityTaskManager,
- mShadeController,
- mTelecomManager, mMetricsLogger);
+ mShadeController, mTelecomManager, mMetricsLogger, mLockPatternUtils,
+ mMainExecutor, mBackgroundExecutor);
}
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt b/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
index e0cf7b6a2bc4..d8085b9f9f2e 100644
--- a/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
+++ b/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
@@ -132,6 +132,7 @@ private object InternalFaceAuthReasons {
/**
* UiEvents that are logged to identify why face auth is being triggered.
+ *
* @param extraInfo is logged as the position. See [UiEventLogger#logWithInstanceIdAndPosition]
*/
enum class FaceAuthUiEvent
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
index baaef1983e9c..f8cb38d7488b 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
@@ -44,7 +44,7 @@ import java.util.Map;
public abstract class KeyguardAbsKeyInputViewController<T extends KeyguardAbsKeyInputView>
extends KeyguardInputViewController<T> {
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
- private final LockPatternUtils mLockPatternUtils;
+ protected final LockPatternUtils mLockPatternUtils;
private final LatencyTracker mLatencyTracker;
private final FalsingCollector mFalsingCollector;
private final EmergencyButtonController mEmergencyButtonController;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt
index fe8b8c944d13..c98e9b40e7ab 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt
@@ -40,7 +40,7 @@ data class KeyguardFaceListenModel(
var keyguardGoingAway: Boolean = false,
var listeningForFaceAssistant: Boolean = false,
var occludingAppRequestingFaceAuth: Boolean = false,
- val postureAllowsListening: Boolean = false,
+ var postureAllowsListening: Boolean = false,
var primaryUser: Boolean = false,
var secureCameraLaunched: Boolean = false,
var supportsDetect: Boolean = false,
@@ -70,6 +70,7 @@ data class KeyguardFaceListenModel(
listeningForFaceAssistant.toString(),
occludingAppRequestingFaceAuth.toString(),
primaryUser.toString(),
+ postureAllowsListening.toString(),
secureCameraLaunched.toString(),
supportsDetect.toString(),
switchingUser.toString(),
@@ -109,6 +110,7 @@ data class KeyguardFaceListenModel(
listeningForFaceAssistant = model.listeningForFaceAssistant
occludingAppRequestingFaceAuth = model.occludingAppRequestingFaceAuth
primaryUser = model.primaryUser
+ postureAllowsListening = model.postureAllowsListening
secureCameraLaunched = model.secureCameraLaunched
supportsDetect = model.supportsDetect
switchingUser = model.switchingUser
@@ -152,6 +154,7 @@ data class KeyguardFaceListenModel(
"listeningForFaceAssistant",
"occludingAppRequestingFaceAuth",
"primaryUser",
+ "postureAllowsListening",
"secureCameraLaunched",
"supportsDetect",
"switchingUser",
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
index c1fae9e44bd3..33bea027cd20 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
@@ -69,6 +69,7 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView {
private Interpolator mLinearOutSlowInInterpolator;
private Interpolator mFastOutLinearInInterpolator;
+ private DisappearAnimationListener mDisappearAnimationListener;
public KeyguardPasswordView(Context context) {
this(context, null);
@@ -186,9 +187,13 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView {
return;
}
Insets shownInsets = controller.getShownStateInsets();
- Insets insets = Insets.add(shownInsets, Insets.of(0, 0, 0,
- (int) (-shownInsets.bottom / 4
- * anim.getAnimatedFraction())));
+ int dist = (int) (-shownInsets.bottom / 4
+ * anim.getAnimatedFraction());
+ Insets insets = Insets.add(shownInsets, Insets.of(0, 0, 0, dist));
+ if (mDisappearAnimationListener != null) {
+ mDisappearAnimationListener.setTranslationY(-dist);
+ }
+
controller.setInsetsAndAlpha(insets,
(float) animation.getAnimatedValue(),
anim.getAnimatedFraction());
@@ -209,6 +214,7 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView {
controller.finish(false);
runOnFinishImeAnimationRunnable();
finishRunnable.run();
+ mDisappearAnimationListener = null;
Trace.endSection();
});
}
@@ -286,4 +292,19 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView {
}
});
}
+
+ /**
+ * Listens to the progress of the disappear animation and handles it.
+ */
+ interface DisappearAnimationListener {
+ void setTranslationY(int transY);
+ }
+
+ /**
+ * Set an instance of the disappear animation listener to this class. This will be
+ * removed when the animation completes.
+ */
+ public void setDisappearAnimationListener(DisappearAnimationListener listener) {
+ mDisappearAnimationListener = listener;
+ }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java
index d221e22a4fcd..a010c9a16517 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java
@@ -26,6 +26,7 @@ import android.text.method.TextKeyListener;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup.MarginLayoutParams;
+import android.view.WindowInsets;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
@@ -156,6 +157,15 @@ public class KeyguardPasswordViewController
// TODO: Remove this workaround by ensuring such a race condition never happens.
mMainExecutor.executeDelayed(
this::updateSwitchImeButton, DELAY_MILLIS_TO_REEVALUATE_IME_SWITCH_ICON);
+ mView.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
+ @Override
+ public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
+ if (!mKeyguardViewController.isBouncerShowing()) {
+ mView.hideKeyboard();
+ }
+ return insets;
+ }
+ });
}
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java
index 92e364110547..559db76748ed 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java
@@ -71,13 +71,17 @@ public abstract class KeyguardPinBasedInputViewController<T extends KeyguardPinB
protected void onViewAttached() {
super.onViewAttached();
- for (NumPadKey button: mView.getButtons()) {
+ boolean showAnimations = !mLockPatternUtils
+ .isPinEnhancedPrivacyEnabled(KeyguardUpdateMonitor.getCurrentUser());
+ mPasswordEntry.setShowPassword(showAnimations);
+ for (NumPadKey button : mView.getButtons()) {
button.setOnTouchListener((v, event) -> {
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
mFalsingCollector.avoidGesture();
}
return false;
});
+ button.setAnimationEnabled(showAnimations);
}
mPasswordEntry.setOnKeyListener(mOnKeyListener);
mPasswordEntry.setUserActivityListener(this::onUserInput);
@@ -102,12 +106,9 @@ public abstract class KeyguardPinBasedInputViewController<T extends KeyguardPinB
View okButton = mView.findViewById(R.id.key_enter);
if (okButton != null) {
okButton.setOnTouchListener(mActionButtonTouchListener);
- okButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (mPasswordEntry.isEnabled()) {
- verifyPasswordAndUnlock();
- }
+ okButton.setOnClickListener(v -> {
+ if (mPasswordEntry.isEnabled()) {
+ verifyPasswordAndUnlock();
}
});
okButton.setOnHoverListener(mLiftToActivateListener);
@@ -118,7 +119,7 @@ public abstract class KeyguardPinBasedInputViewController<T extends KeyguardPinB
protected void onViewDetached() {
super.onViewDetached();
- for (NumPadKey button: mView.getButtons()) {
+ for (NumPadKey button : mView.getButtons()) {
button.setOnTouchListener(null);
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index f164e7d33642..29496169e04f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -174,6 +174,17 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
private @Mode int mCurrentMode = MODE_UNINITIALIZED;
private int mWidth = -1;
+ /**
+ * This callback is used to animate KeyguardSecurityContainer and its child views based on
+ * the interaction with the ime. After
+ * {@link WindowInsetsAnimation.Callback#onPrepare(WindowInsetsAnimation)},
+ * {@link #onApplyWindowInsets} is called where we
+ * set the bottom padding to be the height of the keyboard. We use this padding to determine
+ * the delta of vertical distance for y-translation animations.
+ * Note that bottom padding is not set when the disappear animation is started because
+ * we are deferring the y translation logic to the animator in
+ * {@link KeyguardPasswordView#startDisappearAnimation(Runnable)}
+ */
private final WindowInsetsAnimation.Callback mWindowInsetsAnimationCallback =
new WindowInsetsAnimation.Callback(DISPATCH_MODE_STOP) {
@@ -214,7 +225,6 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
continue;
}
interpolatedFraction = animation.getInterpolatedFraction();
-
final int paddingBottom = (int) MathUtils.lerp(
start, end,
interpolatedFraction);
@@ -569,13 +579,21 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
*/
public void startDisappearAnimation(SecurityMode securitySelection) {
mDisappearAnimRunning = true;
- mViewMode.startDisappearAnimation(securitySelection);
+ if (securitySelection == SecurityMode.Password
+ && mSecurityViewFlipper.getSecurityView() instanceof KeyguardPasswordView) {
+ ((KeyguardPasswordView) mSecurityViewFlipper.getSecurityView())
+ .setDisappearAnimationListener(this::setTranslationY);
+ } else {
+ mViewMode.startDisappearAnimation(securitySelection);
+ }
}
/**
* This will run when the bouncer shows in all cases except when the user drags the bouncer up.
*/
public void startAppearAnimation(SecurityMode securityMode) {
+ setTranslationY(0f);
+ setAlpha(1f);
updateChildren(0 /* translationY */, 1f /* alpha */);
mViewMode.startAppearAnimation(securityMode);
}
@@ -624,7 +642,13 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
int inset = max(bottomInset, imeInset);
int paddingBottom = max(inset, getContext().getResources()
.getDimensionPixelSize(R.dimen.keyguard_security_view_bottom_margin));
- setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), paddingBottom);
+ // If security mode is password, we rely on the animation value of defined in
+ // KeyguardPasswordView to determine the y translation animation.
+ // This means that we will prevent the WindowInsetsAnimationCallback from setting any y
+ // translation values by preventing the setting of the padding here.
+ if (!mDisappearAnimRunning) {
+ setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), paddingBottom);
+ }
return insets.inset(0, 0, 0, inset);
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index b53b868025e8..f4c581552bc4 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -21,8 +21,6 @@ import android.util.Slog;
import com.android.keyguard.KeyguardClockSwitch.ClockSize;
import com.android.keyguard.logging.KeyguardLogger;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.ClockAnimations;
import com.android.systemui.statusbar.notification.AnimatableProperty;
import com.android.systemui.statusbar.notification.PropertyAnimator;
@@ -62,7 +60,6 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
KeyguardUpdateMonitor keyguardUpdateMonitor,
ConfigurationController configurationController,
DozeParameters dozeParameters,
- FeatureFlags featureFlags,
ScreenOffAnimationController screenOffAnimationController,
KeyguardLogger logger) {
super(keyguardStatusView);
@@ -73,8 +70,6 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
mKeyguardVisibilityHelper = new KeyguardVisibilityHelper(mView, keyguardStateController,
dozeParameters, screenOffAnimationController, /* animateYPos= */ true,
logger.getBuffer());
- mKeyguardVisibilityHelper.setOcclusionTransitionFlagEnabled(
- featureFlags.isEnabled(Flags.UNOCCLUSION_TRANSITION));
}
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index b8e1499a5ae7..21d35c9579ea 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -29,6 +29,7 @@ import static android.hardware.biometrics.BiometricConstants.LockoutMode;
import static android.hardware.biometrics.BiometricSourceType.FACE;
import static android.hardware.biometrics.BiometricSourceType.FINGERPRINT;
import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
+import static android.os.PowerManager.WAKE_REASON_UNKNOWN;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
@@ -73,11 +74,9 @@ import static com.android.systemui.statusbar.policy.DevicePostureController.DEVI
import android.annotation.AnyThread;
import android.annotation.MainThread;
import android.annotation.SuppressLint;
-import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.ActivityTaskManager.RootTaskInfo;
import android.app.AlarmManager;
-import android.app.UserSwitchObserver;
import android.app.admin.DevicePolicyManager;
import android.app.trust.TrustManager;
import android.content.BroadcastReceiver;
@@ -96,8 +95,10 @@ import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricSourceType;
import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
import android.hardware.biometrics.SensorProperties;
+import android.hardware.face.FaceAuthenticateOptions;
import android.hardware.face.FaceManager;
import android.hardware.face.FaceSensorPropertiesInternal;
+import android.hardware.fingerprint.FingerprintAuthenticateOptions;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
@@ -106,7 +107,6 @@ import android.hardware.usb.UsbManager;
import android.nfc.NfcAdapter;
import android.os.CancellationSignal;
import android.os.Handler;
-import android.os.IRemoteCallback;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
@@ -137,9 +137,9 @@ import com.android.internal.logging.UiEventLogger;
import com.android.internal.util.LatencyTracker;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.logging.KeyguardUpdateMonitorLogger;
+import com.android.settingslib.Utils;
import com.android.settingslib.WirelessUtils;
import com.android.settingslib.fuelgauge.BatteryStatus;
-import com.android.settingslib.Utils;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.biometrics.AuthController;
@@ -150,6 +150,7 @@ import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.dump.DumpsysTableLogger;
+import com.android.systemui.keyguard.shared.model.SysUiFaceAuthenticateOptions;
import com.android.systemui.log.SessionTracker;
import com.android.systemui.plugins.WeatherData;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -159,6 +160,7 @@ import com.android.systemui.shared.system.TaskStackChangeListeners;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.policy.DevicePostureController;
+import com.android.systemui.statusbar.policy.DevicePostureController.DevicePostureInt;
import com.android.systemui.telephony.TelephonyListenerManager;
import com.android.systemui.util.Assert;
import com.android.systemui.util.settings.SecureSettings;
@@ -178,6 +180,7 @@ import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.TimeZone;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;
@@ -366,7 +369,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private final FaceManager mFaceManager;
private final LockPatternUtils mLockPatternUtils;
@VisibleForTesting
- @DevicePostureController.DevicePostureInt
+ @DevicePostureInt
protected int mConfigFaceAuthSupportedPosture;
private KeyguardBypassController mKeyguardBypassController;
@@ -683,7 +686,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
public void onTrustManagedChanged(boolean managed, int userId) {
Assert.isMainThread();
mUserTrustIsManaged.put(userId, managed);
- mUserTrustIsUsuallyManaged.put(userId, mTrustManager.isTrustUsuallyManaged(userId));
+ boolean trustUsuallyManaged = mTrustManager.isTrustUsuallyManaged(userId);
+ mLogger.logTrustUsuallyManagedUpdated(userId, mUserTrustIsUsuallyManaged.get(userId),
+ trustUsuallyManaged, "onTrustManagedChanged");
+ mUserTrustIsUsuallyManaged.put(userId, trustUsuallyManaged);
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -821,6 +827,19 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
}
+ private void onBiometricDetected(int userId, BiometricSourceType biometricSourceType,
+ boolean isStrongBiometric) {
+ Assert.isMainThread();
+ Trace.beginSection("KeyGuardUpdateMonitor#onBiometricDetected");
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+ if (cb != null) {
+ cb.onBiometricDetected(userId, biometricSourceType, isStrongBiometric);
+ }
+ }
+ Trace.endSection();
+ }
+
@VisibleForTesting
protected void onFingerprintAuthenticated(int userId, boolean isStrongBiometric) {
Assert.isMainThread();
@@ -897,6 +916,20 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
}
+ private void handleBiometricDetected(int authUserId, BiometricSourceType biometricSourceType,
+ boolean isStrongBiometric) {
+ Trace.beginSection("KeyGuardUpdateMonitor#handlerBiometricDetected");
+ onBiometricDetected(authUserId, biometricSourceType, isStrongBiometric);
+ if (biometricSourceType == FINGERPRINT) {
+ mLogger.logFingerprintDetected(authUserId, isStrongBiometric);
+ } else if (biometricSourceType == FACE) {
+ mLogger.logFaceDetected(authUserId, isStrongBiometric);
+ setFaceRunningState(BIOMETRIC_STATE_STOPPED);
+ }
+
+ Trace.endSection();
+ }
+
private void handleFingerprintAuthenticated(int authUserId, boolean isStrongBiometric) {
Trace.beginSection("KeyGuardUpdateMonitor#handlerFingerPrintAuthenticated");
if (mHandler.hasCallbacks(mFpCancelNotReceived)) {
@@ -948,8 +981,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private void onFingerprintCancelNotReceived() {
mLogger.e("Fp cancellation not received, transitioning to STOPPED");
+ final boolean wasCancellingRestarting = mFingerprintRunningState
+ == BIOMETRIC_STATE_CANCELLING_RESTARTING;
mFingerprintRunningState = BIOMETRIC_STATE_STOPPED;
- KeyguardUpdateMonitor.this.updateFingerprintListeningState(BIOMETRIC_ACTION_STOP);
+ if (wasCancellingRestarting) {
+ KeyguardUpdateMonitor.this.updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE);
+ } else {
+ KeyguardUpdateMonitor.this.updateFingerprintListeningState(BIOMETRIC_ACTION_STOP);
+ }
}
private void handleFingerprintError(int msgId, String errString) {
@@ -1036,6 +1075,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
() -> updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE),
getBiometricLockoutDelay());
} else {
+ boolean temporaryLockoutReset = wasLockout && !mFingerprintLockedOut;
+ if (temporaryLockoutReset) {
+ mLogger.d("temporaryLockoutReset - stopListeningForFingerprint() to stop"
+ + " detectFingerprint");
+ stopListeningForFingerprint();
+ }
updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE);
}
@@ -1745,10 +1790,16 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
};
+ private final FingerprintManager.FingerprintDetectionCallback mFingerprintDetectionCallback =
+ (sensorId, userId, isStrongBiometric) -> {
+ // Trigger the fingerprint detected path so the bouncer can be shown
+ handleBiometricDetected(userId, FINGERPRINT, isStrongBiometric);
+ };
+
private final FaceManager.FaceDetectionCallback mFaceDetectionCallback
= (sensorId, userId, isStrongBiometric) -> {
- // Trigger the face success path so the bouncer can be shown
- handleFaceAuthenticated(userId, isStrongBiometric);
+ // Trigger the face detected path so the bouncer can be shown
+ handleBiometricDetected(userId, FACE, isStrongBiometric);
};
@VisibleForTesting
@@ -1812,10 +1863,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
final DevicePostureController.Callback mPostureCallback =
new DevicePostureController.Callback() {
@Override
- public void onPostureChanged(int posture) {
+ public void onPostureChanged(@DevicePostureInt int posture) {
+ boolean currentPostureAllowsFaceAuth = doesPostureAllowFaceAuth(mPostureState);
+ boolean newPostureAllowsFaceAuth = doesPostureAllowFaceAuth(posture);
mPostureState = posture;
- updateFaceListeningState(BIOMETRIC_ACTION_UPDATE,
- FACE_AUTH_UPDATED_POSTURE_CHANGED);
+ if (currentPostureAllowsFaceAuth && !newPostureAllowsFaceAuth) {
+ mLogger.d("New posture does not allow face auth, stopping it");
+ updateFaceListeningState(BIOMETRIC_ACTION_STOP,
+ FACE_AUTH_UPDATED_POSTURE_CHANGED);
+ }
}
};
@@ -2173,7 +2229,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
handleDevicePolicyManagerStateChanged(msg.arg1);
break;
case MSG_USER_SWITCHING:
- handleUserSwitching(msg.arg1, (IRemoteCallback) msg.obj);
+ handleUserSwitching(msg.arg1, (CountDownLatch) msg.obj);
break;
case MSG_USER_SWITCH_COMPLETE:
handleUserSwitchComplete(msg.arg1);
@@ -2299,11 +2355,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
mHandler, UserHandle.ALL);
mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener);
- try {
- ActivityManager.getService().registerUserSwitchObserver(mUserSwitchObserver, TAG);
- } catch (RemoteException e) {
- e.rethrowAsRuntimeException();
- }
+ mUserTracker.addCallback(mUserChangedCallback, mainExecutor);
mTrustManager.registerTrustListener(this);
@@ -2350,8 +2402,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
updateSecondaryLockscreenRequirement(user);
List<UserInfo> allUsers = mUserManager.getUsers();
for (UserInfo userInfo : allUsers) {
+ boolean trustUsuallyManaged = mTrustManager.isTrustUsuallyManaged(userInfo.id);
+ mLogger.logTrustUsuallyManagedUpdated(userInfo.id,
+ mUserTrustIsUsuallyManaged.get(userInfo.id),
+ trustUsuallyManaged, "init from constructor");
mUserTrustIsUsuallyManaged.put(userInfo.id,
- mTrustManager.isTrustUsuallyManaged(userInfo.id));
+ trustUsuallyManaged);
}
updateAirplaneModeState();
@@ -2391,9 +2447,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
private void updateFaceEnrolled(int userId) {
- mIsFaceEnrolled = mFaceManager != null && !mFaceSensorProperties.isEmpty()
+ Boolean isFaceEnrolled = mFaceManager != null && !mFaceSensorProperties.isEmpty()
&& mBiometricEnabledForUser.get(userId)
&& mAuthController.isFaceAuthEnrolled(userId);
+ mIsFaceEnrolled = isFaceEnrolled;
+ mLogger.logFaceEnrolledUpdated(mIsFaceEnrolled, isFaceEnrolled);
}
public boolean isFaceSupported() {
@@ -2439,17 +2497,17 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
return mIsFaceEnrolled;
}
- private final UserSwitchObserver mUserSwitchObserver = new UserSwitchObserver() {
+ private final UserTracker.Callback mUserChangedCallback = new UserTracker.Callback() {
@Override
- public void onUserSwitching(int newUserId, IRemoteCallback reply) {
+ public void onUserChanging(int newUser, Context userContext, CountDownLatch latch) {
mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHING,
- newUserId, 0, reply));
+ newUser, 0, latch));
}
@Override
- public void onUserSwitchComplete(int newUserId) {
+ public void onUserChanged(int newUser, Context userContext) {
mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCH_COMPLETE,
- newUserId, 0));
+ newUser, 0));
}
};
@@ -2781,8 +2839,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
boolean shouldListen = shouldListenKeyguardState && shouldListenUserState
&& shouldListenBouncerState && shouldListenUdfpsState
- && shouldListenSideFpsState
- && !isFingerprintLockedOut();
+ && shouldListenSideFpsState;
logListenerModelData(
new KeyguardFingerprintListenModel(
System.currentTimeMillis(),
@@ -2850,9 +2907,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
final boolean biometricEnabledForUser = mBiometricEnabledForUser.get(user);
final boolean shouldListenForFaceAssistant = shouldListenForFaceAssistant();
final boolean isUdfpsFingerDown = mAuthController.isUdfpsFingerDown();
- final boolean isPostureAllowedForFaceAuth =
- mConfigFaceAuthSupportedPosture == 0 /* DEVICE_POSTURE_UNKNOWN */ ? true
- : (mPostureState == mConfigFaceAuthSupportedPosture);
+ final boolean isPostureAllowedForFaceAuth = doesPostureAllowFaceAuth(mPostureState);
// Only listen if this KeyguardUpdateMonitor belongs to the primary user. There is an
// instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware.
final boolean shouldListen =
@@ -2901,6 +2956,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
return shouldListen;
}
+ private boolean doesPostureAllowFaceAuth(@DevicePostureInt int posture) {
+ return mConfigFaceAuthSupportedPosture == DEVICE_POSTURE_UNKNOWN
+ || (posture == mConfigFaceAuthSupportedPosture);
+ }
+
private void logListenerModelData(@NonNull KeyguardListenModel model) {
mLogger.logKeyguardListenerModel(model);
if (model instanceof KeyguardFingerprintListenModel) {
@@ -2937,12 +2997,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
mLogger.v("startListeningForFingerprint - detect");
mFpm.detectFingerprint(
mFingerprintCancelSignal,
- (sensorId, user, isStrongBiometric) -> {
- mLogger.d("fingerprint detected");
- // Trigger the fingerprint success path so the bouncer can be shown
- handleFingerprintAuthenticated(user, isStrongBiometric);
- },
- userId);
+ mFingerprintDetectionCallback,
+ new FingerprintAuthenticateOptions.Builder()
+ .setUserId(userId)
+ .build());
} else {
mLogger.v("startListeningForFingerprint - authenticate");
mFpm.authenticate(null /* crypto */, mFingerprintCancelSignal,
@@ -2979,6 +3037,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
if (unlockPossible) {
mFaceCancelSignal = new CancellationSignal();
+ final FaceAuthenticateOptions faceAuthenticateOptions =
+ new SysUiFaceAuthenticateOptions(
+ userId,
+ faceAuthUiEvent,
+ faceAuthUiEvent == FACE_AUTH_UPDATED_STARTED_WAKING_UP
+ ? faceAuthUiEvent.getExtraInfo()
+ : WAKE_REASON_UNKNOWN
+ ).toFaceAuthenticateOptions();
// This would need to be updated for multi-sensor devices
final boolean supportsFaceDetection = !mFaceSensorProperties.isEmpty()
&& mFaceSensorProperties.get(0).supportsFaceDetection;
@@ -2988,7 +3054,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
if (supportsFaceDetection && !udfpsFingerprintAuthRunning) {
// Run face detection. (If a face is detected, show the bouncer.)
mLogger.v("startListeningForFace - detect");
- mFaceManager.detectFace(mFaceCancelSignal, mFaceDetectionCallback, userId);
+ mFaceManager.detectFace(mFaceCancelSignal, mFaceDetectionCallback,
+ faceAuthenticateOptions);
} else {
// Don't run face detection. Instead, inform the user
// face auth is unavailable and how to proceed.
@@ -3007,7 +3074,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
final boolean isBypassEnabled = mKeyguardBypassController != null
&& mKeyguardBypassController.isBypassEnabled();
mFaceManager.authenticate(null /* crypto */, mFaceCancelSignal,
- mFaceAuthenticationCallback, null /* handler */, userId, isBypassEnabled);
+ mFaceAuthenticationCallback, null /* handler */,
+ faceAuthenticateOptions);
}
setFaceRunningState(BIOMETRIC_STATE_RUNNING);
}
@@ -3053,9 +3121,13 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
@VisibleForTesting
boolean isUnlockWithFingerprintPossible(int userId) {
// TODO (b/242022358), make this rely on onEnrollmentChanged event and update it only once.
- mIsUnlockWithFingerprintPossible.put(userId, mFpm != null
+ boolean fpEnrolled = mFpm != null
&& !mFingerprintSensorProperties.isEmpty()
- && !isFingerprintDisabled(userId) && mFpm.hasEnrolledTemplates(userId));
+ && !isFingerprintDisabled(userId) && mFpm.hasEnrolledTemplates(userId);
+ mLogger.logFpEnrolledUpdated(userId,
+ mIsUnlockWithFingerprintPossible.getOrDefault(userId, false),
+ fpEnrolled);
+ mIsUnlockWithFingerprintPossible.put(userId, fpEnrolled);
return mIsUnlockWithFingerprintPossible.get(userId);
}
@@ -3168,21 +3240,20 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
* Handle {@link #MSG_USER_SWITCHING}
*/
@VisibleForTesting
- void handleUserSwitching(int userId, IRemoteCallback reply) {
+ void handleUserSwitching(int userId, CountDownLatch latch) {
Assert.isMainThread();
clearBiometricRecognized();
- mUserTrustIsUsuallyManaged.put(userId, mTrustManager.isTrustUsuallyManaged(userId));
+ boolean trustUsuallyManaged = mTrustManager.isTrustUsuallyManaged(userId);
+ mLogger.logTrustUsuallyManagedUpdated(userId, mUserTrustIsUsuallyManaged.get(userId),
+ trustUsuallyManaged, "userSwitching");
+ mUserTrustIsUsuallyManaged.put(userId, trustUsuallyManaged);
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onUserSwitching(userId);
}
}
- try {
- reply.sendResult(null);
- } catch (RemoteException e) {
- mLogger.logException(e, "Ignored exception while userSwitching");
- }
+ latch.countDown();
}
/**
@@ -3955,13 +4026,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
mContext.getContentResolver().unregisterContentObserver(mTimeFormatChangeObserver);
}
- try {
- ActivityManager.getService().unregisterUserSwitchObserver(mUserSwitchObserver);
- } catch (RemoteException e) {
- mLogger.logException(
- e,
- "RemoteException onDestroy. cannot unregister userSwitchObserver");
- }
+ mUserTracker.removeCallback(mUserChangedCallback);
TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index 38f3e5065eec..0d4889a4c39f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -214,7 +214,7 @@ public class KeyguardUpdateMonitorCallback {
public void onBiometricAuthFailed(BiometricSourceType biometricSourceType) { }
/**
- * Called when a biometric is recognized.
+ * Called when a biometric is authenticated.
* @param userId the user id for which the biometric sample was authenticated
* @param biometricSourceType
*/
@@ -222,6 +222,14 @@ public class KeyguardUpdateMonitorCallback {
boolean isStrongBiometric) { }
/**
+ * Called when a biometric is detected but not successfully authenticated.
+ * @param userId the user id for which the biometric sample was detected
+ * @param biometricSourceType
+ */
+ public void onBiometricDetected(int userId, BiometricSourceType biometricSourceType,
+ boolean isStrongBiometric) { }
+
+ /**
* Called when biometric authentication provides help string (e.g. "Try again")
* @param msgId
* @param helpString
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java b/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
index 7e48193bfc62..a678edc0eb06 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
@@ -28,7 +28,6 @@ import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.AnimatableProperty;
import com.android.systemui.statusbar.notification.PropertyAnimator;
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
-import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -49,7 +48,6 @@ public class KeyguardVisibilityHelper {
private boolean mAnimateYPos;
private boolean mKeyguardViewVisibilityAnimating;
private boolean mLastOccludedState = false;
- private boolean mIsUnoccludeTransitionFlagEnabled = false;
private final AnimationProperties mAnimationProperties = new AnimationProperties();
private final LogBuffer mLogBuffer;
@@ -77,10 +75,6 @@ public class KeyguardVisibilityHelper {
return mKeyguardViewVisibilityAnimating;
}
- public void setOcclusionTransitionFlagEnabled(boolean enabled) {
- mIsUnoccludeTransitionFlagEnabled = enabled;
- }
-
/**
* Set the visibility of a keyguard view based on some new state.
*/
@@ -156,24 +150,9 @@ public class KeyguardVisibilityHelper {
// since it may need to be cancelled due to keyguard lifecycle events.
mScreenOffAnimationController.animateInKeyguard(
mView, mAnimateKeyguardStatusViewVisibleEndRunnable);
- } else if (!mIsUnoccludeTransitionFlagEnabled && mLastOccludedState && !isOccluded) {
- // An activity was displayed over the lock screen, and has now gone away
- log("Unoccluded transition");
- mView.setVisibility(View.VISIBLE);
- mView.setAlpha(0f);
-
- mView.animate()
- .setDuration(StackStateAnimator.ANIMATION_DURATION_WAKEUP)
- .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
- .alpha(1f)
- .withEndAction(mAnimateKeyguardStatusViewVisibleEndRunnable)
- .start();
} else {
log("Direct set Visibility to VISIBLE");
mView.setVisibility(View.VISIBLE);
- if (!mIsUnoccludeTransitionFlagEnabled) {
- mView.setAlpha(1f);
- }
}
} else {
log("Direct set Visibility to GONE");
diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java b/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
index b30a0e010e4b..ad669099284f 100644
--- a/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
+++ b/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
@@ -51,7 +51,6 @@ class NumPadAnimator {
private float mStartRadius;
private float mEndRadius;
private int mHeight;
- private boolean mInitialized;
private static final int EXPAND_ANIMATION_MS = 100;
private static final int EXPAND_COLOR_ANIMATION_MS = 50;
@@ -93,15 +92,15 @@ class NumPadAnimator {
}
void onLayout(int height) {
+ boolean shouldUpdateHeight = height != mHeight;
mHeight = height;
mStartRadius = height / 2f;
mEndRadius = height / 4f;
mExpandAnimator.setFloatValues(mStartRadius, mEndRadius);
mContractAnimator.setFloatValues(mEndRadius, mStartRadius);
// Set initial corner radius.
- if (!mInitialized) {
+ if (shouldUpdateHeight) {
mBackground.setCornerRadius(mStartRadius);
- mInitialized = true;
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
index 0a4880e1ce66..7c7680afe368 100644
--- a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
+++ b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
@@ -33,7 +33,6 @@ import android.widget.TextView;
import androidx.annotation.Nullable;
-import com.android.internal.widget.LockPatternUtils;
import com.android.settingslib.Utils;
import com.android.systemui.R;
@@ -46,12 +45,12 @@ public class NumPadKey extends ViewGroup implements NumPadAnimationListener {
private final TextView mDigitText;
private final TextView mKlondikeText;
- private final LockPatternUtils mLockPatternUtils;
private final PowerManager mPM;
private int mDigit = -1;
private int mTextViewResId;
private PasswordTextView mTextView;
+ private boolean mAnimationsEnabled = true;
@Nullable
private NumPadAnimator mAnimator;
@@ -107,7 +106,6 @@ public class NumPadKey extends ViewGroup implements NumPadAnimationListener {
setOnHoverListener(new LiftToActivateListener(
(AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE)));
- mLockPatternUtils = new LockPatternUtils(context);
mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
@@ -167,11 +165,11 @@ public class NumPadKey extends ViewGroup implements NumPadAnimationListener {
switch(event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
doHapticKeyClick();
- if (mAnimator != null) mAnimator.expand();
+ if (mAnimator != null && mAnimationsEnabled) mAnimator.expand();
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
- if (mAnimator != null) mAnimator.contract();
+ if (mAnimator != null && mAnimationsEnabled) mAnimator.contract();
break;
}
return super.onTouchEvent(event);
@@ -231,4 +229,11 @@ public class NumPadKey extends ViewGroup implements NumPadAnimationListener {
mAnimator.setProgress(progress);
}
}
+
+ /**
+ * Controls the animation when a key is pressed
+ */
+ public void setAnimationEnabled(boolean enabled) {
+ mAnimationsEnabled = enabled;
+ }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java b/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
index 8554e11a2f3c..540001135543 100644
--- a/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
+++ b/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
@@ -30,7 +30,6 @@ import android.graphics.Rect;
import android.graphics.Typeface;
import android.os.PowerManager;
import android.os.SystemClock;
-import android.provider.Settings;
import android.text.InputType;
import android.text.TextUtils;
import android.util.AttributeSet;
@@ -100,7 +99,7 @@ public class PasswordTextView extends FrameLayout {
private Interpolator mAppearInterpolator;
private Interpolator mDisappearInterpolator;
private Interpolator mFastOutSlowInInterpolator;
- private boolean mShowPassword;
+ private boolean mShowPassword = true;
private UserActivityListener mUserActivityListener;
private PinShapeInput mPinShapeInput;
private boolean mUsePinShapes = false;
@@ -158,8 +157,6 @@ public class PasswordTextView extends FrameLayout {
mDrawPaint.setTypeface(Typeface.create(
context.getString(com.android.internal.R.string.config_headlineFontFamily),
0));
- mShowPassword = Settings.System.getInt(mContext.getContentResolver(),
- Settings.System.TEXT_SHOW_PASSWORD, 1) == 1;
mAppearInterpolator = AnimationUtils.loadInterpolator(mContext,
android.R.interpolator.linear_out_slow_in);
mDisappearInterpolator = AnimationUtils.loadInterpolator(mContext,
@@ -441,6 +438,13 @@ public class PasswordTextView extends FrameLayout {
addView(mPinShapeInput.getView());
}
+ /**
+ * Controls whether the last entered digit is briefly shown after being entered
+ */
+ public void setShowPassword(boolean enabled) {
+ mShowPassword = enabled;
+ }
+
private class CharState {
char whichChar;
ValueAnimator textAnimator;
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
index c414c088529c..fb2c02ad8c48 100644
--- a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
+++ b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
@@ -26,6 +26,7 @@ import com.android.keyguard.FaceAuthUiEvent
import com.android.keyguard.KeyguardListenModel
import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.keyguard.TrustGrantFlags
+import com.android.systemui.log.dagger.KeyguardUpdateMonitorLog
import com.android.systemui.plugins.log.LogBuffer
import com.android.systemui.plugins.log.LogLevel
import com.android.systemui.plugins.log.LogLevel.DEBUG
@@ -33,18 +34,15 @@ import com.android.systemui.plugins.log.LogLevel.ERROR
import com.android.systemui.plugins.log.LogLevel.INFO
import com.android.systemui.plugins.log.LogLevel.VERBOSE
import com.android.systemui.plugins.log.LogLevel.WARNING
-import com.android.systemui.log.dagger.KeyguardUpdateMonitorLog
import com.google.errorprone.annotations.CompileTimeConstant
import javax.inject.Inject
private const val TAG = "KeyguardUpdateMonitorLog"
-/**
- * Helper class for logging for [com.android.keyguard.KeyguardUpdateMonitor]
- */
-class KeyguardUpdateMonitorLogger @Inject constructor(
- @KeyguardUpdateMonitorLog private val logBuffer: LogBuffer
-) {
+/** Helper class for logging for [com.android.keyguard.KeyguardUpdateMonitor] */
+class KeyguardUpdateMonitorLogger
+@Inject
+constructor(@KeyguardUpdateMonitorLog private val logBuffer: LogBuffer) {
fun d(@CompileTimeConstant msg: String) = log(msg, DEBUG)
fun e(@CompileTimeConstant msg: String) = log(msg, ERROR)
@@ -56,15 +54,16 @@ class KeyguardUpdateMonitorLogger @Inject constructor(
fun log(@CompileTimeConstant msg: String, level: LogLevel) = logBuffer.log(TAG, level, msg)
fun logActiveUnlockTriggered(reason: String?) {
- logBuffer.log("ActiveUnlock", DEBUG,
- { str1 = reason },
- { "initiate active unlock triggerReason=$str1" })
+ logBuffer.log(
+ "ActiveUnlock",
+ DEBUG,
+ { str1 = reason },
+ { "initiate active unlock triggerReason=$str1" }
+ )
}
fun logAuthInterruptDetected(active: Boolean) {
- logBuffer.log(TAG, DEBUG,
- { bool1 = active },
- { "onAuthInterruptDetected($bool1)" })
+ logBuffer.log(TAG, DEBUG, { bool1 = active }, { "onAuthInterruptDetected($bool1)" })
}
fun logBroadcastReceived(action: String?) {
@@ -72,9 +71,12 @@ class KeyguardUpdateMonitorLogger @Inject constructor(
}
fun logDeviceProvisionedState(deviceProvisioned: Boolean) {
- logBuffer.log(TAG, DEBUG,
- { bool1 = deviceProvisioned },
- { "DEVICE_PROVISIONED state = $bool1" })
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ { bool1 = deviceProvisioned },
+ { "DEVICE_PROVISIONED state = $bool1" }
+ )
}
fun logException(ex: Exception, @CompileTimeConstant logMsg: String) {
@@ -82,46 +84,56 @@ class KeyguardUpdateMonitorLogger @Inject constructor(
}
fun logFaceAcquired(acquireInfo: Int) {
- logBuffer.log(TAG, DEBUG,
- { int1 = acquireInfo },
- { "Face acquired acquireInfo=$int1" })
+ logBuffer.log(TAG, DEBUG, { int1 = acquireInfo }, { "Face acquired acquireInfo=$int1" })
}
fun logFaceAuthDisabledForUser(userId: Int) {
- logBuffer.log(TAG, DEBUG,
- { int1 = userId },
- { "Face authentication disabled by DPM for userId: $int1" })
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ { int1 = userId },
+ { "Face authentication disabled by DPM for userId: $int1" }
+ )
}
fun logFaceAuthError(msgId: Int, originalErrMsg: String) {
- logBuffer.log(TAG, DEBUG, {
- str1 = originalErrMsg
- int1 = msgId
- }, { "Face error received: $str1 msgId= $int1" })
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ str1 = originalErrMsg
+ int1 = msgId
+ },
+ { "Face error received: $str1 msgId= $int1" }
+ )
}
fun logFaceAuthForWrongUser(authUserId: Int) {
- logBuffer.log(TAG, DEBUG,
- { int1 = authUserId },
- { "Face authenticated for wrong user: $int1" })
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ { int1 = authUserId },
+ { "Face authenticated for wrong user: $int1" }
+ )
}
fun logFaceAuthHelpMsg(msgId: Int, helpMsg: String?) {
- logBuffer.log(TAG, DEBUG, {
- int1 = msgId
- str1 = helpMsg
- }, { "Face help received, msgId: $int1 msg: $str1" })
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ int1 = msgId
+ str1 = helpMsg
+ },
+ { "Face help received, msgId: $int1 msg: $str1" }
+ )
}
fun logFaceAuthRequested(reason: String?) {
- logBuffer.log(TAG, DEBUG, {
- str1 = reason
- }, { "requestFaceAuth() reason=$str1" })
+ logBuffer.log(TAG, DEBUG, { str1 = reason }, { "requestFaceAuth() reason=$str1" })
}
fun logFaceAuthSuccess(userId: Int) {
- logBuffer.log(TAG, DEBUG,
- { int1 = userId },
- { "Face auth succeeded for user $int1" })
+ logBuffer.log(TAG, DEBUG, { int1 = userId }, { "Face auth succeeded for user $int1" })
}
fun logFaceLockoutReset(@LockoutMode mode: Int) {
@@ -133,21 +145,30 @@ class KeyguardUpdateMonitorLogger @Inject constructor(
}
fun logFaceUnlockPossible(isFaceUnlockPossible: Boolean) {
- logBuffer.log(TAG, DEBUG,
- { bool1 = isFaceUnlockPossible },
- {"isUnlockWithFacePossible: $bool1"})
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ { bool1 = isFaceUnlockPossible },
+ { "isUnlockWithFacePossible: $bool1" }
+ )
}
fun logFingerprintAuthForWrongUser(authUserId: Int) {
- logBuffer.log(TAG, DEBUG,
- { int1 = authUserId },
- { "Fingerprint authenticated for wrong user: $int1" })
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ { int1 = authUserId },
+ { "Fingerprint authenticated for wrong user: $int1" }
+ )
}
fun logFingerprintDisabledForUser(userId: Int) {
- logBuffer.log(TAG, DEBUG,
- { int1 = userId },
- { "Fingerprint disabled by DPM for userId: $int1" })
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ { int1 = userId },
+ { "Fingerprint disabled by DPM for userId: $int1" }
+ )
}
fun logFingerprintLockoutReset(@LockoutMode mode: Int) {
@@ -155,42 +176,77 @@ class KeyguardUpdateMonitorLogger @Inject constructor(
}
fun logFingerprintRunningState(fingerprintRunningState: Int) {
- logBuffer.log(TAG, DEBUG,
- { int1 = fingerprintRunningState },
- { "fingerprintRunningState: $int1" })
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ { int1 = fingerprintRunningState },
+ { "fingerprintRunningState: $int1" }
+ )
}
fun logFingerprintSuccess(userId: Int, isStrongBiometric: Boolean) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ int1 = userId
+ bool1 = isStrongBiometric
+ },
+ { "Fingerprint auth successful: userId: $int1, isStrongBiometric: $bool1" }
+ )
+ }
+
+ fun logFaceDetected(userId: Int, isStrongBiometric: Boolean) {
logBuffer.log(TAG, DEBUG, {
int1 = userId
bool1 = isStrongBiometric
- }, {"Fingerprint auth successful: userId: $int1, isStrongBiometric: $bool1"})
+ }, {"Face detected: userId: $int1, isStrongBiometric: $bool1"})
}
- fun logFingerprintError(msgId: Int, originalErrMsg: String) {
+ fun logFingerprintDetected(userId: Int, isStrongBiometric: Boolean) {
logBuffer.log(TAG, DEBUG, {
- str1 = originalErrMsg
- int1 = msgId
- }, { "Fingerprint error received: $str1 msgId= $int1" })
+ int1 = userId
+ bool1 = isStrongBiometric
+ }, {"Fingerprint detected: userId: $int1, isStrongBiometric: $bool1"})
+ }
+
+ fun logFingerprintError(msgId: Int, originalErrMsg: String) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ str1 = originalErrMsg
+ int1 = msgId
+ },
+ { "Fingerprint error received: $str1 msgId= $int1" }
+ )
}
fun logInvalidSubId(subId: Int) {
- logBuffer.log(TAG, INFO,
- { int1 = subId },
- { "Previously active sub id $int1 is now invalid, will remove" })
+ logBuffer.log(
+ TAG,
+ INFO,
+ { int1 = subId },
+ { "Previously active sub id $int1 is now invalid, will remove" }
+ )
}
fun logPrimaryKeyguardBouncerChanged(
- primaryBouncerIsOrWillBeShowing: Boolean,
- primaryBouncerFullyShown: Boolean
+ primaryBouncerIsOrWillBeShowing: Boolean,
+ primaryBouncerFullyShown: Boolean
) {
- logBuffer.log(TAG, DEBUG, {
- bool1 = primaryBouncerIsOrWillBeShowing
- bool2 = primaryBouncerFullyShown
- }, {
- "handlePrimaryBouncerChanged " +
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ bool1 = primaryBouncerIsOrWillBeShowing
+ bool2 = primaryBouncerFullyShown
+ },
+ {
+ "handlePrimaryBouncerChanged " +
"primaryBouncerIsOrWillBeShowing=$bool1 primaryBouncerFullyShown=$bool2"
- })
+ }
+ )
}
fun logKeyguardListenerModel(model: KeyguardListenModel) {
@@ -198,98 +254,134 @@ class KeyguardUpdateMonitorLogger @Inject constructor(
}
fun logKeyguardShowingChanged(showing: Boolean, occluded: Boolean, visible: Boolean) {
- logBuffer.log(TAG, DEBUG, {
- bool1 = showing
- bool2 = occluded
- bool3 = visible
- }, {
- "keyguardShowingChanged(showing=$bool1 occluded=$bool2 visible=$bool3)"
- })
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ bool1 = showing
+ bool2 = occluded
+ bool3 = visible
+ },
+ { "keyguardShowingChanged(showing=$bool1 occluded=$bool2 visible=$bool3)" }
+ )
}
fun logMissingSupervisorAppError(userId: Int) {
- logBuffer.log(TAG, ERROR,
- { int1 = userId },
- { "No Profile Owner or Device Owner supervision app found for User $int1" })
+ logBuffer.log(
+ TAG,
+ ERROR,
+ { int1 = userId },
+ { "No Profile Owner or Device Owner supervision app found for User $int1" }
+ )
}
fun logPhoneStateChanged(newState: String?) {
- logBuffer.log(TAG, DEBUG,
- { str1 = newState },
- { "handlePhoneStateChanged($str1)" })
+ logBuffer.log(TAG, DEBUG, { str1 = newState }, { "handlePhoneStateChanged($str1)" })
}
fun logRegisterCallback(callback: KeyguardUpdateMonitorCallback?) {
- logBuffer.log(TAG, VERBOSE,
- { str1 = "$callback" },
- { "*** register callback for $str1" })
+ logBuffer.log(TAG, VERBOSE, { str1 = "$callback" }, { "*** register callback for $str1" })
}
fun logRetryingAfterFaceHwUnavailable(retryCount: Int) {
- logBuffer.log(TAG, WARNING,
- { int1 = retryCount },
- { "Retrying face after HW unavailable, attempt $int1" })
+ logBuffer.log(
+ TAG,
+ WARNING,
+ { int1 = retryCount },
+ { "Retrying face after HW unavailable, attempt $int1" }
+ )
}
fun logRetryAfterFpErrorWithDelay(msgId: Int, errString: String?, delay: Int) {
- logBuffer.log(TAG, DEBUG, {
- int1 = msgId
- int2 = delay
- str1 = "$errString"
- }, {
- "Fingerprint scheduling retry auth after $int2 ms due to($int1) -> $str1"
- })
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ int1 = msgId
+ int2 = delay
+ str1 = "$errString"
+ },
+ { "Fingerprint scheduling retry auth after $int2 ms due to($int1) -> $str1" }
+ )
}
fun logRetryAfterFpHwUnavailable(retryCount: Int) {
- logBuffer.log(TAG, WARNING,
- { int1 = retryCount },
- { "Retrying fingerprint attempt: $int1" })
+ logBuffer.log(
+ TAG,
+ WARNING,
+ { int1 = retryCount },
+ { "Retrying fingerprint attempt: $int1" }
+ )
}
fun logSendPrimaryBouncerChanged(
primaryBouncerIsOrWillBeShowing: Boolean,
primaryBouncerFullyShown: Boolean,
) {
- logBuffer.log(TAG, DEBUG, {
- bool1 = primaryBouncerIsOrWillBeShowing
- bool2 = primaryBouncerFullyShown
- }, {
- "sendPrimaryBouncerChanged primaryBouncerIsOrWillBeShowing=$bool1 " +
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ bool1 = primaryBouncerIsOrWillBeShowing
+ bool2 = primaryBouncerFullyShown
+ },
+ {
+ "sendPrimaryBouncerChanged primaryBouncerIsOrWillBeShowing=$bool1 " +
"primaryBouncerFullyShown=$bool2"
- })
+ }
+ )
}
fun logServiceStateChange(subId: Int, serviceState: ServiceState?) {
- logBuffer.log(TAG, DEBUG, {
- int1 = subId
- str1 = "$serviceState"
- }, { "handleServiceStateChange(subId=$int1, serviceState=$str1)" })
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ int1 = subId
+ str1 = "$serviceState"
+ },
+ { "handleServiceStateChange(subId=$int1, serviceState=$str1)" }
+ )
}
fun logServiceStateIntent(action: String?, serviceState: ServiceState?, subId: Int) {
- logBuffer.log(TAG, VERBOSE, {
- str1 = action
- str2 = "$serviceState"
- int1 = subId
- }, { "action $str1 serviceState=$str2 subId=$int1" })
+ logBuffer.log(
+ TAG,
+ VERBOSE,
+ {
+ str1 = action
+ str2 = "$serviceState"
+ int1 = subId
+ },
+ { "action $str1 serviceState=$str2 subId=$int1" }
+ )
}
fun logSimState(subId: Int, slotId: Int, state: Int) {
- logBuffer.log(TAG, DEBUG, {
- int1 = subId
- int2 = slotId
- long1 = state.toLong()
- }, { "handleSimStateChange(subId=$int1, slotId=$int2, state=$long1)" })
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ int1 = subId
+ int2 = slotId
+ long1 = state.toLong()
+ },
+ { "handleSimStateChange(subId=$int1, slotId=$int2, state=$long1)" }
+ )
}
fun logSimStateFromIntent(action: String?, extraSimState: String?, slotId: Int, subId: Int) {
- logBuffer.log(TAG, VERBOSE, {
- str1 = action
- str2 = extraSimState
- int1 = slotId
- int2 = subId
- }, { "action $str1 state: $str2 slotId: $int1 subid: $int2" })
+ logBuffer.log(
+ TAG,
+ VERBOSE,
+ {
+ str1 = action
+ str2 = extraSimState
+ int1 = slotId
+ int2 = subId
+ },
+ { "action $str1 state: $str2 slotId: $int1 subid: $int2" }
+ )
}
fun logSimUnlocked(subId: Int) {
@@ -297,78 +389,98 @@ class KeyguardUpdateMonitorLogger @Inject constructor(
}
fun logStartedListeningForFace(faceRunningState: Int, faceAuthUiEvent: FaceAuthUiEvent) {
- logBuffer.log(TAG, VERBOSE, {
- int1 = faceRunningState
- str1 = faceAuthUiEvent.reason
- str2 = faceAuthUiEvent.extraInfoToString()
- }, { "startListeningForFace(): $int1, reason: $str1 $str2" })
+ logBuffer.log(
+ TAG,
+ VERBOSE,
+ {
+ int1 = faceRunningState
+ str1 = faceAuthUiEvent.reason
+ str2 = faceAuthUiEvent.extraInfoToString()
+ },
+ { "startListeningForFace(): $int1, reason: $str1 $str2" }
+ )
}
fun logStartedListeningForFaceFromWakeUp(faceRunningState: Int, @WakeReason pmWakeReason: Int) {
- logBuffer.log(TAG, VERBOSE, {
- int1 = faceRunningState
- str1 = PowerManager.wakeReasonToString(pmWakeReason)
- }, { "startListeningForFace(): $int1, reason: wakeUp-$str1" })
+ logBuffer.log(
+ TAG,
+ VERBOSE,
+ {
+ int1 = faceRunningState
+ str1 = PowerManager.wakeReasonToString(pmWakeReason)
+ },
+ { "startListeningForFace(): $int1, reason: wakeUp-$str1" }
+ )
}
fun logStoppedListeningForFace(faceRunningState: Int, faceAuthReason: String) {
- logBuffer.log(TAG, VERBOSE, {
- int1 = faceRunningState
- str1 = faceAuthReason
- }, { "stopListeningForFace(): currentFaceRunningState: $int1, reason: $str1" })
+ logBuffer.log(
+ TAG,
+ VERBOSE,
+ {
+ int1 = faceRunningState
+ str1 = faceAuthReason
+ },
+ { "stopListeningForFace(): currentFaceRunningState: $int1, reason: $str1" }
+ )
}
fun logSubInfo(subInfo: SubscriptionInfo?) {
- logBuffer.log(TAG, VERBOSE,
- { str1 = "$subInfo" },
- { "SubInfo:$str1" })
+ logBuffer.log(TAG, VERBOSE, { str1 = "$subInfo" }, { "SubInfo:$str1" })
}
fun logTimeFormatChanged(newTimeFormat: String?) {
- logBuffer.log(TAG, DEBUG,
- { str1 = newTimeFormat },
- { "handleTimeFormatUpdate timeFormat=$str1" })
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ { str1 = newTimeFormat },
+ { "handleTimeFormatUpdate timeFormat=$str1" }
+ )
}
fun logUdfpsPointerDown(sensorId: Int) {
- logBuffer.log(TAG, DEBUG,
- { int1 = sensorId },
- { "onUdfpsPointerDown, sensorId: $int1" })
+ logBuffer.log(TAG, DEBUG, { int1 = sensorId }, { "onUdfpsPointerDown, sensorId: $int1" })
}
fun logUdfpsPointerUp(sensorId: Int) {
- logBuffer.log(TAG, DEBUG,
- { int1 = sensorId },
- { "onUdfpsPointerUp, sensorId: $int1" })
+ logBuffer.log(TAG, DEBUG, { int1 = sensorId }, { "onUdfpsPointerUp, sensorId: $int1" })
}
fun logUnexpectedFaceCancellationSignalState(faceRunningState: Int, unlockPossible: Boolean) {
- logBuffer.log(TAG, ERROR, {
- int1 = faceRunningState
- bool1 = unlockPossible
- }, {
- "Cancellation signal is not null, high chance of bug in " +
- "face auth lifecycle management. " +
- "Face state: $int1, unlockPossible: $bool1"
- })
+ logBuffer.log(
+ TAG,
+ ERROR,
+ {
+ int1 = faceRunningState
+ bool1 = unlockPossible
+ },
+ {
+ "Cancellation signal is not null, high chance of bug in " +
+ "face auth lifecycle management. " +
+ "Face state: $int1, unlockPossible: $bool1"
+ }
+ )
}
fun logUnexpectedFpCancellationSignalState(
fingerprintRunningState: Int,
unlockPossible: Boolean
) {
- logBuffer.log(TAG, ERROR, {
- int1 = fingerprintRunningState
- bool1 = unlockPossible
- }, {
- "Cancellation signal is not null, high chance of bug in " +
- "fp auth lifecycle management. FP state: $int1, unlockPossible: $bool1"
- })
+ logBuffer.log(
+ TAG,
+ ERROR,
+ {
+ int1 = fingerprintRunningState
+ bool1 = unlockPossible
+ },
+ {
+ "Cancellation signal is not null, high chance of bug in " +
+ "fp auth lifecycle management. FP state: $int1, unlockPossible: $bool1"
+ }
+ )
}
fun logUnregisterCallback(callback: KeyguardUpdateMonitorCallback?) {
- logBuffer.log(TAG, VERBOSE,
- { str1 = "$callback" },
- { "*** unregister callback for $str1" })
+ logBuffer.log(TAG, VERBOSE, { str1 = "$callback" }, { "*** unregister callback for $str1" })
}
fun logUserRequestedUnlock(
@@ -376,75 +488,149 @@ class KeyguardUpdateMonitorLogger @Inject constructor(
reason: String?,
dismissKeyguard: Boolean
) {
- logBuffer.log("ActiveUnlock", DEBUG, {
- str1 = requestOrigin?.name
- str2 = reason
- bool1 = dismissKeyguard
- }, { "reportUserRequestedUnlock origin=$str1 reason=$str2 dismissKeyguard=$bool1" })
+ logBuffer.log(
+ "ActiveUnlock",
+ DEBUG,
+ {
+ str1 = requestOrigin?.name
+ str2 = reason
+ bool1 = dismissKeyguard
+ },
+ { "reportUserRequestedUnlock origin=$str1 reason=$str2 dismissKeyguard=$bool1" }
+ )
}
fun logTrustGrantedWithFlags(
- flags: Int,
- newlyUnlocked: Boolean,
- userId: Int,
- message: String?
+ flags: Int,
+ newlyUnlocked: Boolean,
+ userId: Int,
+ message: String?
) {
- logBuffer.log(TAG, DEBUG, {
- int1 = flags
- bool1 = newlyUnlocked
- int2 = userId
- str1 = message
- }, { "trustGrantedWithFlags[user=$int2] newlyUnlocked=$bool1 " +
- "flags=${TrustGrantFlags(int1)} message=$str1" })
- }
-
- fun logTrustChanged(
- wasTrusted: Boolean,
- isNowTrusted: Boolean,
- userId: Int
- ) {
- logBuffer.log(TAG, DEBUG, {
- bool1 = wasTrusted
- bool2 = isNowTrusted
- int1 = userId
- }, { "onTrustChanged[user=$int1] wasTrusted=$bool1 isNowTrusted=$bool2" })
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ int1 = flags
+ bool1 = newlyUnlocked
+ int2 = userId
+ str1 = message
+ },
+ {
+ "trustGrantedWithFlags[user=$int2] newlyUnlocked=$bool1 " +
+ "flags=${TrustGrantFlags(int1)} message=$str1"
+ }
+ )
+ }
+
+ fun logTrustChanged(wasTrusted: Boolean, isNowTrusted: Boolean, userId: Int) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ bool1 = wasTrusted
+ bool2 = isNowTrusted
+ int1 = userId
+ },
+ { "onTrustChanged[user=$int1] wasTrusted=$bool1 isNowTrusted=$bool2" }
+ )
}
fun logKeyguardStateUpdate(
- secure: Boolean,
- canDismissLockScreen: Boolean,
- trusted: Boolean,
- trustManaged: Boolean
-
+ secure: Boolean,
+ canDismissLockScreen: Boolean,
+ trusted: Boolean,
+ trustManaged: Boolean
) {
- logBuffer.log("KeyguardState", DEBUG, {
- bool1 = secure
- bool2 = canDismissLockScreen
- bool3 = trusted
- bool4 = trustManaged
- }, { "#update secure=$bool1 canDismissKeyguard=$bool2" +
- " trusted=$bool3 trustManaged=$bool4" })
+ logBuffer.log(
+ "KeyguardState",
+ DEBUG,
+ {
+ bool1 = secure
+ bool2 = canDismissLockScreen
+ bool3 = trusted
+ bool4 = trustManaged
+ },
+ {
+ "#update secure=$bool1 canDismissKeyguard=$bool2" +
+ " trusted=$bool3 trustManaged=$bool4"
+ }
+ )
}
fun logSkipUpdateFaceListeningOnWakeup(@WakeReason pmWakeReason: Int) {
- logBuffer.log(TAG, VERBOSE, {
- str1 = PowerManager.wakeReasonToString(pmWakeReason)
- }, { "Skip updating face listening state on wakeup from $str1"})
+ logBuffer.log(
+ TAG,
+ VERBOSE,
+ { str1 = PowerManager.wakeReasonToString(pmWakeReason) },
+ { "Skip updating face listening state on wakeup from $str1" }
+ )
}
fun logTaskStackChangedForAssistant(assistantVisible: Boolean) {
- logBuffer.log(TAG, VERBOSE, {
- bool1 = assistantVisible
- }, {
- "TaskStackChanged for ACTIVITY_TYPE_ASSISTANT, assistant visible: $bool1"
- })
+ logBuffer.log(
+ TAG,
+ VERBOSE,
+ { bool1 = assistantVisible },
+ { "TaskStackChanged for ACTIVITY_TYPE_ASSISTANT, assistant visible: $bool1" }
+ )
}
fun logAssistantVisible(assistantVisible: Boolean) {
- logBuffer.log(TAG, VERBOSE, {
- bool1 = assistantVisible
- }, {
- "Updating mAssistantVisible to new value: $bool1"
- })
+ logBuffer.log(
+ TAG,
+ VERBOSE,
+ { bool1 = assistantVisible },
+ { "Updating mAssistantVisible to new value: $bool1" }
+ )
+ }
+
+ fun logFaceEnrolledUpdated(oldValue: Boolean, newValue: Boolean) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ bool1 = oldValue
+ bool2 = newValue
+ },
+ { "Face enrolled state changed: old: $bool1, new: $bool2" }
+ )
+ }
+
+ fun logFpEnrolledUpdated(userId: Int, oldValue: Boolean, newValue: Boolean) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ int1 = userId
+ bool1 = oldValue
+ bool2 = newValue
+ },
+ { "Fp enrolled state changed for userId: $int1 old: $bool1, new: $bool2" }
+ )
+ }
+
+ fun logTrustUsuallyManagedUpdated(
+ userId: Int,
+ oldValue: Boolean,
+ newValue: Boolean,
+ context: String
+ ) {
+ logBuffer.log(
+ TAG,
+ DEBUG,
+ {
+ int1 = userId
+ bool1 = oldValue
+ bool2 = newValue
+ str1 = context
+ },
+ {
+ "trustUsuallyManaged changed for " +
+ "userId: $int1 " +
+ "old: $bool1, " +
+ "new: $bool2 " +
+ "context: $context"
+ }
+ )
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/mediator/ScreenOnCoordinator.kt b/packages/SystemUI/src/com/android/keyguard/mediator/ScreenOnCoordinator.kt
index 0f00a040b094..603471b1de41 100644
--- a/packages/SystemUI/src/com/android/keyguard/mediator/ScreenOnCoordinator.kt
+++ b/packages/SystemUI/src/com/android/keyguard/mediator/ScreenOnCoordinator.kt
@@ -73,6 +73,10 @@ class ScreenOnCoordinator @Inject constructor(
@BinderThread
fun onScreenTurnedOn() {
foldAodAnimationController?.onScreenTurnedOn()
+ }
+
+ @BinderThread
+ fun onScreenTurnedOff() {
pendingTasks.reset()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
index 00f5ac2ffa23..12b5705190d9 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
@@ -58,13 +58,13 @@ import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.phone.StatusBarWindowCallback;
import com.android.systemui.util.Assert;
+import dagger.Lazy;
+
import java.util.Locale;
import java.util.Optional;
import javax.inject.Inject;
-import dagger.Lazy;
-
/**
* Class to register system actions with accessibility framework.
*/
@@ -473,7 +473,7 @@ public class SystemActions implements CoreStartable {
KeyEvent event = KeyEvent.obtain(downTime, time, action, keyCode, 0, 0,
KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM,
InputDevice.SOURCE_KEYBOARD, null);
- InputManager.getInstance()
+ mContext.getSystemService(InputManager.class)
.injectInputEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
event.recycle();
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
index b111e1f72f1d..d35c77c3b231 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
@@ -1468,7 +1468,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
super.onInitializeAccessibilityNodeInfo(host, info);
final AccessibilityAction clickAction = new AccessibilityAction(
AccessibilityAction.ACTION_CLICK.getId(), mContext.getResources().getString(
- R.string.magnification_mode_switch_click_label));
+ R.string.magnification_open_settings_click_label));
info.addAction(clickAction);
info.setClickable(true);
info.addAction(
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
index 15264e64a241..e1f3c6cc5c3b 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
@@ -215,9 +215,7 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest
private boolean performA11yAction(View view, int action) {
final Rect windowBounds = mWindowManager.getCurrentWindowMetrics().getBounds();
- if (action == AccessibilityAction.ACTION_CLICK.getId()) {
- handleSingleTap(view);
- } else if (action == R.id.accessibility_action_move_up) {
+ if (action == R.id.accessibility_action_move_up) {
moveButton(0, -windowBounds.height());
} else if (action == R.id.accessibility_action_move_down) {
moveButton(0, windowBounds.height());
@@ -264,8 +262,6 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest
} else if (id == R.id.magnifier_full_button) {
hideSettingPanel();
toggleMagnificationMode();
- } else {
- hideSettingPanel();
}
}
};
@@ -273,7 +269,6 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest
@Override
public boolean onSingleTap(View view) {
mSingleTapDetected = true;
- handleSingleTap(view);
return true;
}
@@ -358,6 +353,10 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest
}
mWindowManager.addView(mSettingView, mParams);
+ if (resetPosition) {
+ // Request focus on the settings panel when position of the panel is reset.
+ mSettingView.requestFocus();
+ }
// Exclude magnification switch button from system gesture area.
setSystemGestureExclusion();
@@ -385,8 +384,8 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest
mSettingView = (LinearLayout) View.inflate(mContext,
R.layout.window_magnification_settings_view, null);
- mSettingView.setClickable(true);
mSettingView.setFocusable(true);
+ mSettingView.setFocusableInTouchMode(true);
mSettingView.setOnTouchListener(this::onTouch);
mPanelView = mSettingView.findViewById(R.id.magnifier_panel_view);
@@ -499,22 +498,6 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest
}
}
- private void handleSingleTap(View view) {
- int id = view.getId();
- if (id == R.id.magnifier_small_button) {
- setMagnifierSize(MagnificationSize.SMALL);
- } else if (id == R.id.magnifier_medium_button) {
- setMagnifierSize(MagnificationSize.MEDIUM);
- } else if (id == R.id.magnifier_large_button) {
- setMagnifierSize(MagnificationSize.LARGE);
- } else if (id == R.id.magnifier_full_button) {
- hideSettingPanel();
- toggleMagnificationMode();
- } else {
- hideSettingPanel();
- }
- }
-
public void editMagnifierSizeMode(boolean enable) {
setEditMagnifierSizeMode(enable);
updateSelectedButton(MagnificationSize.NONE);
@@ -551,7 +534,7 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT,
LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY,
- LayoutParams.FLAG_NOT_FOCUSABLE,
+ /* _flags= */ 0,
PixelFormat.TRANSPARENT);
params.gravity = Gravity.TOP | Gravity.START;
params.accessibilityTitle = getAccessibilityWindowTitle(context);
diff --git a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
index 03d999f697d0..0002ae95f476 100644
--- a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
@@ -24,6 +24,7 @@ import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.animation.LayoutTransition;
import android.animation.ObjectAnimator;
import android.annotation.IntDef;
+import android.annotation.IntRange;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -37,7 +38,6 @@ import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
-import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -195,7 +195,13 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
return false;
}
- void onBatteryLevelChanged(int level, boolean pluggedIn) {
+ /**
+ * Update battery level
+ *
+ * @param level int between 0 and 100 (representing percentage value)
+ * @param pluggedIn whether the device is plugged in or not
+ */
+ public void onBatteryLevelChanged(@IntRange(from = 0, to = 100) int level, boolean pluggedIn) {
mDrawable.setCharging(pluggedIn);
mDrawable.setBatteryLevel(level);
mCharging = pluggedIn;
@@ -340,10 +346,9 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
}
if (mTextColor != 0) mBatteryPercentView.setTextColor(mTextColor);
updatePercentText();
- addView(mBatteryPercentView,
- new ViewGroup.LayoutParams(
- LayoutParams.WRAP_CONTENT,
- LayoutParams.MATCH_PARENT));
+ addView(mBatteryPercentView, new LayoutParams(
+ LayoutParams.WRAP_CONTENT,
+ LayoutParams.MATCH_PARENT));
}
} else {
if (showing) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
index 3ea3cd171062..52312b8e8add 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
@@ -97,7 +97,6 @@ open class AuthBiometricFingerprintIconController(
val iconContentDescription = getIconContentDescription(newState)
if (iconContentDescription != null) {
iconView.contentDescription = iconContentDescription
- iconViewOverlay.contentDescription = iconContentDescription
}
iconView.frame = 0
@@ -152,7 +151,7 @@ open class AuthBiometricFingerprintIconController(
STATE_AUTHENTICATING_ANIMATING_IN,
STATE_AUTHENTICATING,
STATE_PENDING_CONFIRMATION,
- STATE_AUTHENTICATED -> R.string.accessibility_fingerprint_dialog_fingerprint_icon
+ STATE_AUTHENTICATED -> R.string.security_settings_sfps_enroll_find_sensor_message
STATE_ERROR,
STATE_HELP -> R.string.biometric_dialog_try_again
else -> null
@@ -231,21 +230,29 @@ open class AuthBiometricFingerprintIconController(
if (isReverseDefaultRotation) (rotation + 1) % 4 else rotation
@RawRes
- private fun getSideFpsAnimationForTransition(rotation: Int): Int = when (rotation) {
- Surface.ROTATION_90 -> if (isDeviceFolded) {
- R.raw.biometricprompt_folded_base_topleft
- } else {
- R.raw.biometricprompt_portrait_base_topleft
- }
- Surface.ROTATION_270 -> if (isDeviceFolded) {
- R.raw.biometricprompt_folded_base_bottomright
- } else {
- R.raw.biometricprompt_portrait_base_bottomright
- }
- else -> if (isDeviceFolded) {
- R.raw.biometricprompt_folded_base_default
- } else {
- R.raw.biometricprompt_landscape_base
+ private fun getSideFpsAnimationForTransition(rotation: Int): Int {
+ when (rotation) {
+ Surface.ROTATION_90 -> if (context.isInRearDisplayMode()) {
+ return R.raw.biometricprompt_rear_portrait_reverse_base
+ } else if (isDeviceFolded) {
+ return R.raw.biometricprompt_folded_base_topleft
+ } else {
+ return R.raw.biometricprompt_portrait_base_topleft
+ }
+ Surface.ROTATION_270 -> if (context.isInRearDisplayMode()) {
+ return R.raw.biometricprompt_rear_portrait_base
+ } else if (isDeviceFolded) {
+ return R.raw.biometricprompt_folded_base_bottomright
+ } else {
+ return R.raw.biometricprompt_portrait_base_bottomright
+ }
+ else -> if (context.isInRearDisplayMode()) {
+ return R.raw.biometricprompt_rear_landscape_base
+ } else if (isDeviceFolded) {
+ return R.raw.biometricprompt_folded_base_default
+ } else {
+ return R.raw.biometricprompt_landscape_base
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
index e12c1706798e..a7b6e6ae6d40 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
@@ -658,6 +658,7 @@ public abstract class AuthBiometricView extends LinearLayout {
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mIconController.onConfigurationChanged(newConfig);
+ updateState(mSavedState.getInt(AuthDialog.KEY_BIOMETRIC_STATE));
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index e698faffd3f6..08efd89029ed 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -85,6 +85,8 @@ import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.concurrency.Execution;
+import kotlin.Unit;
+
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
@@ -98,8 +100,6 @@ import java.util.Set;
import javax.inject.Inject;
import javax.inject.Provider;
-import kotlin.Unit;
-
/**
* Receives messages sent from {@link com.android.server.biometrics.BiometricService} and shows the
* appropriate biometric UI (e.g. BiometricDialogView).
@@ -872,7 +872,8 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
}
/**
- * Stores the callback received from {@link com.android.server.display.DisplayModeDirector}.
+ * Stores the callback received from
+ * {@link com.android.server.display.mode.DisplayModeDirector}.
*
* DisplayModeDirector implements {@link IUdfpsRefreshRateRequestCallback}
* and registers it with this class by calling
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/FaceHelpMessageDeferral.kt b/packages/SystemUI/src/com/android/systemui/biometrics/FaceHelpMessageDeferral.kt
index fabc1c1bb908..e16121d1104e 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/FaceHelpMessageDeferral.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/FaceHelpMessageDeferral.kt
@@ -49,8 +49,8 @@ constructor(
/**
* @property messagesToDefer messages that shouldn't show immediately when received, but may be
- * shown later if the message is the most frequent acquiredInfo processed and meets [threshold]
- * percentage of all passed acquired frames.
+ * shown later if the message is the most frequent acquiredInfo processed and meets [threshold]
+ * percentage of all passed acquired frames.
*/
open class BiometricMessageDeferral(
private val messagesToDefer: Set<Int>,
@@ -127,8 +127,9 @@ open class BiometricMessageDeferral(
/**
* Get the most frequent deferred message that meets the [threshold] percentage of processed
* frames.
+ *
* @return null if no acquiredInfo have been deferred OR deferred messages didn't meet the
- * [threshold] percentage.
+ * [threshold] percentage.
*/
fun getDeferredMessage(): CharSequence? {
mostFrequentAcquiredInfoToDefer?.let {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
index 6c490780b79a..f7d87fc69e55 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
@@ -172,12 +172,16 @@ constructor(
override fun show(
sensorId: Int,
@BiometricOverlayConstants.ShowReason reason: Int
- ) =
- if (reason.isReasonToAutoShow(activityTaskManager)) {
+ ) {
+ if (
+ reason.isReasonToAutoShow(activityTaskManager) &&
+ !context.isInRearDisplayMode()
+ ) {
show(SideFpsUiRequestSource.AUTO_SHOW, reason)
} else {
hide(SideFpsUiRequestSource.AUTO_SHOW)
}
+ }
override fun hide(sensorId: Int) = hide(SideFpsUiRequestSource.AUTO_SHOW)
}
@@ -488,7 +492,9 @@ class OrientationReasonListener(
displayManager,
handler,
BiometricDisplayListener.SensorType.SideFingerprint(sensorProps)
- ) { onOrientationChanged(reason) }
+ ) {
+ onOrientationChanged(reason)
+ }
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt
index 2d0d52e067ab..231e7a429c53 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt
@@ -348,6 +348,7 @@ constructor(
/**
* Overrides non-bouncer show logic in shouldPauseAuth to still show icon.
+ *
* @return whether the udfpsBouncer has been newly shown or hidden
*/
private fun showUdfpsBouncer(show: Boolean): Boolean {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt b/packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt
index d0d6f4cbf166..3d563267ca74 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt
@@ -36,6 +36,7 @@ import android.view.WindowManager
import android.view.accessibility.AccessibilityEvent
import android.view.accessibility.AccessibilityManager
import com.android.internal.widget.LockPatternUtils
+import com.android.systemui.R
import java.lang.annotation.Retention
import java.lang.annotation.RetentionPolicy
@@ -117,4 +118,7 @@ object Utils {
@Retention(RetentionPolicy.SOURCE)
@IntDef(CREDENTIAL_PIN, CREDENTIAL_PATTERN, CREDENTIAL_PASSWORD)
internal annotation class CredentialType
-} \ No newline at end of file
+}
+
+fun Context.isInRearDisplayMode(): Boolean = resources.getIntArray(
+ com.android.internal.R.array.config_rearDisplayDeviceStates).isNotEmpty() \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/udfps/NormalizedTouchData.kt b/packages/SystemUI/src/com/android/systemui/biometrics/udfps/NormalizedTouchData.kt
index 28bc2b727a27..6854b50370ba 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/udfps/NormalizedTouchData.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/udfps/NormalizedTouchData.kt
@@ -76,5 +76,6 @@ data class NormalizedTouchData(
| time: $time
| gestureStart: $gestureStart
|}
- """.trimMargin()
+ """
+ .trimMargin()
}
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialog.java b/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialog.java
index 8e062bd69d63..653c12ef955e 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialog.java
@@ -46,11 +46,11 @@ public class BroadcastDialog extends SystemUIDialog {
@VisibleForTesting
protected View mDialogView;
private MediaOutputDialogFactory mMediaOutputDialogFactory;
- private String mSwitchBroadcastApp;
+ private String mCurrentBroadcastApp;
private String mOutputPackageName;
public BroadcastDialog(Context context, MediaOutputDialogFactory mediaOutputDialogFactory,
- String switchBroadcastApp, String outputPkgName, UiEventLogger uiEventLogger) {
+ String currentBroadcastApp, String outputPkgName, UiEventLogger uiEventLogger) {
super(context);
if (DEBUG) {
Log.d(TAG, "Init BroadcastDialog");
@@ -58,7 +58,7 @@ public class BroadcastDialog extends SystemUIDialog {
mContext = getContext();
mMediaOutputDialogFactory = mediaOutputDialogFactory;
- mSwitchBroadcastApp = switchBroadcastApp;
+ mCurrentBroadcastApp = currentBroadcastApp;
mOutputPackageName = outputPkgName;
mUiEventLogger = uiEventLogger;
}
@@ -77,20 +77,18 @@ public class BroadcastDialog extends SystemUIDialog {
TextView title = mDialogView.requireViewById(R.id.dialog_title);
TextView subTitle = mDialogView.requireViewById(R.id.dialog_subtitle);
- title.setText(
- mContext.getString(R.string.bt_le_audio_broadcast_dialog_title,
- MediaDataUtils.getAppLabel(mContext, mOutputPackageName,
- mContext.getString(
- R.string.bt_le_audio_broadcast_dialog_unknown_name))));
- subTitle.setText(
- mContext.getString(R.string.bt_le_audio_broadcast_dialog_sub_title,
- mSwitchBroadcastApp));
+ title.setText(mContext.getString(
+ R.string.bt_le_audio_broadcast_dialog_title, mCurrentBroadcastApp));
+ String switchBroadcastApp = MediaDataUtils.getAppLabel(mContext, mOutputPackageName,
+ mContext.getString(R.string.bt_le_audio_broadcast_dialog_unknown_name));
+ subTitle.setText(mContext.getString(
+ R.string.bt_le_audio_broadcast_dialog_sub_title, switchBroadcastApp));
Button switchBroadcast = mDialogView.requireViewById(R.id.switch_broadcast);
Button changeOutput = mDialogView.requireViewById(R.id.change_output);
Button cancelBtn = mDialogView.requireViewById(R.id.cancel);
switchBroadcast.setText(mContext.getString(
- R.string.bt_le_audio_broadcast_dialog_switch_app, mSwitchBroadcastApp), null);
+ R.string.bt_le_audio_broadcast_dialog_switch_app, switchBroadcastApp));
changeOutput.setOnClickListener((view) -> {
mMediaOutputDialogFactory.create(mOutputPackageName, true, null);
dismiss();
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogController.java b/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogController.java
index 8a54345ae28c..1b699e8ea5dd 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogController.java
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogController.java
@@ -47,10 +47,15 @@ public class BroadcastDialogController {
mMediaOutputDialogFactory = mediaOutputDialogFactory;
}
- public void createBroadcastDialog(String switchAppName, String outputPkgName,
+ /** Creates a [BroadcastDialog] for the user to switch broadcast or change the output device
+ *
+ * @param currentBroadcastAppName Indicates the APP name currently broadcasting
+ * @param outputPkgName Indicates the output media package name to be switched
+ */
+ public void createBroadcastDialog(String currentBroadcastAppName, String outputPkgName,
boolean aboveStatusBar, View view) {
BroadcastDialog broadcastDialog = new BroadcastDialog(mContext, mMediaOutputDialogFactory,
- switchAppName, outputPkgName, mUiEventLogger);
+ currentBroadcastAppName, outputPkgName, mUiEventLogger);
if (view != null) {
mDialogLaunchAnimator.showFromView(broadcastDialog, view);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
index cef415c8a490..98a3e4b55256 100644
--- a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
@@ -130,7 +130,8 @@ final class WirelessChargingLayout extends FrameLayout {
animatorSet.playTogether(textSizeAnimator, textOpacityAnimator, textFadeAnimator);
// For tablet docking animation, we don't play the background scrim.
- if (!Utilities.isTablet(context)) {
+ // TODO(b/270524780): use utility to check for tablet instead.
+ if (!Utilities.isLargeScreen(context)) {
ValueAnimator scrimFadeInAnimator = ObjectAnimator.ofArgb(this,
"backgroundColor", Color.TRANSPARENT, SCRIM_COLOR);
scrimFadeInAnimator.setDuration(SCRIM_FADE_DURATION);
diff --git a/packages/SystemUI/src/com/android/systemui/common/coroutine/ChannelExt.kt b/packages/SystemUI/src/com/android/systemui/common/coroutine/ChannelExt.kt
index a0b19dc5c96e..c0e1717ea014 100644
--- a/packages/SystemUI/src/com/android/systemui/common/coroutine/ChannelExt.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/coroutine/ChannelExt.kt
@@ -26,7 +26,6 @@ object ChannelExt {
/**
* Convenience wrapper around [SendChannel.trySend] that also logs on failure. This is the
* equivalent of calling:
- *
* ```
* sendChannel.trySend(element).onFailure {
* Log.e(
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsView.java b/packages/SystemUI/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsView.java
index a2077a3ae96a..24f6296de122 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsView.java
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsView.java
@@ -108,7 +108,7 @@ public class SeekBarWithIconButtonsView extends LinearLayout {
mSeekbar.setOnSeekBarChangeListener(mSeekBarListener);
- mIconStart.setOnClickListener((view) -> {
+ mIconStartFrame.setOnClickListener((view) -> {
final int progress = mSeekbar.getProgress();
if (progress > 0) {
mSeekbar.setProgress(progress - 1);
@@ -116,7 +116,7 @@ public class SeekBarWithIconButtonsView extends LinearLayout {
}
});
- mIconEnd.setOnClickListener((view) -> {
+ mIconEndFrame.setOnClickListener((view) -> {
final int progress = mSeekbar.getProgress();
if (progress < mSeekbar.getMax()) {
mSeekbar.setProgress(progress + 1);
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt
index b3c18fb3cd98..3744344421a9 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt
@@ -86,6 +86,7 @@ internal constructor(wrapper: ControlsFavoritePersistenceWrapper) {
*
* When the favorites for that application are returned, they will be removed from the auxiliary
* file immediately, so they won't be retrieved again.
+ *
* @param componentName the name of the service that provided the controls
* @return a list of structures with favorites
*/
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
index 822190f21da1..3555d0a7e7fb 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
@@ -166,6 +166,19 @@ interface ControlsController : UserAwareController {
)
/**
+ * Removes favorites for a given component
+ * @param componentName the name of the service that provides the [Control]
+ * @return true when favorites is scheduled for deletion
+ */
+ fun removeFavorites(componentName: ComponentName): Boolean
+
+ /**
+ * Checks if the favorites can be removed. You can't remove components from the preferred list.
+ * @param componentName the name of the service that provides the [Control]
+ */
+ fun canRemoveFavorites(componentName: ComponentName): Boolean
+
+ /**
* Replaces the favorites for the given structure.
*
* Calling this method will eliminate the previous selection of favorites and replace it with a
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
index 700f4f62029f..a171f43013e0 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
@@ -499,6 +499,21 @@ class ControlsControllerImpl @Inject constructor (
}
}
+ override fun canRemoveFavorites(componentName: ComponentName): Boolean =
+ !authorizedPanelsRepository.getPreferredPackages().contains(componentName.packageName)
+
+ override fun removeFavorites(componentName: ComponentName): Boolean {
+ if (!confirmAvailability()) return false
+ if (!canRemoveFavorites(componentName)) return false
+
+ executor.execute {
+ Favorites.removeStructures(componentName)
+ authorizedPanelsRepository.removeAuthorizedPanels(setOf(componentName.packageName))
+ persistenceWrapper.storeFavorites(Favorites.getAllStructures())
+ }
+ return true
+ }
+
override fun replaceFavoritesForStructure(structureInfo: StructureInfo) {
if (!confirmAvailability()) return
executor.execute {
@@ -657,10 +672,11 @@ private object Favorites {
return true
}
- fun removeStructures(componentName: ComponentName) {
+ fun removeStructures(componentName: ComponentName): Boolean {
val newFavMap = favMap.toMutableMap()
- newFavMap.remove(componentName)
+ val removed = newFavMap.remove(componentName) != null
favMap = newFavMap
+ return removed
}
fun addFavorite(
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
index 72c3a943c30b..217f4d89e24c 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
@@ -84,7 +84,7 @@ class ControlsProviderLifecycleManager(
private val BIND_FLAGS_PANEL = Context.BIND_AUTO_CREATE or Context.BIND_NOT_PERCEPTIBLE
}
- private val intent = Intent().apply {
+ private val intent = Intent(ControlsProviderService.SERVICE_CONTROLS).apply {
component = componentName
putExtra(CALLBACK_BUNDLE, Bundle().apply {
putBinder(CALLBACK_TOKEN, token)
diff --git a/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepository.kt b/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepository.kt
index 3e672f391e81..ae9c37aa0e7b 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepository.kt
@@ -26,6 +26,14 @@ interface AuthorizedPanelsRepository {
/** A set of package names that the user has previously authorized to show panels. */
fun getAuthorizedPanels(): Set<String>
+ /** Preferred applications to query controls suggestions from */
+ fun getPreferredPackages(): Set<String>
+
/** Adds [packageNames] to the set of packages that the user has authorized to show panels. */
fun addAuthorizedPanels(packageNames: Set<String>)
+
+ /**
+ * Removes [packageNames] from the set of packages that the user has authorized to show panels.
+ */
+ fun removeAuthorizedPanels(packageNames: Set<String>)
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImpl.kt
index f7e43a77b573..e51e8326c0a5 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImpl.kt
@@ -37,10 +37,20 @@ constructor(
return getAuthorizedPanelsInternal(instantiateSharedPrefs())
}
+ override fun getPreferredPackages(): Set<String> =
+ context.resources.getStringArray(R.array.config_controlsPreferredPackages).toSet()
+
override fun addAuthorizedPanels(packageNames: Set<String>) {
addAuthorizedPanelsInternal(instantiateSharedPrefs(), packageNames)
}
+ override fun removeAuthorizedPanels(packageNames: Set<String>) {
+ with(instantiateSharedPrefs()) {
+ val currentSet = getAuthorizedPanelsInternal(this)
+ edit().putStringSet(KEY, currentSet - packageNames).apply()
+ }
+ }
+
private fun getAuthorizedPanelsInternal(sharedPreferences: SharedPreferences): Set<String> {
return sharedPreferences.getStringSet(KEY, emptySet())!!
}
@@ -63,15 +73,7 @@ constructor(
// If we've never run this (i.e., the key doesn't exist), add the default packages
if (sharedPref.getStringSet(KEY, null) == null) {
- sharedPref
- .edit()
- .putStringSet(
- KEY,
- context.resources
- .getStringArray(R.array.config_controlsPreferredPackages)
- .toSet()
- )
- .apply()
+ sharedPref.edit().putStringSet(KEY, getPreferredPackages()).apply()
}
return sharedPref
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsDialogManager.kt b/packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsDialogManager.kt
index bb2e2d701aa0..06d4a0888197 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsDialogManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsDialogManager.kt
@@ -38,7 +38,6 @@ import javax.inject.Inject
/**
* Manager to display a dialog to prompt user to enable controls related Settings:
- *
* * [Settings.Secure.LOCKSCREEN_SHOW_CONTROLS]
* * [Settings.Secure.LOCKSCREEN_ALLOW_TRIVIAL_CONTROLS]
*/
@@ -46,20 +45,19 @@ interface ControlsSettingsDialogManager {
/**
* Shows the corresponding dialog. In order for a dialog to appear, the following must be true
- *
* * At least one of the Settings in [ControlsSettingsRepository] are `false`.
* * The dialog has not been seen by the user too many times (as defined by
- * [MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG]).
+ * [MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG]).
*
* When the dialogs are shown, the following outcomes are possible:
* * User cancels the dialog by clicking outside or going back: we register that the dialog was
- * seen but the settings don't change.
+ * seen but the settings don't change.
* * User responds negatively to the dialog: we register that the user doesn't want to change
- * the settings (dialog will not appear again) and the settings don't change.
+ * the settings (dialog will not appear again) and the settings don't change.
* * User responds positively to the dialog: the settings are set to `true` and the dialog will
- * not appear again.
+ * not appear again.
* * SystemUI closes the dialogs (for example, the activity showing it is closed). In this case,
- * we don't modify anything.
+ * we don't modify anything.
*
* Of those four scenarios, only the first three will cause [onAttemptCompleted] to be called.
* It will also be called if the dialogs are not shown.
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
index 3a3f9b4e5265..bf0a69296dfd 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
@@ -68,7 +68,7 @@ class ControlsActivity @Inject constructor(
getLifecycle().addObserver(
ControlsAnimations.observerForAnimations(
- requireViewById<ViewGroup>(R.id.control_detail_root),
+ requireViewById(R.id.control_detail_root),
window,
intent,
!featureFlags.isEnabled(Flags.USE_APP_PANELS)
@@ -95,7 +95,7 @@ class ControlsActivity @Inject constructor(
override fun onStart() {
super.onStart()
- parent = requireViewById<ViewGroup>(R.id.global_actions_controls)
+ parent = requireViewById(R.id.control_detail_root)
parent.alpha = 0f
if (featureFlags.isEnabled(Flags.USE_APP_PANELS) && !keyguardStateController.isUnlocked) {
controlsSettingsDialogManager.maybeShowDialog(this) {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsDialogsFactory.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsDialogsFactory.kt
new file mode 100644
index 000000000000..d6cfb79101d7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsDialogsFactory.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2023 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.app.Dialog
+import android.content.Context
+import android.content.DialogInterface
+import com.android.systemui.R
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import java.util.function.Consumer
+import javax.inject.Inject
+
+class ControlsDialogsFactory(private val internalDialogFactory: (Context) -> SystemUIDialog) {
+
+ @Inject constructor() : this({ SystemUIDialog(it) })
+
+ fun createRemoveAppDialog(
+ context: Context,
+ appName: CharSequence,
+ response: Consumer<Boolean>
+ ): Dialog {
+ val listener =
+ DialogInterface.OnClickListener { _, which ->
+ response.accept(which == DialogInterface.BUTTON_POSITIVE)
+ }
+ return internalDialogFactory(context).apply {
+ setTitle(context.getString(R.string.controls_panel_remove_app_authorization, appName))
+ setCanceledOnTouchOutside(true)
+ setOnCancelListener { response.accept(false) }
+ setPositiveButton(R.string.controls_dialog_remove, listener)
+ setNeutralButton(R.string.cancel, listener)
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
index 9405c602caf7..c61dad6fc075 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
@@ -21,6 +21,7 @@ import android.animation.AnimatorListenerAdapter
import android.animation.ObjectAnimator
import android.app.Activity
import android.app.ActivityOptions
+import android.app.Dialog
import android.app.PendingIntent
import android.content.ComponentName
import android.content.Context
@@ -52,7 +53,6 @@ import com.android.systemui.Dumpable
import com.android.systemui.R
import com.android.systemui.controls.ControlsMetricsLogger
import com.android.systemui.controls.ControlsServiceInfo
-import com.android.systemui.controls.settings.ControlsSettingsRepository
import com.android.systemui.controls.CustomIconCache
import com.android.systemui.controls.controller.ControlsController
import com.android.systemui.controls.controller.StructureInfo
@@ -64,6 +64,7 @@ import com.android.systemui.controls.management.ControlsFavoritingActivity
import com.android.systemui.controls.management.ControlsListingController
import com.android.systemui.controls.management.ControlsProviderSelectorActivity
import com.android.systemui.controls.panels.AuthorizedPanelsRepository
+import com.android.systemui.controls.settings.ControlsSettingsRepository
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
@@ -83,7 +84,7 @@ import com.android.wm.shell.TaskViewFactory
import dagger.Lazy
import java.io.PrintWriter
import java.text.Collator
-import java.util.Optional
+import java.util.*
import java.util.function.Consumer
import javax.inject.Inject
@@ -108,6 +109,7 @@ class ControlsUiControllerImpl @Inject constructor (
private val controlsSettingsRepository: ControlsSettingsRepository,
private val authorizedPanelsRepository: AuthorizedPanelsRepository,
private val featureFlags: FeatureFlags,
+ private val dialogsFactory: ControlsDialogsFactory,
dumpManager: DumpManager
) : ControlsUiController, Dumpable {
@@ -122,6 +124,7 @@ class ControlsUiControllerImpl @Inject constructor (
private const val ADD_CONTROLS_ID = 1L
private const val ADD_APP_ID = 2L
private const val EDIT_CONTROLS_ID = 3L
+ private const val REMOVE_APP_ID = 4L
}
private var selectedItem: SelectedItem = SelectedItem.EMPTY_SELECTION
@@ -151,6 +154,7 @@ class ControlsUiControllerImpl @Inject constructor (
private var openAppIntent: Intent? = null
private var overflowMenuAdapter: BaseAdapter? = null
+ private var removeAppDialog: Dialog? = null
private val onSeedingComplete = Consumer<Boolean> {
accepted ->
@@ -330,6 +334,31 @@ class ControlsUiControllerImpl @Inject constructor (
}
}
+ @VisibleForTesting
+ internal fun startRemovingApp(componentName: ComponentName, appName: CharSequence) {
+ removeAppDialog?.cancel()
+ removeAppDialog = dialogsFactory.createRemoveAppDialog(context, appName) {
+ if (!controlsController.get().removeFavorites(componentName)) {
+ return@createRemoveAppDialog
+ }
+ if (
+ sharedPreferences.getString(PREF_COMPONENT, "") ==
+ componentName.flattenToString()
+ ) {
+ sharedPreferences
+ .edit()
+ .remove(PREF_COMPONENT)
+ .remove(PREF_STRUCTURE_OR_APP_NAME)
+ .remove(PREF_IS_PANEL)
+ .commit()
+ }
+
+ allStructures = controlsController.get().getFavorites()
+ selectedItem = getPreferredSelectedItem(allStructures)
+ reload(parent)
+ }.apply { show() }
+ }
+
private fun startTargetedActivity(si: StructureInfo, klazz: Class<*>) {
val i = Intent(activityContext, klazz)
putIntentExtras(i, si)
@@ -433,7 +462,10 @@ class ControlsUiControllerImpl @Inject constructor (
val currentApps = panelsAndStructures.map { it.componentName }.toSet()
val allApps = controlsListingController.get()
.getCurrentServices().map { it.componentName }.toSet()
- createMenu(extraApps = (allApps - currentApps).isNotEmpty())
+ createMenu(
+ selectionItem = selectionItem,
+ extraApps = (allApps - currentApps).isNotEmpty(),
+ )
}
private fun createPanelView(componentName: ComponentName) {
@@ -472,7 +504,7 @@ class ControlsUiControllerImpl @Inject constructor (
}
}
- private fun createMenu(extraApps: Boolean) {
+ private fun createMenu(selectionItem: SelectionItem, extraApps: Boolean) {
val isPanel = selectedItem is SelectedItem.PanelItem
val selectedStructure = (selectedItem as? SelectedItem.StructureItem)?.structure
?: EMPTY_STRUCTURE
@@ -490,6 +522,13 @@ class ControlsUiControllerImpl @Inject constructor (
ADD_APP_ID
))
}
+ if (featureFlags.isEnabled(Flags.APP_PANELS_REMOVE_APPS_ALLOWED) &&
+ controlsController.get().canRemoveFavorites(selectedItem.componentName)) {
+ add(OverflowMenuAdapter.MenuItem(
+ context.getText(R.string.controls_menu_remove),
+ REMOVE_APP_ID,
+ ))
+ }
} else {
add(OverflowMenuAdapter.MenuItem(
context.getText(R.string.controls_menu_add),
@@ -529,6 +568,9 @@ class ControlsUiControllerImpl @Inject constructor (
ADD_APP_ID -> startProviderSelectorActivity()
ADD_CONTROLS_ID -> startFavoritingActivity(selectedStructure)
EDIT_CONTROLS_ID -> startEditingActivity(selectedStructure)
+ REMOVE_APP_ID -> startRemovingApp(
+ selectedStructure.componentName, selectionItem.appName
+ )
}
dismiss()
}
@@ -546,8 +588,12 @@ class ControlsUiControllerImpl @Inject constructor (
RenderInfo.registerComponentIcon(it.componentName, it.icon)
}
- var adapter = ItemAdapter(context, R.layout.controls_spinner_item).apply {
- addAll(items)
+ val adapter = ItemAdapter(context, R.layout.controls_spinner_item).apply {
+ add(selected)
+ addAll(items
+ .filter { it !== selected }
+ .sortedBy { it.appName.toString() }
+ )
}
val iconSize = context.resources
@@ -728,6 +774,7 @@ class ControlsUiControllerImpl @Inject constructor (
it.value.dismiss()
}
controlActionCoordinator.closeDialogs()
+ removeAppDialog?.cancel()
}
override fun hide(parent: ViewGroup) {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt
index 3b6ab20e39d4..78e87cafc4f2 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt
@@ -71,7 +71,7 @@ class PanelTaskViewController(
taskView.post {
val roundedCorner =
activityContext.resources.getDimensionPixelSize(
- R.dimen.notification_corner_radius
+ R.dimen.controls_panel_corner_radius
)
val radii = FloatArray(8) { roundedCorner.toFloat() }
taskView.background =
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
index 19b000b87b39..d5a41460c89e 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
@@ -54,6 +54,7 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.dagger.StartCentralSurfacesModule;
+import com.android.systemui.statusbar.events.StatusBarEventsModule;
import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider;
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.phone.DozeServiceHost;
@@ -104,6 +105,7 @@ import dagger.Provides;
QSModule.class,
ReferenceScreenshotModule.class,
RotationLockModule.class,
+ StatusBarEventsModule.class,
StartCentralSurfacesModule.class,
VolumeModule.class,
KeyboardShortcutsModule.class
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
index 9921b1fcd4bc..b86d419f540f 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
@@ -47,10 +47,7 @@ import com.android.systemui.reardisplay.RearDisplayDialogController
import com.android.systemui.recents.Recents
import com.android.systemui.settings.dagger.MultiUserUtilsModule
import com.android.systemui.shortcut.ShortcutKeyDispatcher
-import com.android.systemui.statusbar.notification.fsi.FsiChromeRepo
import com.android.systemui.statusbar.notification.InstantAppNotifier
-import com.android.systemui.statusbar.notification.fsi.FsiChromeViewModelFactory
-import com.android.systemui.statusbar.notification.fsi.FsiChromeViewBinder
import com.android.systemui.statusbar.phone.KeyguardLiftController
import com.android.systemui.stylus.StylusUsiPowerStartable
import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator
@@ -91,24 +88,6 @@ abstract class SystemUICoreStartableModule {
@ClassKey(ClipboardListener::class)
abstract fun bindClipboardListener(sysui: ClipboardListener): CoreStartable
- /** Inject into FsiChromeRepo. */
- @Binds
- @IntoMap
- @ClassKey(FsiChromeRepo::class)
- abstract fun bindFSIChromeRepo(sysui: FsiChromeRepo): CoreStartable
-
- /** Inject into FsiChromeWindowViewModel. */
- @Binds
- @IntoMap
- @ClassKey(FsiChromeViewModelFactory::class)
- abstract fun bindFSIChromeWindowViewModel(sysui: FsiChromeViewModelFactory): CoreStartable
-
- /** Inject into FsiChromeWindowBinder. */
- @Binds
- @IntoMap
- @ClassKey(FsiChromeViewBinder::class)
- abstract fun bindFsiChromeWindowBinder(sysui: FsiChromeViewBinder): CoreStartable
-
/** Inject into GlobalActionsComponent. */
@Binds
@IntoMap
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index f6bb85f4c10d..7a1abf46bd93 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -75,6 +75,7 @@ import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.connectivity.ConnectivityModule;
+import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
@@ -256,6 +257,9 @@ public abstract class SystemUIModule {
@BindsOptionalOf
abstract FingerprintInteractiveToAuthProvider optionalFingerprintInteractiveToAuthProvider();
+ @BindsOptionalOf
+ abstract SystemStatusAnimationScheduler optionalSystemStatusAnimationScheduler();
+
@SysUISingleton
@Binds
abstract SystemClock bindSystemClock(SystemClockImpl systemClock);
diff --git a/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt b/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt
index 84f83f1ae956..45ff963c2a9f 100644
--- a/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt
+++ b/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt
@@ -128,7 +128,6 @@ constructor(
*
* This is equivalent of creating a listener manually and adding an event handler for the given
* command, like so:
- *
* ```
* class Demoable {
* private val demoHandler = object : DemoMode {
diff --git a/packages/SystemUI/src/com/android/systemui/devicepolicy/DevicePolicyManagerExt.kt b/packages/SystemUI/src/com/android/systemui/devicepolicy/DevicePolicyManagerExt.kt
new file mode 100644
index 000000000000..1390b4db3576
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/devicepolicy/DevicePolicyManagerExt.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2023 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.devicepolicy
+
+import android.app.admin.DevicePolicyManager
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL
+import android.content.ComponentName
+
+/** Returns true if the admin of [userId] disallows keyguard shortcuts. */
+fun DevicePolicyManager.areKeyguardShortcutsDisabled(
+ admin: ComponentName? = null,
+ userId: Int
+): Boolean {
+ val flags = getKeyguardDisabledFeatures(admin, userId)
+ return flags and KEYGUARD_DISABLE_SHORTCUTS_ALL == KEYGUARD_DISABLE_SHORTCUTS_ALL ||
+ flags and KEYGUARD_DISABLE_FEATURES_ALL == KEYGUARD_DISABLE_FEATURES_ALL
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
index c3bd5d96590e..ca1cef385755 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
@@ -184,6 +184,7 @@ constructor(
/**
* Ends the dream content and dream overlay animations, if they're currently running.
+ *
* @see [AnimatorSet.end]
*/
fun endAnimations() {
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
index a14aa5222580..9374ad93347a 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
@@ -16,6 +16,8 @@
package com.android.systemui.dreams;
+import static com.android.systemui.dreams.dagger.DreamModule.DREAM_OVERLAY_WINDOW_TITLE;
+
import android.content.ComponentName;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
@@ -76,6 +78,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
private final ComponentName mLowLightDreamComponent;
private final UiEventLogger mUiEventLogger;
private final WindowManager mWindowManager;
+ private final String mWindowTitle;
// A reference to the {@link Window} used to hold the dream overlay.
private Window mWindow;
@@ -151,7 +154,8 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
TouchInsetManager touchInsetManager,
@Nullable @Named(LowLightDreamModule.LOW_LIGHT_DREAM_COMPONENT)
ComponentName lowLightDreamComponent,
- DreamOverlayCallbackController dreamOverlayCallbackController) {
+ DreamOverlayCallbackController dreamOverlayCallbackController,
+ @Named(DREAM_OVERLAY_WINDOW_TITLE) String windowTitle) {
mContext = context;
mExecutor = executor;
mWindowManager = windowManager;
@@ -161,6 +165,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
mStateController = stateController;
mUiEventLogger = uiEventLogger;
mDreamOverlayCallbackController = dreamOverlayCallbackController;
+ mWindowTitle = windowTitle;
final ViewModelStore viewModelStore = new ViewModelStore();
final Complication.Host host =
@@ -221,7 +226,14 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
mDreamOverlayTouchMonitor.init();
mStateController.setShouldShowComplications(shouldShowComplications());
- addOverlayWindowLocked(layoutParams);
+
+ // If we are not able to add the overlay window, reset the overlay.
+ if (!addOverlayWindowLocked(layoutParams)) {
+ resetCurrentDreamOverlayLocked();
+ return;
+ }
+
+
setCurrentStateLocked(Lifecycle.State.RESUMED);
mStateController.setOverlayActive(true);
final ComponentName dreamComponent = getDreamComponent();
@@ -267,10 +279,10 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
* @param layoutParams The {@link android.view.WindowManager.LayoutParams} which allow inserting
* into the dream window.
*/
- private void addOverlayWindowLocked(WindowManager.LayoutParams layoutParams) {
+ private boolean addOverlayWindowLocked(WindowManager.LayoutParams layoutParams) {
mWindow = new PhoneWindow(mContext);
// Default to SystemUI name for TalkBack.
- mWindow.setTitle("");
+ mWindow.setTitle(mWindowTitle);
mWindow.setAttributes(layoutParams);
mWindow.setWindowManager(null, layoutParams.token, "DreamOverlay", true);
@@ -292,9 +304,22 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
// risk an IllegalStateException in some cases when setting the container view as the
// window's content view and the container view hasn't been properly removed previously).
removeContainerViewFromParentLocked();
+
mWindow.setContentView(mDreamOverlayContainerViewController.getContainerView());
- mWindowManager.addView(mWindow.getDecorView(), mWindow.getAttributes());
+ // It is possible that a dream's window (and the dream as a whole) is no longer valid by
+ // the time the overlay service processes the dream. This can happen for example if
+ // another dream is started immediately after the existing dream begins. In this case, the
+ // overlay service should identify the situation through the thrown exception and tear down
+ // the overlay.
+ try {
+ mWindowManager.addView(mWindow.getDecorView(), mWindow.getAttributes());
+ return true;
+ } catch (WindowManager.BadTokenException exception) {
+ Log.e(TAG, "Dream activity window invalid: " + layoutParams.packageName,
+ exception);
+ return false;
+ }
}
private void removeContainerViewFromParentLocked() {
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java
index e39073bb6711..ff1f31245570 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java
@@ -28,6 +28,8 @@ import android.widget.FrameLayout;
import com.android.systemui.CoreStartable;
import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.dreams.smartspace.DreamSmartspaceController;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.BcSmartspaceDataPlugin;
import com.android.systemui.shared.condition.Monitor;
import com.android.systemui.util.condition.ConditionalCoreStartable;
@@ -68,6 +70,7 @@ public class SmartSpaceComplication implements Complication {
private final DreamSmartspaceController mSmartSpaceController;
private final DreamOverlayStateController mDreamOverlayStateController;
private final SmartSpaceComplication mComplication;
+ private final FeatureFlags mFeatureFlags;
private final BcSmartspaceDataPlugin.SmartspaceTargetListener mSmartspaceListener =
new BcSmartspaceDataPlugin.SmartspaceTargetListener() {
@@ -85,15 +88,21 @@ public class SmartSpaceComplication implements Complication {
DreamOverlayStateController dreamOverlayStateController,
SmartSpaceComplication smartSpaceComplication,
DreamSmartspaceController smartSpaceController,
- @Named(DREAM_PRETEXT_MONITOR) Monitor monitor) {
+ @Named(DREAM_PRETEXT_MONITOR) Monitor monitor,
+ FeatureFlags featureFlags) {
super(monitor);
mDreamOverlayStateController = dreamOverlayStateController;
mComplication = smartSpaceComplication;
mSmartSpaceController = smartSpaceController;
+ mFeatureFlags = featureFlags;
}
@Override
public void onStart() {
+ if (mFeatureFlags.isEnabled(Flags.HIDE_SMARTSPACE_ON_DREAM_OVERLAY)) {
+ return;
+ }
+
mDreamOverlayStateController.addCallback(new DreamOverlayStateController.Callback() {
@Override
public void onStateChanged() {
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
index f598c360dbcf..f130026b76b4 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
@@ -23,6 +23,7 @@ import android.content.res.Resources;
import com.android.dream.lowlight.dagger.LowLightDreamModule;
import com.android.settingslib.dream.DreamBackend;
+import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dreams.DreamOverlayNotificationCountProvider;
@@ -66,6 +67,8 @@ public interface DreamModule {
String DREAM_SUPPORTED = "dream_supported";
String DREAM_PRETEXT_CONDITIONS = "dream_pretext_conditions";
String DREAM_PRETEXT_MONITOR = "dream_prtext_monitor";
+ String DREAM_OVERLAY_WINDOW_TITLE = "dream_overlay_window_title";
+
/**
* Provides the dream component
@@ -139,4 +142,11 @@ public interface DreamModule {
@Named(DREAM_PRETEXT_CONDITIONS) Set<Condition> pretextConditions) {
return new Monitor(executor, pretextConditions);
}
+
+ /** */
+ @Provides
+ @Named(DREAM_OVERLAY_WINDOW_TITLE)
+ static String providesDreamOverlayWindowTitle(@Main Resources resources) {
+ return resources.getString(R.string.app_label);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/BouncerScrimController.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/BouncerScrimController.java
index f5bbba780b27..776b7bd080d0 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/BouncerScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/touch/scrim/BouncerScrimController.java
@@ -34,7 +34,7 @@ public class BouncerScrimController implements ScrimController {
@Override
public void show() {
- mStatusBarKeyguardViewManager.showBouncer(false);
+ mStatusBarKeyguardViewManager.showPrimaryBouncer(false);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index fa4caaf8960d..3608b91aa91a 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -62,10 +62,7 @@ object Flags {
val FSI_REQUIRES_KEYGUARD = releasedFlag(110, "fsi_requires_keyguard")
// TODO(b/259130119): Tracking Bug
- val FSI_ON_DND_UPDATE = unreleasedFlag(259130119, "fsi_on_dnd_update", teamfood = true)
-
- // TODO(b/265804648): Tracking Bug
- @JvmField val DISABLE_FSI = unreleasedFlag(265804648, "disable_fsi")
+ val FSI_ON_DND_UPDATE = releasedFlag(259130119, "fsi_on_dnd_update")
// TODO(b/254512538): Tracking Bug
val INSTANT_VOICE_REPLY = releasedFlag(111, "instant_voice_reply")
@@ -87,9 +84,6 @@ object Flags {
val NOTIFICATION_GROUP_DISMISSAL_ANIMATION =
releasedFlag(259217907, "notification_group_dismissal_animation")
- // TODO(b/257506350): Tracking Bug
- @JvmField val FSI_CHROME = unreleasedFlag(117, "fsi_chrome")
-
@JvmField
val SIMPLIFIED_APPEAR_FRACTION =
unreleasedFlag(259395680, "simplified_appear_fraction", teamfood = true)
@@ -155,7 +149,7 @@ object Flags {
// TODO(b/255618149): Tracking Bug
@JvmField
val CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES =
- unreleasedFlag(216, "customizable_lock_screen_quick_affordances", teamfood = true)
+ releasedFlag(216, "customizable_lock_screen_quick_affordances")
/** Shows chipbar UI whenever the device is unlocked by ActiveUnlock (watch). */
// TODO(b/256513609): Tracking Bug
@@ -187,11 +181,7 @@ object Flags {
// TODO(b/262780002): Tracking Bug
@JvmField
- val REVAMPED_WALLPAPER_UI = unreleasedFlag(222, "revamped_wallpaper_ui", teamfood = true)
-
- /** A different path for unocclusion transitions back to keyguard */
- // TODO(b/262859270): Tracking Bug
- @JvmField val UNOCCLUSION_TRANSITION = releasedFlag(223, "unocclusion_transition")
+ val REVAMPED_WALLPAPER_UI = releasedFlag(222, "revamped_wallpaper_ui")
// flag for controlling auto pin confirmation and material u shapes in bouncer
@JvmField
@@ -214,10 +204,9 @@ object Flags {
// TODO(b/266242192): Tracking Bug
@JvmField
val LOCK_SCREEN_LONG_PRESS_ENABLED =
- unreleasedFlag(
+ releasedFlag(
228,
- "lock_screen_long_press_enabled",
- teamfood = true,
+ "lock_screen_long_press_enabled"
)
// 300 - power menu
@@ -235,10 +224,12 @@ object Flags {
val SMARTSPACE_DATE_WEATHER_DECOUPLED =
sysPropBooleanFlag(403, "persist.sysui.ss.dw_decoupled", default = true)
+ // TODO(b/270223352): Tracking Bug
+ @JvmField
+ val HIDE_SMARTSPACE_ON_DREAM_OVERLAY = unreleasedFlag(404, "hide_smartspace_on_dream_overlay")
+
// 500 - quick settings
- // TODO(b/254512321): Tracking Bug
- @JvmField val COMBINED_QS_HEADERS = releasedFlag(501, "combined_qs_headers")
val PEOPLE_TILE = resourceBooleanFlag(502, R.bool.flag_conversations, "people_tile")
@JvmField
@@ -249,6 +240,9 @@ object Flags {
"qs_user_detail_shortcut"
)
+ @JvmField
+ val QS_PIPELINE_NEW_HOST = unreleasedFlag(504, "qs_pipeline_new_host", teamfood = false)
+
// TODO(b/254512383): Tracking Bug
@JvmField
val FULL_SCREEN_USER_SWITCHER =
@@ -266,6 +260,12 @@ object Flags {
@JvmField
val ENABLE_FONT_SCALING_TILE = unreleasedFlag(509, "enable_font_scaling_tile", teamfood = false)
+ /** Enables new QS Edit Mode visual refresh */
+ // TODO(b/269787742): Tracking Bug
+ @JvmField
+ val ENABLE_NEW_QS_EDIT_MODE =
+ unreleasedFlag(510, "enable_new_qs_edit_mode", teamfood = false)
+
// 600- status bar
// TODO(b/256614753): Tracking Bug
@@ -291,6 +291,9 @@ object Flags {
val NEW_STATUS_BAR_ICONS_DEBUG_COLORING =
unreleasedFlag(611, "new_status_bar_icons_debug_coloring")
+ // TODO(b/265892345): Tracking Bug
+ val PLUG_IN_STATUS_BAR_CHIP = unreleasedFlag(265892345, "plug_in_status_bar_chip")
+
// 700 - dialer/calls
// TODO(b/254512734): Tracking Bug
val ONGOING_CALL_STATUS_BAR_CHIP = releasedFlag(700, "ongoing_call_status_bar_chip")
@@ -364,15 +367,24 @@ object Flags {
// TODO(b/267166152) : Tracking Bug
val MEDIA_RETAIN_RECOMMENDATIONS = releasedFlag(916, "media_retain_recommendations")
+ // TODO(b/270437894): Tracking Bug
+ val MEDIA_REMOTE_RESUME = unreleasedFlag(917, "media_remote_resume")
+
// 1000 - dock
val SIMULATE_DOCK_THROUGH_CHARGING = releasedFlag(1000, "simulate_dock_through_charging")
// TODO(b/254512758): Tracking Bug
@JvmField val ROUNDED_BOX_RIPPLE = releasedFlag(1002, "rounded_box_ripple")
+ // TODO(b/270882464): Tracking Bug
+ val ENABLE_DOCK_SETUP_V2 = unreleasedFlag(1005, "enable_dock_setup_v2")
+
// TODO(b/265045965): Tracking Bug
val SHOW_LOWLIGHT_ON_DIRECT_BOOT = releasedFlag(1003, "show_lowlight_on_direct_boot")
+ @JvmField
+ val ENABLE_LOW_LIGHT_CLOCK_UNDOCKED = unreleasedFlag(1004, "enable_low_light_clock_undocked")
+
// 1100 - windowing
@Keep
@JvmField
@@ -481,9 +493,9 @@ object Flags {
val WM_ENABLE_PREDICTIVE_BACK_SYSUI =
unreleasedFlag(1204, "persist.wm.debug.predictive_back_sysui_enable", teamfood = true)
- // TODO(b/255697805): Tracking Bug
+ // TODO(b/270987164): Tracking Bug
@JvmField
- val TRACKPAD_GESTURE_BACK = unreleasedFlag(1205, "trackpad_gesture_back", teamfood = false)
+ val TRACKPAD_GESTURE_BACK = unreleasedFlag(1205, "trackpad_gesture_back", teamfood = true)
// TODO(b/263826204): Tracking Bug
@JvmField
@@ -613,11 +625,6 @@ object Flags {
@JvmField
val OUTPUT_SWITCHER_DEVICE_STATUS = releasedFlag(2502, "output_switcher_device_status")
- // TODO(b/20911786): Tracking Bug
- @JvmField
- val OUTPUT_SWITCHER_SHOW_API_ENABLED =
- releasedFlag(2503, "output_switcher_show_api_enabled", teamfood = true)
-
// 2700 - unfold transitions
// TODO(b/265764985): Tracking Bug
@Keep
@@ -630,7 +637,8 @@ object Flags {
// 2600 - keyboard
// TODO(b/259352579): Tracking Bug
- @JvmField val SHORTCUT_LIST_SEARCH_LAYOUT = unreleasedFlag(2600, "shortcut_list_search_layout")
+ @JvmField val SHORTCUT_LIST_SEARCH_LAYOUT =
+ unreleasedFlag(2600, "shortcut_list_search_layout", teamfood = true)
// TODO(b/259428678): Tracking Bug
@JvmField
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
index 949bcfbd684d..e43f83b876ba 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
@@ -2056,6 +2056,10 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene
|| Intent.ACTION_SCREEN_OFF.equals(action)) {
String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY);
if (!SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS.equals(reason)) {
+ // These broadcasts are usually received when locking the device, swiping up to
+ // home (which collapses the shade), etc. In those cases, we usually don't want
+ // to animate this dialog back into the view, so we disable the exit animations.
+ mDialogLaunchAnimator.disableAllCurrentDialogsExitAnimations();
mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISMISS, reason));
}
} else if (TelephonyManager.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED.equals(action)) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardModule.kt b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardModule.kt
index e9b8908214fc..496c64e1120e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardModule.kt
@@ -17,6 +17,14 @@
package com.android.systemui.keyboard
+import com.android.systemui.keyboard.data.repository.KeyboardRepository
+import com.android.systemui.keyboard.data.repository.KeyboardRepositoryImpl
+import dagger.Binds
import dagger.Module
-@Module abstract class KeyboardModule
+@Module
+abstract class KeyboardModule {
+
+ @Binds
+ abstract fun bindKeyboardRepository(repository: KeyboardRepositoryImpl): KeyboardRepository
+}
diff --git a/core/java/android/window/IWindowlessStartingSurfaceCallback.aidl b/packages/SystemUI/src/com/android/systemui/keyboard/data/model/BacklightModel.kt
index a0813565b256..ea15a9f18584 100644
--- a/core/java/android/window/IWindowlessStartingSurfaceCallback.aidl
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/data/model/BacklightModel.kt
@@ -11,19 +11,14 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
+ *
*/
-package android.window;
-
-import android.view.SurfaceControl;
+package com.android.systemui.keyboard.data.model
/**
- * Interface to be invoked when a windowless starting surface added.
- *
- * @param addedSurface The starting surface.
- * {@hide}
+ * Model for current state of keyboard backlight brightness. [level] indicates current level of
+ * backlight brightness and [maxLevel] its max possible value.
*/
-interface IWindowlessStartingSurfaceCallback {
- void onSurfaceAdded(in SurfaceControl addedSurface);
-}
+data class BacklightModel(val level: Int, val maxLevel: Int)
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/data/repository/KeyboardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyboard/data/repository/KeyboardRepository.kt
new file mode 100644
index 000000000000..dd5c5d31fae3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/data/repository/KeyboardRepository.kt
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2023 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.keyboard.data.repository
+
+import android.hardware.input.InputManager
+import android.hardware.input.InputManager.KeyboardBacklightListener
+import android.hardware.input.KeyboardBacklightState
+import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.keyboard.data.model.BacklightModel
+import java.util.concurrent.Executor
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.channels.SendChannel
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.shareIn
+
+interface KeyboardRepository {
+ val keyboardConnected: Flow<Boolean>
+ val backlight: Flow<BacklightModel>
+}
+
+@SysUISingleton
+class KeyboardRepositoryImpl
+@Inject
+constructor(
+ @Application private val applicationScope: CoroutineScope,
+ @Background private val backgroundDispatcher: CoroutineDispatcher,
+ private val inputManager: InputManager,
+) : KeyboardRepository {
+
+ private val connectedDeviceIds: Flow<Set<Int>> =
+ conflatedCallbackFlow {
+ var connectedKeyboards = inputManager.inputDeviceIds.toSet()
+ val listener =
+ object : InputManager.InputDeviceListener {
+ override fun onInputDeviceAdded(deviceId: Int) {
+ connectedKeyboards = connectedKeyboards + deviceId
+ sendWithLogging(connectedKeyboards)
+ }
+
+ override fun onInputDeviceChanged(deviceId: Int) = Unit
+
+ override fun onInputDeviceRemoved(deviceId: Int) {
+ connectedKeyboards = connectedKeyboards - deviceId
+ sendWithLogging(connectedKeyboards)
+ }
+ }
+ sendWithLogging(connectedKeyboards)
+ inputManager.registerInputDeviceListener(listener, /* handler= */ null)
+ awaitClose { inputManager.unregisterInputDeviceListener(listener) }
+ }
+ .shareIn(
+ scope = applicationScope,
+ started = SharingStarted.Lazily,
+ replay = 1,
+ )
+
+ private val backlightStateListener: Flow<KeyboardBacklightState> = conflatedCallbackFlow {
+ val listener = KeyboardBacklightListener { _, state, isTriggeredByKeyPress ->
+ if (isTriggeredByKeyPress) {
+ sendWithLogging(state)
+ }
+ }
+ inputManager.registerKeyboardBacklightListener(Executor(Runnable::run), listener)
+ awaitClose { inputManager.unregisterKeyboardBacklightListener(listener) }
+ }
+
+ override val keyboardConnected: Flow<Boolean> =
+ connectedDeviceIds
+ .map { it.any { deviceId -> isPhysicalFullKeyboard(deviceId) } }
+ .distinctUntilChanged()
+ .flowOn(backgroundDispatcher)
+
+ override val backlight: Flow<BacklightModel> =
+ backlightStateListener
+ .map { BacklightModel(it.brightnessLevel, it.maxBrightnessLevel) }
+ .flowOn(backgroundDispatcher)
+
+ private fun <T> SendChannel<T>.sendWithLogging(element: T) {
+ trySendWithFailureLogging(element, TAG)
+ }
+
+ private fun isPhysicalFullKeyboard(deviceId: Int): Boolean {
+ val device = inputManager.getInputDevice(deviceId)
+ return !device.isVirtual && device.isFullKeyboard
+ }
+
+ companion object {
+ const val TAG = "KeyboardRepositoryImpl"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 7a891b0058af..eef7ccc65d95 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -602,6 +602,7 @@ public class KeyguardService extends Service {
checkPermission();
mKeyguardViewMediator.onScreenTurnedOff();
mKeyguardLifecyclesDispatcher.dispatch(KeyguardLifecyclesDispatcher.SCREEN_TURNED_OFF);
+ mScreenOnCoordinator.onScreenTurnedOff();
}
@Override // Binder interface
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
index 0ca9115723a3..57c4b36b8b7a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
@@ -945,9 +945,9 @@ class KeyguardUnlockAnimationController @Inject constructor(
return false
}
- // We don't do the shared element on tablets because they're large and the smartspace has to
- // fly across large distances, which is distracting.
- if (Utilities.isTablet(context)) {
+ // We don't do the shared element on large screens because the smartspace has to fly across
+ // large distances, which is distracting.
+ if (Utilities.isLargeScreen(context)) {
return false
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 02bee3efbe2f..2ad1ab722d55 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -127,8 +127,6 @@ import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.keyguard.dagger.KeyguardModule;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -522,8 +520,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
private CentralSurfaces mCentralSurfaces;
- private boolean mUnocclusionTransitionFlagEnabled = false;
-
private final DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener =
new DeviceConfig.OnPropertiesChangedListener() {
@Override
@@ -970,9 +966,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
public void onAnimationStart(int transit, RemoteAnimationTarget[] apps,
RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
IRemoteAnimationFinishedCallback finishedCallback) throws RemoteException {
- if (!mUnocclusionTransitionFlagEnabled) {
- setOccluded(true /* isOccluded */, true /* animate */);
- }
if (apps == null || apps.length == 0 || apps[0] == null) {
if (DEBUG) {
Log.d(TAG, "No apps provided to the OccludeByDream runner; "
@@ -1023,7 +1016,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
@Override
public void onAnimationEnd(Animator animation) {
try {
- if (!mIsCancelled && mUnocclusionTransitionFlagEnabled) {
+ if (!mIsCancelled) {
// We're already on the main thread, don't queue this call
handleSetOccluded(true /* isOccluded */,
false /* animate */);
@@ -1200,7 +1193,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
ScreenOnCoordinator screenOnCoordinator,
InteractionJankMonitor interactionJankMonitor,
DreamOverlayStateController dreamOverlayStateController,
- FeatureFlags featureFlags,
Lazy<ShadeController> shadeControllerLazy,
Lazy<NotificationShadeWindowController> notificationShadeWindowControllerLazy,
Lazy<ActivityLaunchAnimator> activityLaunchAnimator,
@@ -1259,7 +1251,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
mDreamOpenAnimationDuration = (int) DREAMING_ANIMATION_DURATION_MS;
mDreamCloseAnimationDuration = (int) LOCKSCREEN_ANIMATION_DURATION_MS;
- mUnocclusionTransitionFlagEnabled = featureFlags.isEnabled(Flags.UNOCCLUSION_TRANSITION);
}
public void userActivity() {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
index 98d3570106ce..47ef0fac17ab 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -39,7 +39,6 @@ import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.KeyguardViewMediator;
@@ -113,7 +112,6 @@ public class KeyguardModule {
ScreenOnCoordinator screenOnCoordinator,
InteractionJankMonitor interactionJankMonitor,
DreamOverlayStateController dreamOverlayStateController,
- FeatureFlags featureFlags,
Lazy<ShadeController> shadeController,
Lazy<NotificationShadeWindowController> notificationShadeWindowController,
Lazy<ActivityLaunchAnimator> activityLaunchAnimator,
@@ -144,7 +142,6 @@ public class KeyguardModule {
screenOnCoordinator,
interactionJankMonitor,
dreamOverlayStateController,
- featureFlags,
shadeController,
notificationShadeWindowController,
activityLaunchAnimator,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt
index be73f851fa82..ef0c9a175141 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt
@@ -134,7 +134,9 @@ constructor(
.flowOn(backgroundDispatcher)
.distinctUntilChanged()
.onEach { settingsValue = it }
- ) { callbackFlowValue, _ -> callbackFlowValue }
+ ) { callbackFlowValue, _ ->
+ callbackFlowValue
+ }
override suspend fun getPickerScreenState(): KeyguardQuickAffordanceConfig.PickerScreenState {
return if (controller.isZenAvailable) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManager.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManager.kt
index 006678546de8..356a8fb65883 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManager.kt
@@ -102,7 +102,8 @@ constructor(
// setup).
emit(Unit)
}
- ) { _, _ -> }
+ ) { _, _ ->
+ }
.flatMapLatest {
conflatedCallbackFlow {
// We want to instantiate a new SharedPreferences instance each time either the
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt
index baadc66170cc..84abf57cacf2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt
@@ -24,8 +24,10 @@ import android.hardware.biometrics.BiometricManager
import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback
import android.os.Looper
import android.os.UserHandle
+import android.util.Log
import com.android.internal.widget.LockPatternUtils
import com.android.systemui.Dumpable
+import com.android.systemui.R
import com.android.systemui.biometrics.AuthController
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
@@ -35,6 +37,7 @@ import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dump.DumpManager
+import com.android.systemui.keyguard.shared.model.DevicePosture
import com.android.systemui.user.data.repository.UserRepository
import java.io.PrintWriter
import javax.inject.Inject
@@ -47,8 +50,10 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.transformLatest
@@ -82,6 +87,12 @@ interface BiometricSettingsRepository {
/** Whether fingerprint feature is enabled for the current user by the DevicePolicy */
val isFingerprintEnabledByDevicePolicy: StateFlow<Boolean>
+
+ /**
+ * Whether face authentication is supported for the current device posture. Face auth can be
+ * restricted to specific postures using [R.integer.config_face_auth_supported_posture]
+ */
+ val isFaceAuthSupportedInCurrentPosture: Flow<Boolean>
}
@SysUISingleton
@@ -98,11 +109,27 @@ constructor(
@Background backgroundDispatcher: CoroutineDispatcher,
biometricManager: BiometricManager?,
@Main looper: Looper,
+ devicePostureRepository: DevicePostureRepository,
dumpManager: DumpManager,
) : BiometricSettingsRepository, Dumpable {
+ override val isFaceAuthSupportedInCurrentPosture: Flow<Boolean>
+
init {
dumpManager.registerDumpable(this)
+ val configFaceAuthSupportedPosture =
+ DevicePosture.toPosture(
+ context.resources.getInteger(R.integer.config_face_auth_supported_posture)
+ )
+ isFaceAuthSupportedInCurrentPosture =
+ if (configFaceAuthSupportedPosture == DevicePosture.UNKNOWN) {
+ flowOf(true)
+ } else {
+ devicePostureRepository.currentDevicePosture.map {
+ it == configFaceAuthSupportedPosture
+ }
+ }
+ .onEach { Log.d(TAG, "isFaceAuthSupportedInCurrentPosture value changed to: $it") }
}
override fun dump(pw: PrintWriter, args: Array<String?>) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DevicePostureRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DevicePostureRepository.kt
new file mode 100644
index 000000000000..adb1e01d0d00
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DevicePostureRepository.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2023 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.keyguard.data.repository
+
+import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.shared.model.DevicePosture
+import com.android.systemui.statusbar.policy.DevicePostureController
+import javax.inject.Inject
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+
+/** Provide current device posture state. */
+interface DevicePostureRepository {
+ /** Provides the current device posture. */
+ val currentDevicePosture: Flow<DevicePosture>
+}
+
+@SysUISingleton
+class DevicePostureRepositoryImpl
+@Inject
+constructor(private val postureController: DevicePostureController) : DevicePostureRepository {
+ override val currentDevicePosture: Flow<DevicePosture>
+ get() = conflatedCallbackFlow {
+ val sendPostureUpdate = { posture: Int ->
+ val currentDevicePosture = DevicePosture.toPosture(posture)
+ trySendWithFailureLogging(
+ currentDevicePosture,
+ TAG,
+ "Error sending posture update to $currentDevicePosture"
+ )
+ }
+ val callback = DevicePostureController.Callback { sendPostureUpdate(it) }
+ postureController.addCallback(callback)
+ sendPostureUpdate(postureController.devicePosture)
+
+ awaitClose { postureController.removeCallback(callback) }
+ }
+
+ companion object {
+ const val TAG = "PostureRepositoryImpl"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt
index 0e85347c24b0..86e5cd738120 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt
@@ -53,6 +53,7 @@ interface KeyguardBouncerRepository {
val primaryBouncerScrimmed: StateFlow<Boolean>
/**
* Set how much of the notification panel is showing on the screen.
+ *
* ```
* 0f = panel fully hidden = bouncer fully showing
* 1f = panel fully showing = bouncer fully hidden
@@ -134,6 +135,7 @@ constructor(
override val primaryBouncerScrimmed = _primaryBouncerScrimmed.asStateFlow()
/**
* Set how much of the notification panel is showing on the screen.
+ *
* ```
* 0f = panel fully hidden = bouncer fully showing
* 1f = panel fully showing = bouncer fully hidden
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManager.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManager.kt
index 2069891a23e0..a3268405a830 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManager.kt
@@ -18,6 +18,7 @@ package com.android.systemui.keyguard.data.repository
import android.app.StatusBarManager
import android.content.Context
+import android.hardware.face.FaceAuthenticateOptions
import android.hardware.face.FaceManager
import android.os.CancellationSignal
import com.android.internal.logging.InstanceId
@@ -235,8 +236,7 @@ constructor(
cancellationSignal,
faceAuthCallback,
null,
- currentUserId,
- lockscreenBypassEnabled
+ FaceAuthenticateOptions.Builder().setUserId(currentUserId).build()
)
}
}
@@ -255,7 +255,11 @@ constructor(
withContext(mainDispatcher) {
// We always want to invoke face detect in the main thread.
faceAuthLogger.faceDetectionStarted()
- faceManager?.detectFace(cancellationSignal, detectionCallback, currentUserId)
+ faceManager?.detectFace(
+ cancellationSignal,
+ detectionCallback,
+ FaceAuthenticateOptions.Builder().setUserId(currentUserId).build()
+ )
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt
index 4a262f580749..f27f89995dbd 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt
@@ -31,6 +31,8 @@ interface KeyguardRepositoryModule {
@Binds
fun lightRevealScrimRepository(impl: LightRevealScrimRepositoryImpl): LightRevealScrimRepository
+ @Binds fun devicePostureRepository(impl: DevicePostureRepositoryImpl): DevicePostureRepository
+
@Binds
fun biometricSettingsRepository(
impl: BiometricSettingsRepositoryImpl
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt
index dfe10381720c..eae40d61cdb6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt
@@ -24,6 +24,7 @@ import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager.LegacyAlternateBouncer
+import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.time.SystemClock
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
@@ -33,6 +34,7 @@ import kotlinx.coroutines.flow.Flow
class AlternateBouncerInteractor
@Inject
constructor(
+ private val keyguardStateController: KeyguardStateController,
private val bouncerRepository: KeyguardBouncerRepository,
private val biometricSettingsRepository: BiometricSettingsRepository,
private val deviceEntryFingerprintAuthRepository: DeviceEntryFingerprintAuthRepository,
@@ -48,6 +50,7 @@ constructor(
/**
* Sets the correct bouncer states to show the alternate bouncer if it can show.
+ *
* @return whether alternateBouncer is visible
*/
fun show(): Boolean {
@@ -72,6 +75,7 @@ constructor(
* Sets the correct bouncer states to hide the bouncer. Should only be called through
* StatusBarKeyguardViewManager until ScrimController is refactored to use
* alternateBouncerInteractor.
+ *
* @return true if the alternate bouncer was newly hidden, else false.
*/
fun hide(): Boolean {
@@ -102,7 +106,8 @@ constructor(
biometricSettingsRepository.isFingerprintEnrolled.value &&
biometricSettingsRepository.isStrongBiometricAllowed.value &&
biometricSettingsRepository.isFingerprintEnabledByDevicePolicy.value &&
- !deviceEntryFingerprintAuthRepository.isLockedOut.value
+ !deviceEntryFingerprintAuthRepository.isLockedOut.value &&
+ !keyguardStateController.isUnlocked
} else {
legacyAlternateBouncer != null &&
keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(true)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt
index 310f44da6e66..e6568f20bc20 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt
@@ -71,8 +71,7 @@ constructor(
isPrimaryBouncerShowing,
lastStartedTransitionStep,
wakefulnessState,
- isAodAvailable
- ) ->
+ isAodAvailable) ->
if (
!isAlternateBouncerShowing &&
!isPrimaryBouncerShowing &&
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
index dfbe1c216847..bc3c7203ce3d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
@@ -26,6 +26,7 @@ import com.android.systemui.animation.DialogLaunchAnimator
import com.android.systemui.animation.Expandable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.devicepolicy.areKeyguardShortcutsDisabled
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig
@@ -119,7 +120,7 @@ constructor(
* Notifies that a quick affordance has been "triggered" (clicked) by the user.
*
* @param configKey The configuration key corresponding to the [KeyguardQuickAffordanceModel] of
- * the affordance that was clicked
+ * the affordance that was clicked
* @param expandable An optional [Expandable] for the activity- or dialog-launch animation
*/
fun onQuickAffordanceTriggered(
@@ -198,9 +199,9 @@ constructor(
*
* @param slotId The ID of the slot.
* @param affordanceId The ID of the affordance to remove; if `null`, removes all affordances
- * from the slot.
+ * from the slot.
* @return `true` if the affordance was successfully removed; `false` otherwise (for example, if
- * the affordance was not on the slot to begin with).
+ * the affordance was not on the slot to begin with).
*/
suspend fun unselect(slotId: String, affordanceId: String?): Boolean {
check(isUsingRepository)
@@ -410,16 +411,10 @@ constructor(
)
}
- private suspend fun isFeatureDisabledByDevicePolicy(): Boolean {
- val flags =
- withContext(backgroundDispatcher) {
- devicePolicyManager.getKeyguardDisabledFeatures(null, userTracker.userId)
- }
- val flagsToCheck =
- DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL or
- DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL
- return flagsToCheck and flags != 0
- }
+ private suspend fun isFeatureDisabledByDevicePolicy(): Boolean =
+ withContext(backgroundDispatcher) {
+ devicePolicyManager.areKeyguardShortcutsDisabled(userId = userTracker.userId)
+ }
companion object {
private const val TAG = "KeyguardQuickAffordanceInteractor"
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/DevicePosture.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/DevicePosture.kt
new file mode 100644
index 000000000000..fff7cfe1d6a3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/DevicePosture.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2023 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.keyguard.shared.model
+
+import com.android.systemui.statusbar.policy.DevicePostureController
+
+/** Represents the possible posture states of the device. */
+enum class DevicePosture {
+ UNKNOWN,
+ CLOSED,
+ HALF_OPENED,
+ OPENED,
+ FLIPPED;
+
+ companion object {
+ fun toPosture(@DevicePostureController.DevicePostureInt posture: Int): DevicePosture {
+ return when (posture) {
+ DevicePostureController.DEVICE_POSTURE_CLOSED -> CLOSED
+ DevicePostureController.DEVICE_POSTURE_HALF_OPENED -> HALF_OPENED
+ DevicePostureController.DEVICE_POSTURE_OPENED -> OPENED
+ DevicePostureController.DEVICE_POSTURE_FLIPPED -> FLIPPED
+ DevicePostureController.DEVICE_POSTURE_UNKNOWN -> UNKNOWN
+ else -> UNKNOWN
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/SysUiFaceAuthenticateOptions.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/SysUiFaceAuthenticateOptions.kt
new file mode 100644
index 000000000000..a79513ebd867
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/SysUiFaceAuthenticateOptions.kt
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2023 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.keyguard.shared.model
+
+import android.hardware.face.FaceAuthenticateOptions
+import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN
+import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_ASSISTANT_VISIBLE
+import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED
+import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED
+import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED
+import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN
+import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_STARTED_WAKING_UP
+import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER
+import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_UDFPS_POINTER_DOWN
+import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_UNKNOWN
+import android.hardware.face.FaceAuthenticateOptions.AuthenticateReason
+import android.os.PowerManager
+import android.os.PowerManager.WAKE_REASON_UNKNOWN
+import android.util.Log
+import com.android.internal.logging.UiEvent
+import com.android.internal.logging.UiEventLogger
+import com.android.keyguard.FaceAuthUiEvent
+
+/**
+ * Wrapper for [FaceAuthenticateOptions] to convert SystemUI values to their corresponding value in
+ * [FaceAuthenticateOptions].
+ */
+data class SysUiFaceAuthenticateOptions(
+ val userId: Int,
+ private val faceAuthUiEvent: UiEventLogger.UiEventEnum,
+ @PowerManager.WakeReason val wakeReason: Int = WAKE_REASON_UNKNOWN
+) {
+ val authenticateReason = setAuthenticateReason(faceAuthUiEvent)
+
+ /**
+ * The [FaceAuthUiEvent] for this operation. This method converts the UiEvent to the framework
+ * [AuthenticateReason].
+ */
+ @AuthenticateReason
+ fun setAuthenticateReason(uiEvent: UiEventLogger.UiEventEnum): Int {
+ return when (uiEvent) {
+ FaceAuthUiEvent.FACE_AUTH_UPDATED_STARTED_WAKING_UP -> {
+ AUTHENTICATE_REASON_STARTED_WAKING_UP
+ }
+ FaceAuthUiEvent.FACE_AUTH_UPDATED_PRIMARY_BOUNCER_SHOWN,
+ FaceAuthUiEvent.FACE_AUTH_UPDATED_PRIMARY_BOUNCER_SHOWN_OR_WILL_BE_SHOWN -> {
+ AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN
+ }
+ FaceAuthUiEvent.FACE_AUTH_UPDATED_ASSISTANT_VISIBILITY_CHANGED -> {
+ AUTHENTICATE_REASON_ASSISTANT_VISIBLE
+ }
+ FaceAuthUiEvent.FACE_AUTH_TRIGGERED_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN -> {
+ AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN
+ }
+ FaceAuthUiEvent.FACE_AUTH_TRIGGERED_NOTIFICATION_PANEL_CLICKED -> {
+ AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED
+ }
+ FaceAuthUiEvent.FACE_AUTH_TRIGGERED_OCCLUDING_APP_REQUESTED -> {
+ AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED
+ }
+ FaceAuthUiEvent.FACE_AUTH_TRIGGERED_PICK_UP_GESTURE_TRIGGERED -> {
+ AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED
+ }
+ FaceAuthUiEvent.FACE_AUTH_TRIGGERED_SWIPE_UP_ON_BOUNCER -> {
+ AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER
+ }
+ FaceAuthUiEvent.FACE_AUTH_TRIGGERED_UDFPS_POINTER_DOWN -> {
+ AUTHENTICATE_REASON_UDFPS_POINTER_DOWN
+ }
+ else -> {
+ Log.e("FaceAuthenticateOptions", " unmapped FaceAuthUiEvent $uiEvent")
+ AUTHENTICATE_REASON_UNKNOWN
+ }
+ }
+ }
+
+ /** Builds the instance. */
+ fun toFaceAuthenticateOptions(): FaceAuthenticateOptions {
+ return FaceAuthenticateOptions.Builder()
+ .setUserId(userId)
+ .setAuthenticateReason(authenticateReason)
+ .setWakeReason(wakeReason)
+ .build()
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
index ab009f4a6a66..2a9060f6db47 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
@@ -342,7 +342,13 @@ object KeyguardBottomAreaViewBinder {
if (viewModel.isClickable) {
if (viewModel.useLongPress) {
view.setOnTouchListener(
- OnTouchListener(view, viewModel, messageDisplayer, vibratorHelper)
+ OnTouchListener(
+ view,
+ viewModel,
+ messageDisplayer,
+ vibratorHelper,
+ falsingManager,
+ )
)
} else {
view.setOnClickListener(OnClickListener(viewModel, checkNotNull(falsingManager)))
@@ -371,6 +377,7 @@ object KeyguardBottomAreaViewBinder {
private val viewModel: KeyguardQuickAffordanceViewModel,
private val messageDisplayer: (Int) -> Unit,
private val vibratorHelper: VibratorHelper?,
+ private val falsingManager: FalsingManager?,
) : View.OnTouchListener {
private val longPressDurationMs = ViewConfiguration.getLongPressTimeout().toLong()
@@ -395,7 +402,14 @@ object KeyguardBottomAreaViewBinder {
.scaleY(PRESSED_SCALE)
.setDuration(longPressDurationMs)
.withEndAction {
- dispatchClick(viewModel.configKey)
+ if (
+ falsingManager
+ ?.isFalseLongTap(
+ FalsingManager.MODERATE_PENALTY
+ ) == false
+ ) {
+ dispatchClick(viewModel.configKey)
+ }
cancel()
}
}
@@ -421,7 +435,8 @@ object KeyguardBottomAreaViewBinder {
// the pointer performs a click.
if (
viewModel.configKey != null &&
- distanceMoved(event) <= ViewConfiguration.getTouchSlop()
+ distanceMoved(event) <= ViewConfiguration.getTouchSlop() &&
+ falsingManager?.isFalseTap(FalsingManager.NO_PENALTY) == false
) {
dispatchClick(viewModel.configKey)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardLongPressViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardLongPressViewBinder.kt
index ef3f242a39a9..86717537efd3 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardLongPressViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardLongPressViewBinder.kt
@@ -34,7 +34,7 @@ object KeyguardLongPressViewBinder {
* @param viewModel The view-model that models the UI state.
* @param onSingleTap A callback to invoke when the system decides that there was a single tap.
* @param falsingManager [FalsingManager] for making sure the long-press didn't just happen in
- * the user's pocket.
+ * the user's pocket.
*/
@JvmStatic
fun bind(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt
index 1e3b60c27d84..ab9e6a4ce045 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt
@@ -135,7 +135,7 @@ constructor(
*
* @param initiallySelectedSlotId The ID of the initial slot to render as the selected one.
* @param shouldHighlightSelectedAffordance Whether the selected quick affordance should be
- * highlighted (while all others are dimmed to make the selected one stand out).
+ * highlighted (while all others are dimmed to make the selected one stand out).
*/
fun enablePreviewMode(
initiallySelectedSlotId: String?,
@@ -187,6 +187,7 @@ constructor(
previewMode.isInPreviewMode &&
previewMode.shouldHighlightSelectedAffordance &&
!isSelected,
+ forceInactive = previewMode.isInPreviewMode
)
}
.distinctUntilChanged()
@@ -198,6 +199,7 @@ constructor(
isClickable: Boolean,
isSelected: Boolean,
isDimmed: Boolean,
+ forceInactive: Boolean,
): KeyguardQuickAffordanceViewModel {
return when (this) {
is KeyguardQuickAffordanceModel.Visible ->
@@ -213,7 +215,7 @@ constructor(
)
},
isClickable = isClickable,
- isActivated = activationState is ActivationState.Active,
+ isActivated = !forceInactive && activationState is ActivationState.Active,
isSelected = isSelected,
useLongPress = quickAffordanceInteractor.useLongPress,
isDimmed = isDimmed,
diff --git a/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt b/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
index d69ac7fe035d..34a67403fc84 100644
--- a/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
+++ b/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
@@ -47,13 +47,13 @@ import kotlinx.coroutines.launch
* fresh one.
*
* @param coroutineContext An optional [CoroutineContext] to replace the dispatcher [block] is
- * invoked on.
+ * invoked on.
* @param block The block of code that should be run when the view becomes attached. It can end up
- * being invoked multiple times if the view is reattached after being detached.
+ * being invoked multiple times if the view is reattached after being detached.
* @return A [DisposableHandle] to invoke when the caller of the function destroys its [View] and is
- * no longer interested in the [block] being run the next time its attached. Calling this is an
- * optional optimization as the logic will be properly cleaned up and destroyed each time the view
- * is detached. Using this is not *thread-safe* and should only be used on the main thread.
+ * no longer interested in the [block] being run the next time its attached. Calling this is an
+ * optional optimization as the logic will be properly cleaned up and destroyed each time the view
+ * is detached. Using this is not *thread-safe* and should only be used on the main thread.
*/
@MainThread
fun View.repeatWhenAttached(
@@ -125,7 +125,6 @@ private fun createLifecycleOwnerAndRun(
* The implementation requires the caller to call [onCreate] and [onDestroy] when the view is
* attached to or detached from a view hierarchy. After [onCreate] and before [onDestroy] is called,
* the implementation monitors window state in the following way
- *
* * If the window is not visible, we are in the [Lifecycle.State.CREATED] state
* * If the window is visible but not focused, we are in the [Lifecycle.State.STARTED] state
* * If the window is visible and focused, we are in the [Lifecycle.State.RESUMED] state
diff --git a/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt b/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt
index f7349a2a7ae6..647e3a15ba2f 100644
--- a/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt
@@ -16,7 +16,6 @@ private const val TAG = "KeyguardFaceAuthManagerLog"
* Helper class for logging for [com.android.keyguard.faceauth.KeyguardFaceAuthManager]
*
* To enable logcat echoing for an entire buffer:
- *
* ```
* adb shell settings put global systemui/buffer/KeyguardFaceAuthManagerLog <logLevel>
*
diff --git a/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt b/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt
index 5acaa46c25d6..edc278d1ae4f 100644
--- a/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt
@@ -33,7 +33,6 @@ private const val TAG = "ScreenDecorationsLog"
* Helper class for logging for [com.android.systemui.ScreenDecorations]
*
* To enable logcat echoing for an entire buffer:
- *
* ```
* adb shell settings put global systemui/buffer/ScreenDecorationsLog <logLevel>
*
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
index 220993f8ad4f..ca1ed1f5b0be 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
@@ -62,6 +62,15 @@ public class LogModule {
return factory.create("NotifLog", maxSize, false /* systrace */);
}
+ /** Provides a logging buffer for all logs related to notifications on the lockscreen. */
+ @Provides
+ @SysUISingleton
+ @NotificationLockscreenLog
+ public static LogBuffer provideNotificationLockScreenLogBuffer(
+ LogBufferFactory factory) {
+ return factory.create("NotifLockscreenLog", 50, false /* systrace */);
+ }
+
/** Provides a logging buffer for logs related to heads up presentation of notifications. */
@Provides
@SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLockscreenLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLockscreenLog.java
new file mode 100644
index 000000000000..a2d381ec90f0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLockscreenLog.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2023 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.log.dagger;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.android.systemui.plugins.log.LogBuffer;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Qualifier;
+
+/** A {@link LogBuffer} for notification & lockscreen related messages. */
+@Qualifier
+@Documented
+@Retention(RUNTIME)
+public @interface NotificationLockscreenLog {
+}
diff --git a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
index 1712dab8aff9..29f273a5ed41 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
@@ -29,7 +29,6 @@ import kotlinx.coroutines.flow.Flow
*
* Some parts of System UI maintain a lot of pieces of state at once.
* [com.android.systemui.plugins.log.LogBuffer] allows us to easily log change events:
- *
* - 10-10 10:10:10.456: state2 updated to newVal2
* - 10-10 10:11:00.000: stateN updated to StateN(val1=true, val2=1)
* - 10-10 10:11:02.123: stateN updated to StateN(val1=true, val2=2)
@@ -37,7 +36,6 @@ import kotlinx.coroutines.flow.Flow
* - 10-10 10:11:06.000: stateN updated to StateN(val1=false, val2=3)
*
* However, it can sometimes be more useful to view the state changes in table format:
- *
* - timestamp--------- | state1- | state2- | ... | stateN.val1 | stateN.val2
* - -------------------------------------------------------------------------
* - 10-10 10:10:10.123 | val1--- | val2--- | ... | false------ | 0-----------
@@ -56,23 +54,18 @@ import kotlinx.coroutines.flow.Flow
* individual fields.
*
* How it works:
- *
* 1) Create an instance of this buffer via [TableLogBufferFactory].
- *
* 2) For any states being logged, implement [Diffable]. Implementing [Diffable] allows the state to
- * only log the fields that have *changed* since the previous update, instead of always logging all
- * fields.
- *
+ * only log the fields that have *changed* since the previous update, instead of always logging
+ * all fields.
* 3) Each time a change in a state happens, call [logDiffs]. If your state is emitted using a
- * [Flow], you should use the [logDiffsForTable] extension function to automatically log diffs any
- * time your flow emits a new value.
+ * [Flow], you should use the [logDiffsForTable] extension function to automatically log diffs
+ * any time your flow emits a new value.
*
* When a dump occurs, there will be two dumps:
- *
* 1) The change events under the dumpable name "$name-changes".
- *
* 2) This class will coalesce all the diffs into a table format and log them under the dumpable
- * name "$name-table".
+ * name "$name-table".
*
* @param maxSize the maximum size of the buffer. Must be > 0.
*/
@@ -99,11 +92,10 @@ class TableLogBuffer(
* The [newVal] object's method [Diffable.logDiffs] will be used to fetch the diffs.
*
* @param columnPrefix a prefix that will be applied to every column name that gets logged. This
- * ensures that all the columns related to the same state object will be grouped together in the
- * table.
- *
+ * ensures that all the columns related to the same state object will be grouped together in
+ * the table.
* @throws IllegalArgumentException if [columnPrefix] or column name contain "|". "|" is used as
- * the separator token for parsing, so it can't be present in any part of the column name.
+ * the separator token for parsing, so it can't be present in any part of the column name.
*/
@Synchronized
fun <T : Diffable<T>> logDiffs(columnPrefix: String, prevVal: T, newVal: T) {
@@ -117,7 +109,7 @@ class TableLogBuffer(
* Logs change(s) to the buffer using [rowInitializer].
*
* @param rowInitializer a function that will be called immediately to store relevant data on
- * the row.
+ * the row.
*/
@Synchronized
fun logChange(columnPrefix: String, rowInitializer: (TableRowLogger) -> Unit) {
diff --git a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
index 7ccc43ce62c2..06668d33408d 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
@@ -38,7 +38,6 @@ constructor(
*
* @param name a unique table name
* @param maxSize the buffer max size. See [adjustMaxSize]
- *
* @return a new [TableLogBuffer] registered with [DumpManager]
*/
fun create(
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/models/player/SeekBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/models/player/SeekBarViewModel.kt
index a057c9f22be3..2509f21242cd 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/models/player/SeekBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/models/player/SeekBarViewModel.kt
@@ -187,6 +187,7 @@ constructor(
/**
* Handle request to change the current position in the media track.
+ *
* @param position Place to seek to in the track.
*/
@AnyThread
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/SmartspaceMediaData.kt b/packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/SmartspaceMediaData.kt
index 0b57175defe7..ae03f27b32cd 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/SmartspaceMediaData.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/SmartspaceMediaData.kt
@@ -52,6 +52,7 @@ data class SmartspaceMediaData(
* Indicates if all the data is valid.
*
* TODO(b/230333302): Make MediaControlPanel more flexible so that we can display fewer than
+ *
* ```
* [NUM_REQUIRED_RECOMMENDATIONS].
* ```
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataFilter.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataFilter.kt
index 97717a64ce26..207df6bc4422 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataFilter.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataFilter.kt
@@ -329,9 +329,8 @@ constructor(
* Return the time since last active for the most-recent media.
*
* @param sortedEntries userEntries sorted from the earliest to the most-recent.
- *
* @return The duration in milliseconds from the most-recent media's last active timestamp to
- * the present. MAX_VALUE will be returned if there is no media.
+ * the present. MAX_VALUE will be returned if there is no media.
*/
private fun timeSinceActiveForMostRecentMedia(
sortedEntries: SortedMap<String, MediaData>
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt
index 9d6230b429f9..72c4aabd44b9 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt
@@ -526,8 +526,8 @@ class MediaDataManager(
* through the internal listener pipeline.
*
* @param immediately indicates should apply the UI changes immediately, otherwise wait until
- * the next refresh-round before UI becomes visible. Should only be true if the update is
- * initiated by user's interaction.
+ * the next refresh-round before UI becomes visible. Should only be true if the update is
+ * initiated by user's interaction.
*/
private fun notifySmartspaceMediaDataRemoved(key: String, immediately: Boolean) {
internalListeners.forEach { it.onSmartspaceMediaDataRemoved(key, immediately) }
@@ -536,6 +536,7 @@ class MediaDataManager(
/**
* Called whenever the player has been paused or stopped for a while, or swiped from QQS. This
* will make the player not active anymore, hiding it from QQS and Keyguard.
+ *
* @see MediaData.active
*/
internal fun setTimedOut(key: String, timedOut: Boolean, forceUpdate: Boolean = false) {
@@ -666,7 +667,7 @@ class MediaDataManager(
appIntent: PendingIntent,
packageName: String
) {
- if (TextUtils.isEmpty(desc.title)) {
+ if (desc.title.isNullOrBlank()) {
Log.e(TAG, "Description incomplete")
// Delete the placeholder entry
mediaEntries.remove(packageName)
@@ -1024,6 +1025,7 @@ class MediaDataManager(
* @param packageName Package name for the media app
* @param controller MediaController for the current session
* @return a Pair consisting of a list of media actions, and a list of ints representing which
+ *
* ```
* of those actions should be shown in the compact player
* ```
@@ -1127,6 +1129,7 @@ class MediaDataManager(
* [PlaybackState.ACTION_SKIP_TO_NEXT]
* @return
* ```
+ *
* A [MediaAction] with correct values set, or null if the state doesn't support it
*/
private fun getStandardAction(
@@ -1229,6 +1232,7 @@ class MediaDataManager(
}
/**
* Load a bitmap from a URI
+ *
* @param uri the uri to load
* @return bitmap, or null if couldn't be loaded
*/
@@ -1342,10 +1346,13 @@ class MediaDataManager(
fun onNotificationRemoved(key: String) {
Assert.isMainThread()
val removed = mediaEntries.remove(key) ?: return
-
+ val isEligibleForResume =
+ removed.isLocalSession() ||
+ (mediaFlags.isRemoteResumeAllowed() &&
+ removed.playbackLocation != MediaData.PLAYBACK_CAST_REMOTE)
if (keyguardUpdateMonitor.isUserInLockdown(removed.userId)) {
logger.logMediaRemoved(removed.appUid, removed.packageName, removed.instanceId)
- } else if (useMediaResumption && removed.resumeAction != null && removed.isLocalSession()) {
+ } else if (useMediaResumption && removed.resumeAction != null && isEligibleForResume) {
convertToResumePlayer(key, removed)
} else if (mediaFlags.isRetainingPlayersEnabled()) {
handlePossibleRemoval(key, removed, notificationRemoved = true)
@@ -1408,6 +1415,13 @@ class MediaDataManager(
/** Set the given [MediaData] as a resume state player and notify listeners */
private fun convertToResumePlayer(key: String, data: MediaData) {
if (DEBUG) Log.d(TAG, "Converting $key to resume")
+ // Resumption controls must have a title.
+ if (data.song.isNullOrBlank()) {
+ Log.e(TAG, "Description incomplete")
+ notifyMediaDataRemoved(key)
+ logger.logMediaRemoved(data.appUid, data.packageName, data.instanceId)
+ return
+ }
// Move to resume key (aka package name) if that key doesn't already exist.
val resumeAction = data.resumeAction?.let { getResumeMediaAction(it) }
val actions = resumeAction?.let { listOf(resumeAction) } ?: emptyList()
@@ -1512,15 +1526,13 @@ class MediaDataManager(
* notification key) or vice versa.
*
* @param immediately indicates should apply the UI changes immediately, otherwise wait
- * until the next refresh-round before UI becomes visible. True by default to take in place
- * immediately.
- *
+ * until the next refresh-round before UI becomes visible. True by default to take in
+ * place immediately.
* @param receivedSmartspaceCardLatency is the latency between headphone connects and sysUI
- * displays Smartspace media targets. Will be 0 if the data is not activated by Smartspace
- * signal.
- *
+ * displays Smartspace media targets. Will be 0 if the data is not activated by Smartspace
+ * signal.
* @param isSsReactivated indicates resume media card is reactivated by Smartspace
- * recommendation signal
+ * recommendation signal
*/
fun onMediaDataLoaded(
key: String,
@@ -1535,8 +1547,8 @@ class MediaDataManager(
* Called whenever there's new Smartspace media data loaded.
*
* @param shouldPrioritize indicates the sorting priority of the Smartspace card. If true,
- * it will be prioritized as the first card. Otherwise, it will show up as the last card as
- * default.
+ * it will be prioritized as the first card. Otherwise, it will show up as the last card
+ * as default.
*/
fun onSmartspaceMediaDataLoaded(
key: String,
@@ -1551,8 +1563,8 @@ class MediaDataManager(
* Called whenever a previously existing Smartspace media data was removed.
*
* @param immediately indicates should apply the UI changes immediately, otherwise wait
- * until the next refresh-round before UI becomes visible. True by default to take in place
- * immediately.
+ * until the next refresh-round before UI becomes visible. True by default to take in
+ * place immediately.
*/
fun onSmartspaceMediaDataRemoved(key: String, immediately: Boolean = true) {}
}
@@ -1561,7 +1573,7 @@ class MediaDataManager(
* Converts the pass-in SmartspaceTarget to SmartspaceMediaData
*
* @return An empty SmartspaceMediaData with the valid target Id is returned if the
- * SmartspaceTarget's data is invalid.
+ * SmartspaceTarget's data is invalid.
*/
private fun toSmartspaceMediaData(target: SmartspaceTarget): SmartspaceMediaData {
var dismissIntent: Intent? = null
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt
index 6a512be091e1..120704c0582a 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt
@@ -408,9 +408,9 @@ constructor(
* [LocalMediaManager.DeviceCallback.onAboutToConnectDeviceAdded] for more information.
*
* @property fullMediaDevice a full-fledged [MediaDevice] object representing the device. If
- * non-null, prefer using [fullMediaDevice] over [backupMediaDeviceData].
+ * non-null, prefer using [fullMediaDevice] over [backupMediaDeviceData].
* @property backupMediaDeviceData a backup [MediaDeviceData] object containing the minimum
- * information required to display the device. Only use if [fullMediaDevice] is null.
+ * information required to display the device. Only use if [fullMediaDevice] is null.
*/
private data class AboutToConnectDevice(
val fullMediaDevice: MediaDevice? = null,
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaTimeoutListener.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaTimeoutListener.kt
index 878962dc60b4..a1d9214cb215 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaTimeoutListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaTimeoutListener.kt
@@ -60,6 +60,7 @@ constructor(
/**
* Callback representing that a media object is now expired:
+ *
* @param key Media control unique identifier
* @param timedOut True when expired for {@code PAUSED_MEDIA_TIMEOUT} for active media,
* ```
@@ -70,6 +71,7 @@ constructor(
/**
* Callback representing that a media object [PlaybackState] has changed.
+ *
* @param key Media control unique identifier
* @param state The new [PlaybackState]
*/
@@ -77,6 +79,7 @@ constructor(
/**
* Callback representing that the [MediaSession] for an active control has been destroyed
+ *
* @param key Media control unique identifier
*/
lateinit var sessionCallback: (String) -> Unit
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/resume/MediaResumeListener.kt b/packages/SystemUI/src/com/android/systemui/media/controls/resume/MediaResumeListener.kt
index 2d10b823f784..92e0c851a462 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/resume/MediaResumeListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/resume/MediaResumeListener.kt
@@ -37,6 +37,7 @@ import com.android.systemui.dump.DumpManager
import com.android.systemui.media.controls.models.player.MediaData
import com.android.systemui.media.controls.pipeline.MediaDataManager
import com.android.systemui.media.controls.pipeline.RESUME_MEDIA_TIMEOUT
+import com.android.systemui.media.controls.util.MediaFlags
import com.android.systemui.settings.UserTracker
import com.android.systemui.tuner.TunerService
import com.android.systemui.util.Utils
@@ -63,7 +64,8 @@ constructor(
private val tunerService: TunerService,
private val mediaBrowserFactory: ResumeMediaBrowserFactory,
dumpManager: DumpManager,
- private val systemClock: SystemClock
+ private val systemClock: SystemClock,
+ private val mediaFlags: MediaFlags,
) : MediaDataManager.Listener, Dumpable {
private var useMediaResumption: Boolean = Utils.useMediaResumption(context)
@@ -231,7 +233,11 @@ constructor(
mediaBrowser = null
}
// If we don't have a resume action, check if we haven't already
- if (data.resumeAction == null && !data.hasCheckedForResume && data.isLocalSession()) {
+ val isEligibleForResume =
+ data.isLocalSession() ||
+ (mediaFlags.isRemoteResumeAllowed() &&
+ data.playbackLocation != MediaData.PLAYBACK_CAST_REMOTE)
+ if (data.resumeAction == null && !data.hasCheckedForResume && isEligibleForResume) {
// TODO also check for a media button receiver intended for restarting (b/154127084)
Log.d(TAG, "Checking for service component for " + data.packageName)
val pm = context.packageManager
@@ -291,6 +297,7 @@ constructor(
/**
* Add the component to the saved list of media browser services, checking for duplicates and
* removing older components that exceed the maximum limit
+ *
* @param componentName
*/
private fun updateResumptionList(componentName: ComponentName) {
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowserLogger.kt b/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowserLogger.kt
index 335ce1d3d694..095cf09a6c2c 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowserLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowserLogger.kt
@@ -52,10 +52,12 @@ class ResumeMediaBrowserLogger @Inject constructor(@MediaBrowserLog private val
* event.
*
* @param isBrowserConnected true if there's a currently connected
+ *
* ```
* [android.media.browse.MediaBrowser] and false otherwise.
* @param componentName
* ```
+ *
* the component name for the [ResumeMediaBrowser] that triggered this log.
*/
fun logSessionDestroyed(isBrowserConnected: Boolean, componentName: ComponentName) =
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/AnimationBindHandler.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/AnimationBindHandler.kt
index d2793bca867b..f5cc04331f94 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/AnimationBindHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/AnimationBindHandler.kt
@@ -24,10 +24,12 @@ import android.graphics.drawable.Drawable
* and conflicts due to media notifications arriving at any time during an animation. It does this
* in two parts.
* - Exit animations fired as a result of user input are tracked. When these are running, any
+ *
* ```
* bind actions are delayed until the animation completes (and then fired in sequence).
* ```
* - Continuous animations are tracked using their rebind id. Later calls using the same
+ *
* ```
* rebind id will be totally ignored to prevent the continuous animation from restarting.
* ```
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt
index 4827a16d229d..2b42604e7160 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt
@@ -201,7 +201,9 @@ internal constructor(
animatingColorTransitionFactory(
loadDefaultColor(R.attr.textColorSecondary),
::textSecondaryFromScheme
- ) { textSecondary -> mediaViewHolder.artistText.setTextColor(textSecondary) }
+ ) { textSecondary ->
+ mediaViewHolder.artistText.setTextColor(textSecondary)
+ }
val textTertiary =
animatingColorTransitionFactory(
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/IlluminationDrawable.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/IlluminationDrawable.kt
index 9f86cd88788b..3669493f4e41 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/IlluminationDrawable.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/IlluminationDrawable.kt
@@ -159,6 +159,7 @@ class IlluminationDrawable : Drawable() {
/**
* Cross fade background.
+ *
* @see setTintList
* @see backgroundColor
*/
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
index 68d2c5c5f4c4..680a8b6603d6 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
@@ -39,6 +39,7 @@ import com.android.systemui.Dumpable
import com.android.systemui.R
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dump.DumpManager
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
@@ -68,6 +69,7 @@ import com.android.systemui.util.time.SystemClock
import com.android.systemui.util.traceSection
import java.io.PrintWriter
import java.util.TreeMap
+import java.util.concurrent.Executor
import javax.inject.Inject
import javax.inject.Provider
import kotlinx.coroutines.CoroutineScope
@@ -93,7 +95,8 @@ constructor(
private val mediaHostStatesManager: MediaHostStatesManager,
private val activityStarter: ActivityStarter,
private val systemClock: SystemClock,
- @Main executor: DelayableExecutor,
+ @Main private val mainExecutor: DelayableExecutor,
+ @Background private val backgroundExecutor: Executor,
private val mediaManager: MediaDataManager,
configurationController: ConfigurationController,
falsingCollector: FalsingCollector,
@@ -256,7 +259,7 @@ constructor(
MediaCarouselScrollHandler(
mediaCarousel,
pageIndicator,
- executor,
+ mainExecutor,
this::onSwipeToDismiss,
this::updatePageIndicatorLocation,
this::updateSeekbarListening,
@@ -618,10 +621,50 @@ constructor(
MediaPlayerData.visiblePlayerKeys()
.elementAtOrNull(mediaCarouselScrollHandler.visibleMediaIndex)
if (existingPlayer == null) {
- val newPlayer = mediaControlPanelFactory.get()
- newPlayer.attachPlayer(
- MediaViewHolder.create(LayoutInflater.from(context), mediaContent)
+ setupNewPlayer(key, data, isSsReactivated, curVisibleMediaKey)
+ } else {
+ existingPlayer.bindPlayer(data, key)
+ MediaPlayerData.addMediaPlayer(
+ key,
+ data,
+ existingPlayer,
+ systemClock,
+ isSsReactivated,
+ debugLogger
)
+ val packageName = MediaPlayerData.smartspaceMediaData?.packageName ?: String()
+ // In case of recommendations hits.
+ // Check the playing status of media player and the package name.
+ // To make sure we scroll to the right app's media player.
+ if (
+ isReorderingAllowed ||
+ shouldScrollToKey &&
+ data.isPlaying == true &&
+ packageName == data.packageName
+ ) {
+ reorderAllPlayers(curVisibleMediaKey, key)
+ } else {
+ needsReordering = true
+ }
+ updatePageIndicator()
+ mediaCarouselScrollHandler.onPlayersChanged()
+ mediaFrame.requiresRemeasuring = true
+ }
+ return existingPlayer == null
+ }
+
+ private fun setupNewPlayer(
+ key: String,
+ data: MediaData,
+ isSsReactivated: Boolean,
+ curVisibleMediaKey: MediaPlayerData.MediaSortKey?,
+ ) {
+ backgroundExecutor.execute {
+ val mediaViewHolder = createMediaViewHolderInBg()
+ // Add the new player in the main thread.
+ mainExecutor.execute {
+ val newPlayer = mediaControlPanelFactory.get()
+ newPlayer.attachPlayer(mediaViewHolder)
newPlayer.mediaViewController.sizeChangedListener = this::updateCarouselDimensions
val lp =
LinearLayout.LayoutParams(
@@ -651,36 +694,16 @@ constructor(
} else {
needsReordering = true
}
- } else {
- existingPlayer.bindPlayer(data, key)
- MediaPlayerData.addMediaPlayer(
- key,
- data,
- existingPlayer,
- systemClock,
- isSsReactivated,
- debugLogger
- )
- val packageName = MediaPlayerData.smartspaceMediaData?.packageName ?: String()
- // In case of recommendations hits.
- // Check the playing status of media player and the package name.
- // To make sure we scroll to the right app's media player.
- if (
- isReorderingAllowed ||
- shouldScrollToKey &&
- data.isPlaying == true &&
- packageName == data.packageName
- ) {
- reorderAllPlayers(curVisibleMediaKey, key)
- } else {
- needsReordering = true
- }
+ updatePageIndicator()
+ mediaCarouselScrollHandler.onPlayersChanged()
+ mediaFrame.requiresRemeasuring = true
}
- updatePageIndicator()
- mediaCarouselScrollHandler.onPlayersChanged()
- mediaFrame.requiresRemeasuring = true
- return existingPlayer == null
}
+ }
+
+ private fun createMediaViewHolderInBg(): MediaViewHolder {
+ return MediaViewHolder.create(LayoutInflater.from(context), mediaContent)
+ }
private fun addSmartspaceMediaRecommendations(
key: String,
@@ -714,15 +737,14 @@ constructor(
debugLogger.logPotentialMemoryLeak(existingSmartspaceMediaKey)
}
}
-
val newRecs = mediaControlPanelFactory.get()
- newRecs.attachRecommendation(
+ val recommendationViewHolder =
RecommendationViewHolder.create(
LayoutInflater.from(context),
mediaContent,
mediaFlags.isRecommendationCardUpdateEnabled()
)
- )
+ newRecs.attachRecommendation(recommendationViewHolder)
newRecs.mediaViewController.sizeChangedListener = this::updateCarouselDimensions
val lp =
LinearLayout.LayoutParams(
@@ -746,17 +768,6 @@ constructor(
reorderAllPlayers(curVisibleMediaKey)
updatePageIndicator()
mediaFrame.requiresRemeasuring = true
- // Check postcondition: mediaContent should have the same number of children as there
- // are
- // elements in mediaPlayers.
- if (MediaPlayerData.players().size != mediaContent.childCount) {
- Log.e(
- TAG,
- "Size of players list and number of views in carousel are out of sync. " +
- "Players size is ${MediaPlayerData.players().size}. " +
- "View count is ${mediaContent.childCount}."
- )
- }
}
fun removePlayer(
@@ -842,10 +853,12 @@ constructor(
* @param startLocation the start location of our state or -1 if this is directly set
* @param endLocation the ending location of our state.
* @param progress the progress of the transition between startLocation and endlocation. If
+ *
* ```
* this is not a guided transformation, this will be 1.0f
* @param immediately
* ```
+ *
* should this state be applied immediately, canceling all animations?
*/
fun setCurrentState(
@@ -1089,17 +1102,17 @@ constructor(
*
* @param eventId UI event id (e.g. 800 for SMARTSPACE_CARD_SEEN)
* @param instanceId id to uniquely identify a card, e.g. each headphone generates a new
- * instanceId
+ * instanceId
* @param uid uid for the application that media comes from
* @param surfaces list of display surfaces the media card is on (e.g. lockscreen, shade) when
- * the event happened
+ * the event happened
* @param interactedSubcardRank the rank for interacted media item for recommendation card, -1
- * for tapping on card but not on any media item, 0 for first media item, 1 for second, etc.
+ * for tapping on card but not on any media item, 0 for first media item, 1 for second, etc.
* @param interactedSubcardCardinality how many media items were shown to the user when there is
- * user interaction
+ * user interaction
* @param rank the rank for media card in the media carousel, starting from 0
* @param receivedLatencyMillis latency in milliseconds for card received events. E.g. latency
- * between headphone connection to sysUI displays media recommendation card
+ * between headphone connection to sysUI displays media recommendation card
* @param isSwipeToDismiss whether is to log swipe-to-dismiss event
*/
fun logSmartspaceCardReported(
@@ -1360,6 +1373,7 @@ internal object MediaPlayerData {
/**
* Removes media player given the key.
+ *
* @param isDismissed determines whether the media player is removed from the carousel.
*/
fun removeMediaPlayer(key: String, isDismissed: Boolean = false) =
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
index 288266a36927..097cc3eef304 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
@@ -227,7 +227,7 @@ public class MediaControlPanel {
private final BroadcastDialogController mBroadcastDialogController;
private boolean mIsCurrentBroadcastedApp = false;
private boolean mShowBroadcastDialogButton = false;
- private String mSwitchBroadcastApp;
+ private String mCurrentBroadcastApp;
private MultiRippleController mMultiRippleController;
private TurbulenceNoiseController mTurbulenceNoiseController;
private final FeatureFlags mFeatureFlags;
@@ -573,9 +573,8 @@ public class MediaControlPanel {
// TODO(b/233698402): Use the package name instead of app label to avoid the
// unexpected result.
mIsCurrentBroadcastedApp = device != null
- && TextUtils.equals(device.getName(),
- MediaDataUtils.getAppLabel(mContext, mPackageName, mContext.getString(
- R.string.bt_le_audio_broadcast_dialog_unknown_name)));
+ && TextUtils.equals(device.getName(),
+ mContext.getString(R.string.broadcasting_description_is_broadcasting));
useDisabledAlpha = !mIsCurrentBroadcastedApp;
// Always be enabled if the broadcast button is shown
isTapEnabled = true;
@@ -630,8 +629,8 @@ public class MediaControlPanel {
// media output dialog.
if (!mIsCurrentBroadcastedApp) {
mLogger.logOpenBroadcastDialog(mUid, mPackageName, mInstanceId);
- mSwitchBroadcastApp = device.getName().toString();
- mBroadcastDialogController.createBroadcastDialog(mSwitchBroadcastApp,
+ mCurrentBroadcastApp = device.getName().toString();
+ mBroadcastDialogController.createBroadcastDialog(mCurrentBroadcastApp,
mPackageName, true, mMediaViewHolder.getSeamlessButton());
} else {
mLogger.logOpenOutputSwitcher(mUid, mPackageName, mInstanceId);
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt
index 66f12d6242b0..7fc7bdb872c9 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt
@@ -28,7 +28,6 @@ import android.net.Uri
import android.os.Handler
import android.os.UserHandle
import android.provider.Settings
-import android.util.Log
import android.util.MathUtils
import android.view.View
import android.view.ViewGroup
@@ -418,8 +417,8 @@ constructor(
* Calculate the alpha of the view when given a cross-fade progress.
*
* @param crossFadeProgress The current cross fade progress. 0.5f means it's just switching
- * between the start and the end location and the content is fully faded, while 0.75f means that
- * we're halfway faded in again in the target state.
+ * between the start and the end location and the content is fully faded, while 0.75f means
+ * that we're halfway faded in again in the target state.
*/
private fun calculateAlphaFromCrossFade(crossFadeProgress: Float): Float {
if (crossFadeProgress <= 0.5f) {
@@ -629,6 +628,7 @@ constructor(
*
* @param forceNoAnimation optional parameter telling the system not to animate
* @param forceStateUpdate optional parameter telling the system to update transition state
+ *
* ```
* even if location did not change
* ```
@@ -944,7 +944,7 @@ constructor(
/**
* @return the current transformation progress if we're in a guided transformation and -1
- * otherwise
+ * otherwise
*/
private fun getTransformationProgress(): Float {
if (skipQqsOnExpansion) {
@@ -1055,17 +1055,6 @@ constructor(
// This will either do a full layout pass and remeasure, or it will bypass
// that and directly set the mediaFrame's bounds within the premeasured host.
targetHost.addView(mediaFrame)
-
- if (mediaFrame.childCount > 0) {
- val child = mediaFrame.getChildAt(0)
- if (mediaFrame.height < child.height) {
- Log.wtf(
- TAG,
- "mediaFrame height is too small for child: " +
- "${mediaFrame.height} vs ${child.height}"
- )
- }
- }
}
if (isCrossFadeAnimatorRunning) {
// When cross-fading with an animation, we only notify the media carousel of the
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt
index 455b7de3dc0c..be570b4a1119 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt
@@ -126,6 +126,7 @@ constructor(
* remeasurings later on.
*
* @param location the location this host name has. Used to identify the host during
+ *
* ```
* transitions.
* ```
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt
index b9b0459ad615..0788e6172a78 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt
@@ -348,14 +348,17 @@ constructor(
* bottom of UMO reach the bottom of this group It will change to alpha 1.0 when the visible
* bottom of UMO reach the top of the group below e.g.Album title, artist title and play-pause
* button will change alpha together.
+ *
* ```
* And their alpha becomes 1.0 when the visible bottom of UMO reach the top of controls,
* including progress bar, next button, previous button
* ```
+ *
* widgetGroupIds: a group of widgets have same state during UMO is squished,
* ```
* e.g. Album title, artist title and play-pause button
* ```
+ *
* groupEndPosition: the height of UMO, when the height reaches this value,
* ```
* widgets in this group should have 1.0 as alpha
@@ -363,6 +366,7 @@ constructor(
* visible when the height of UMO reaches the top of controls group
* (progress bar, previous button and next button)
* ```
+ *
* squishedViewState: hold the widgetState of each widget, which will be modified
* squishFraction: the squishFraction of UMO
*/
@@ -665,7 +669,7 @@ constructor(
*
* @param location Target
* @param locationWhenHidden Location that will be used when the target is not
- * [MediaHost.visible]
+ * [MediaHost.visible]
* @return State require for executing a transition, and also the respective [MediaHost].
*/
private fun obtainViewStateForLocation(@MediaLocation location: Int): TransitionViewState? {
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
index c3fa76ec9433..9bc66f6c98d0 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
@@ -61,4 +61,7 @@ class MediaFlags @Inject constructor(private val featureFlags: FeatureFlags) {
/** If true, do not automatically dismiss the recommendation card */
fun isPersistentSsCardEnabled() = featureFlags.isEnabled(Flags.MEDIA_RETAIN_RECOMMENDATIONS)
+
+ /** Check whether we allow remote media to generate resume controls */
+ fun isRemoteResumeAllowed() = featureFlags.isEnabled(Flags.MEDIA_REMOTE_RESUME)
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSwitcherDialogUI.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSwitcherDialogUI.java
index e35575bfc184..b5b1f0ffe23d 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSwitcherDialogUI.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSwitcherDialogUI.java
@@ -23,8 +23,6 @@ import android.util.Log;
import com.android.systemui.CoreStartable;
import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.statusbar.CommandQueue;
import javax.inject.Inject;
@@ -37,26 +35,19 @@ public class MediaOutputSwitcherDialogUI implements CoreStartable, CommandQueue.
private final CommandQueue mCommandQueue;
private final MediaOutputDialogFactory mMediaOutputDialogFactory;
- private final FeatureFlags mFeatureFlags;
@Inject
public MediaOutputSwitcherDialogUI(
Context context,
CommandQueue commandQueue,
- MediaOutputDialogFactory mediaOutputDialogFactory,
- FeatureFlags featureFlags) {
+ MediaOutputDialogFactory mediaOutputDialogFactory) {
mCommandQueue = commandQueue;
mMediaOutputDialogFactory = mediaOutputDialogFactory;
- mFeatureFlags = featureFlags;
}
@Override
public void start() {
- if (mFeatureFlags.isEnabled(Flags.OUTPUT_SWITCHER_SHOW_API_ENABLED)) {
- mCommandQueue.addCallback(this);
- } else {
- Log.w(TAG, "Show media output switcher is not enabled.");
- }
+ mCommandQueue.addCallback(this);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt
index 720c44a0904b..ee93c3788243 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt
@@ -43,7 +43,7 @@ class MediaTttUtils {
*
* @param appPackageName the package name of the app playing the media.
* @param onPackageNotFoundException a function run if a
- * [PackageManager.NameNotFoundException] occurs.
+ * [PackageManager.NameNotFoundException] occurs.
* @param isReceiver indicates whether the icon is displayed in a receiver view.
*/
fun getIconInfoFromPackageName(
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt
index 7a77c476aa11..01398cf81314 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt
@@ -70,6 +70,8 @@ constructor(
RECENT_IGNORE_UNAVAILABLE,
userTracker.userId,
backgroundExecutor
- ) { tasks -> continuation.resume(tasks) }
+ ) { tasks ->
+ continuation.resume(tasks)
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionTaskView.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionTaskView.kt
index d4991f90a86b..9b9d561b5180 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionTaskView.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionTaskView.kt
@@ -33,7 +33,7 @@ import com.android.systemui.R
import com.android.systemui.mediaprojection.appselector.data.RecentTask
import com.android.systemui.shared.recents.model.ThumbnailData
import com.android.systemui.shared.recents.utilities.PreviewPositionHelper
-import com.android.systemui.shared.recents.utilities.Utilities.isTablet
+import com.android.systemui.shared.recents.utilities.Utilities.isLargeScreen
/**
* Custom view that shows a thumbnail preview of one recent task based on [ThumbnailData].
@@ -150,9 +150,9 @@ constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
val displayWidthPx = windowMetrics.bounds.width()
val displayHeightPx = windowMetrics.bounds.height()
val isRtl = layoutDirection == LAYOUT_DIRECTION_RTL
- val isTablet = isTablet(context)
+ val isLargeScreen = isLargeScreen(context)
val taskbarSize =
- if (isTablet) {
+ if (isLargeScreen) {
resources.getDimensionPixelSize(AndroidR.dimen.taskbar_frame_height)
} else {
0
@@ -166,7 +166,7 @@ constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
displayWidthPx,
displayHeightPx,
taskbarSize,
- isTablet,
+ isLargeScreen,
currentRotation,
isRtl
)
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProvider.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProvider.kt
index 88d5eaaff216..1c901540ed39 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProvider.kt
@@ -23,7 +23,7 @@ import android.view.WindowManager
import com.android.internal.R as AndroidR
import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorScope
import com.android.systemui.mediaprojection.appselector.view.TaskPreviewSizeProvider.TaskPreviewSizeListener
-import com.android.systemui.shared.recents.utilities.Utilities.isTablet
+import com.android.systemui.shared.recents.utilities.Utilities.isLargeScreen
import com.android.systemui.statusbar.policy.CallbackController
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener
@@ -61,8 +61,8 @@ constructor(
val width = windowMetrics.bounds.width()
var height = maximumWindowHeight
- val isTablet = isTablet(context)
- if (isTablet) {
+ val isLargeScreen = isLargeScreen(context)
+ if (isLargeScreen) {
val taskbarSize =
context.resources.getDimensionPixelSize(AndroidR.dimen.taskbar_frame_height)
height -= taskbarSize
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index d5d73258bb08..a233cdc156f8 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -41,7 +41,7 @@ import static com.android.internal.accessibility.common.ShortcutConstants.CHOOSE
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.HOME_BUTTON_LONG_PRESS_DURATION_MS;
import static com.android.systemui.navigationbar.NavBarHelper.transitionMode;
import static com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
-import static com.android.systemui.shared.recents.utilities.Utilities.isTablet;
+import static com.android.systemui.shared.recents.utilities.Utilities.isLargeScreen;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY;
@@ -164,6 +164,8 @@ import com.android.systemui.util.ViewController;
import com.android.wm.shell.back.BackAnimation;
import com.android.wm.shell.pip.Pip;
+import dagger.Lazy;
+
import java.io.PrintWriter;
import java.util.Locale;
import java.util.Map;
@@ -173,8 +175,6 @@ import java.util.function.Consumer;
import javax.inject.Inject;
-import dagger.Lazy;
-
/**
* Contains logic for a navigation bar view.
*/
@@ -251,12 +251,6 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
private boolean mTransientShown;
private boolean mTransientShownFromGestureOnSystemBar;
- /**
- * This is to indicate whether the navigation bar button is forced visible. This is true
- * when the setup wizard is on display. When that happens, the window frame should be provided
- * as insets size directly.
- */
- private boolean mIsButtonForceVisible;
private int mNavBarMode = NAV_BAR_MODE_3BUTTON;
private LightBarController mLightBarController;
private final LightBarController mMainLightBarController;
@@ -670,8 +664,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
mView.setTouchHandler(mTouchHandler);
setNavBarMode(mNavBarMode);
mEdgeBackGestureHandler.setStateChangeCallback(mView::updateStates);
- mEdgeBackGestureHandler.setButtonForceVisibleChangeCallback((forceVisible) -> {
- mIsButtonForceVisible = forceVisible;
+ mEdgeBackGestureHandler.setButtonForcedVisibleChangeCallback((forceVisible) -> {
repositionNavigationBar(mCurrentRotation);
});
mNavigationBarTransitions.addListener(this::onBarTransition);
@@ -1007,7 +1000,11 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
private void notifyNavigationBarSurface() {
ViewRootImpl viewRoot = mView.getViewRootImpl();
- SurfaceControl surface = viewRoot != null ? viewRoot.getSurfaceControl() : null;
+ SurfaceControl surface = viewRoot != null
+ && viewRoot.getSurfaceControl() != null
+ && viewRoot.getSurfaceControl().isValid()
+ ? viewRoot.getSurfaceControl()
+ : null;
mOverviewProxyService.onNavigationBarSurfaceChanged(surface);
}
@@ -1706,7 +1703,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
private InsetsFrameProvider[] getInsetsFrameProvider(int insetsHeight, Context userContext) {
final InsetsFrameProvider navBarProvider;
- if (insetsHeight != -1 && !mIsButtonForceVisible) {
+ if (insetsHeight != -1 && !mEdgeBackGestureHandler.isButtonForcedVisible()) {
navBarProvider = new InsetsFrameProvider(
ITYPE_NAVIGATION_BAR, Insets.of(0, 0, 0, insetsHeight));
// Use window frame for IME.
@@ -1729,41 +1726,26 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
bottomTappableProvider = new InsetsFrameProvider(ITYPE_BOTTOM_TAPPABLE_ELEMENT);
}
- if (!mEdgeBackGestureHandler.isHandlingGestures()) {
- // 2/3 button navigation is on. Do not provide any gesture insets here. But need to keep
- // the provider to support runtime update.
- return new InsetsFrameProvider[] {
- navBarProvider,
- new InsetsFrameProvider(
- ITYPE_BOTTOM_MANDATORY_GESTURES, Insets.NONE),
- new InsetsFrameProvider(ITYPE_LEFT_GESTURES, InsetsFrameProvider.SOURCE_DISPLAY,
- Insets.NONE, null),
- new InsetsFrameProvider(ITYPE_RIGHT_GESTURES,
- InsetsFrameProvider.SOURCE_DISPLAY,
- Insets.NONE, null),
- bottomTappableProvider
- };
- } else {
- // Gesture navigation
- final int gestureHeight = userContext.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.navigation_bar_gesture_height);
- final DisplayCutout cutout = userContext.getDisplay().getCutout();
- final int safeInsetsLeft = cutout != null ? cutout.getSafeInsetLeft() : 0;
- final int safeInsetsRight = cutout != null ? cutout.getSafeInsetRight() : 0;
- return new InsetsFrameProvider[] {
- navBarProvider,
- new InsetsFrameProvider(
- ITYPE_BOTTOM_MANDATORY_GESTURES, Insets.of(0, 0, 0, gestureHeight)),
- new InsetsFrameProvider(ITYPE_LEFT_GESTURES, InsetsFrameProvider.SOURCE_DISPLAY,
- Insets.of(safeInsetsLeft
- + mEdgeBackGestureHandler.getEdgeWidthLeft(), 0, 0, 0), null),
- new InsetsFrameProvider(ITYPE_RIGHT_GESTURES,
- InsetsFrameProvider.SOURCE_DISPLAY,
- Insets.of(0, 0, safeInsetsRight
- + mEdgeBackGestureHandler.getEdgeWidthRight(), 0), null),
- bottomTappableProvider
- };
- }
+ final DisplayCutout cutout = userContext.getDisplay().getCutout();
+ final int safeInsetsLeft = cutout != null ? cutout.getSafeInsetLeft() : 0;
+ final int safeInsetsRight = cutout != null ? cutout.getSafeInsetRight() : 0;
+ final int gestureHeight = userContext.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.navigation_bar_gesture_height);
+ final boolean handlingGesture = mEdgeBackGestureHandler.isHandlingGestures();
+ final int gestureInsetsLeft = handlingGesture
+ ? mEdgeBackGestureHandler.getEdgeWidthLeft() + safeInsetsLeft : 0;
+ final int gestureInsetsRight = handlingGesture
+ ? mEdgeBackGestureHandler.getEdgeWidthRight() + safeInsetsRight : 0;
+ return new InsetsFrameProvider[] {
+ navBarProvider,
+ new InsetsFrameProvider(
+ ITYPE_BOTTOM_MANDATORY_GESTURES, Insets.of(0, 0, 0, gestureHeight)),
+ new InsetsFrameProvider(ITYPE_LEFT_GESTURES, InsetsFrameProvider.SOURCE_DISPLAY,
+ Insets.of(gestureInsetsLeft, 0, 0, 0), null),
+ new InsetsFrameProvider(ITYPE_RIGHT_GESTURES, InsetsFrameProvider.SOURCE_DISPLAY,
+ Insets.of(0, 0, gestureInsetsRight, 0), null),
+ bottomTappableProvider
+ };
}
private boolean canShowSecondaryHandle() {
@@ -1792,7 +1774,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
private void setNavigationIconHints(int hints) {
if (hints == mNavigationIconHints) return;
- if (!isTablet(mContext)) {
+ if (!isLargeScreen(mContext)) {
// All IME functions handled by launcher via Sysui flags for large screen
final boolean newBackAlt = (hints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
final boolean oldBackAlt =
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
index 3c1746532a02..63d977ed33a7 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
@@ -21,7 +21,7 @@ import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_GESTURE
import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR;
import static com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler.DEBUG_MISSING_GESTURE_TAG;
-import static com.android.systemui.shared.recents.utilities.Utilities.isTablet;
+import static com.android.systemui.shared.recents.utilities.Utilities.isLargeScreen;
import android.content.Context;
import android.content.pm.ActivityInfo;
@@ -91,7 +91,7 @@ public class NavigationBarController implements
private final DisplayManager mDisplayManager;
private final TaskbarDelegate mTaskbarDelegate;
private int mNavMode;
- @VisibleForTesting boolean mIsTablet;
+ @VisibleForTesting boolean mIsLargeScreen;
/** A displayId - nav bar maps. */
@VisibleForTesting
@@ -138,16 +138,16 @@ public class NavigationBarController implements
navBarHelper, navigationModeController, sysUiFlagsContainer,
dumpManager, autoHideController, lightBarController, pipOptional,
backAnimation.orElse(null), taskStackChangeListeners);
- mIsTablet = isTablet(mContext);
+ mIsLargeScreen = isLargeScreen(mContext);
dumpManager.registerDumpable(this);
}
@Override
public void onConfigChanged(Configuration newConfig) {
- boolean isOldConfigTablet = mIsTablet;
- mIsTablet = isTablet(mContext);
+ boolean isOldConfigLargeScreen = mIsLargeScreen;
+ mIsLargeScreen = isLargeScreen(mContext);
boolean willApplyConfig = mConfigChanges.applyNewConfig(mContext.getResources());
- boolean largeScreenChanged = mIsTablet != isOldConfigTablet;
+ boolean largeScreenChanged = mIsLargeScreen != isOldConfigLargeScreen;
// TODO(b/243765256): Disable this logging once b/243765256 is fixed.
Log.i(DEBUG_MISSING_GESTURE_TAG, "NavbarController: newConfig=" + newConfig
+ " mTaskbarDelegate initialized=" + mTaskbarDelegate.isInitialized()
@@ -235,8 +235,9 @@ public class NavigationBarController implements
/** @return {@code true} if taskbar is enabled, false otherwise */
private boolean initializeTaskbarIfNecessary() {
- // Enable for tablet or (phone AND flag is set); assuming phone = !mIsTablet
- boolean taskbarEnabled = mIsTablet || mFeatureFlags.isEnabled(Flags.HIDE_NAVBAR_WINDOW);
+ // Enable for large screens or (phone AND flag is set); assuming phone = !mIsLargeScreen
+ boolean taskbarEnabled = mIsLargeScreen || mFeatureFlags.isEnabled(
+ Flags.HIDE_NAVBAR_WINDOW);
if (taskbarEnabled) {
Trace.beginSection("NavigationBarController#initializeTaskbarIfNecessary");
@@ -258,7 +259,7 @@ public class NavigationBarController implements
@Override
public void onDisplayReady(int displayId) {
Display display = mDisplayManager.getDisplay(displayId);
- mIsTablet = isTablet(mContext);
+ mIsLargeScreen = isLargeScreen(mContext);
createNavigationBar(display, null /* savedState */, null /* result */);
}
@@ -470,7 +471,7 @@ public class NavigationBarController implements
@Override
public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
- pw.println("mIsTablet=" + mIsTablet);
+ pw.println("mIsLargeScreen=" + mIsLargeScreen);
pw.println("mNavMode=" + mNavMode);
for (int i = 0; i < mNavigationBars.size(); i++) {
if (i > 0) {
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
index c3d736917b5d..27e99f7d9176 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
@@ -75,6 +75,7 @@ import com.android.systemui.statusbar.phone.AutoHideController;
import com.android.systemui.statusbar.phone.BarTransitions;
import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.phone.LightBarTransitionsController;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.wm.shell.back.BackAnimation;
import com.android.wm.shell.pip.Pip;
@@ -166,16 +167,20 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
private BackAnimation mBackAnimation;
+ private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
@Inject
public TaskbarDelegate(Context context,
EdgeBackGestureHandler.Factory edgeBackGestureHandlerFactory,
- LightBarTransitionsController.Factory lightBarTransitionsControllerFactory) {
+ LightBarTransitionsController.Factory lightBarTransitionsControllerFactory,
+ StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
mLightBarTransitionsControllerFactory = lightBarTransitionsControllerFactory;
mEdgeBackGestureHandler = edgeBackGestureHandlerFactory.create(context);
mContext = context;
mDisplayManager = mContext.getSystemService(DisplayManager.class);
mPipListener = mEdgeBackGestureHandler::setPipStashExclusionBounds;
+ mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
+ mStatusBarKeyguardViewManager.setTaskbarDelegate(this);
}
public void setDependencies(CommandQueue commandQueue,
@@ -431,6 +436,19 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
}
}
+ @Override
+ public void toggleTaskbar() {
+ if (mOverviewProxyService.getProxy() == null) {
+ return;
+ }
+
+ try {
+ mOverviewProxyService.getProxy().onTaskbarToggled();
+ } catch (RemoteException e) {
+ Log.e(TAG, "onTaskbarToggled() failed", e);
+ }
+ }
+
private void clearTransient() {
if (mTaskbarTransientShowing) {
mTaskbarTransientShowing = false;
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index 389034af8a33..163b6fa816aa 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -28,6 +28,7 @@ import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.graphics.Insets;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.PointF;
@@ -54,6 +55,7 @@ import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.ViewConfiguration;
+import android.view.WindowInsets;
import android.view.WindowManager;
import android.window.BackEvent;
@@ -176,7 +178,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
private final OverviewProxyService mOverviewProxyService;
private final SysUiState mSysUiState;
private Runnable mStateChangeCallback;
- private Consumer<Boolean> mButtonForceVisibleCallback;
+ private Consumer<Boolean> mButtonForcedVisibleCallback;
private final PluginManager mPluginManager;
private final ProtoTracer mProtoTracer;
@@ -234,6 +236,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
private boolean mLogGesture = false;
private boolean mInRejectedExclusion = false;
private boolean mIsOnLeftEdge;
+ private boolean mDeferSetIsOnLeftEdge;
private boolean mIsAttached;
private boolean mIsGesturalModeEnabled;
@@ -243,7 +246,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
private boolean mGestureBlockingActivityRunning;
private boolean mIsNewBackAffordanceEnabled;
private boolean mIsTrackpadGestureBackEnabled;
- private boolean mIsButtonForceVisible;
+ private boolean mIsButtonForcedVisible;
private InputMonitor mInputMonitor;
private InputChannelCompat.InputEventReceiver mInputEventReceiver;
@@ -410,8 +413,8 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
mStateChangeCallback = callback;
}
- public void setButtonForceVisibleChangeCallback(Consumer<Boolean> callback) {
- mButtonForceVisibleCallback = callback;
+ public void setButtonForcedVisibleChangeCallback(Consumer<Boolean> callback) {
+ mButtonForcedVisibleCallback = callback;
}
public int getEdgeWidthLeft() {
@@ -426,13 +429,14 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
Resources res = mNavigationModeController.getCurrentUserContext().getResources();
mEdgeWidthLeft = mGestureNavigationSettingsObserver.getLeftSensitivity(res);
mEdgeWidthRight = mGestureNavigationSettingsObserver.getRightSensitivity(res);
- final boolean previousForceVisible = mIsButtonForceVisible;
- mIsButtonForceVisible =
+ final boolean previousForcedVisible = mIsButtonForcedVisible;
+ mIsButtonForcedVisible =
mGestureNavigationSettingsObserver.areNavigationButtonForcedVisible();
- if (previousForceVisible != mIsButtonForceVisible && mButtonForceVisibleCallback != null) {
- mButtonForceVisibleCallback.accept(mIsButtonForceVisible);
+ if (previousForcedVisible != mIsButtonForcedVisible
+ && mButtonForcedVisibleCallback != null) {
+ mButtonForcedVisibleCallback.accept(mIsButtonForcedVisible);
}
- mIsBackGestureAllowed = !mIsButtonForceVisible;
+ mIsBackGestureAllowed = !mIsButtonForcedVisible;
final DisplayMetrics dm = res.getDisplayMetrics();
final float defaultGestureHeight = res.getDimension(
@@ -580,7 +584,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
}
// Register input event receiver
- mInputMonitor = InputManager.getInstance().monitorGestureInput(
+ mInputMonitor = mContext.getSystemService(InputManager.class).monitorGestureInput(
"edge-swipe", mDisplayId);
mInputEventReceiver = new InputChannelCompat.InputEventReceiver(
mInputMonitor.getInputChannel(), Looper.getMainLooper(),
@@ -632,6 +636,10 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
return mIsEnabled && mIsBackGestureAllowed;
}
+ public boolean isButtonForcedVisible() {
+ return mIsButtonForcedVisible;
+ }
+
/**
* Update the PiP bounds, used for exclusion calculation.
*/
@@ -775,6 +783,19 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
return true;
}
+ private boolean isValidTrackpadBackGesture(boolean isTrackpadEvent) {
+ if (!isTrackpadEvent) {
+ return false;
+ }
+ // for trackpad gestures, unless the whole screen is excluded region, 3-finger swipe
+ // gestures are allowed even if the cursor is in the excluded region.
+ WindowInsets windowInsets = mWindowManager.getCurrentWindowMetrics().getWindowInsets();
+ Insets insets = windowInsets.getInsets(WindowInsets.Type.systemBars());
+ final Rect excludeBounds = mExcludeRegion.getBounds();
+ return !excludeBounds.contains(insets.left, insets.top, mDisplaySize.x - insets.right,
+ mDisplaySize.y - insets.bottom);
+ }
+
private boolean isWithinTouchRegion(int x, int y) {
// If the point is inside the PiP or Nav bar overlay excluded bounds, then ignore the back
// gesture
@@ -878,7 +899,9 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
// either the bouncer is showing or the notification panel is hidden
mInputEventReceiver.setBatchingEnabled(false);
if (isTrackpadEvent) {
- // TODO: show the back arrow based on the direction of the swipe.
+ // Since trackpad gestures don't have zones, this will be determined later by the
+ // direction of the gesture. {@code mIsOnLeftEdge} is set to false to begin with.
+ mDeferSetIsOnLeftEdge = true;
mIsOnLeftEdge = false;
} else {
mIsOnLeftEdge = ev.getX() <= mEdgeWidthLeft + mLeftInset;
@@ -893,13 +916,14 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
&& (isTrackpadEvent || isWithinInsets)
&& !mGestureBlockingActivityRunning
&& !QuickStepContract.isBackGestureDisabled(mSysUiFlags)
- && (isTrackpadEvent || isWithinTouchRegion((int) ev.getX(), (int) ev.getY()));
+ && (isValidTrackpadBackGesture(isTrackpadEvent) || isWithinTouchRegion(
+ (int) ev.getX(), (int) ev.getY()));
if (mAllowGesture) {
mEdgeBackPlugin.setIsLeftPanel(mIsOnLeftEdge);
mEdgeBackPlugin.onMotionEvent(ev);
dispatchToBackAnimation(ev);
}
- if (mLogGesture) {
+ if (mLogGesture || isTrackpadEvent) {
mDownPoint.set(ev.getX(), ev.getY());
mEndPoint.set(-1, -1);
mThresholdCrossed = false;
@@ -907,9 +931,9 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
// For debugging purposes, only log edge points
(isWithinInsets ? mGestureLogInsideInsets : mGestureLogOutsideInsets).log(String.format(
- "Gesture [%d,alw=%B,%B,%B,%B,%B,disp=%s,wl=%d,il=%d,wr=%d,ir=%d,excl=%s]",
+ "Gesture [%d,alw=%B,%B,%B,%B,%B,%B,disp=%s,wl=%d,il=%d,wr=%d,ir=%d,excl=%s]",
System.currentTimeMillis(), isTrackpadEvent, mAllowGesture, mIsOnLeftEdge,
- mIsBackGestureAllowed,
+ mDeferSetIsOnLeftEdge, mIsBackGestureAllowed,
QuickStepContract.isBackGestureDisabled(mSysUiFlags), mDisplaySize,
mEdgeWidthLeft, mLeftInset, mEdgeWidthRight, mRightInset, mExcludeRegion));
} else if (mAllowGesture || mLogGesture) {
@@ -928,6 +952,14 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
mLogGesture = false;
return;
} else if (action == MotionEvent.ACTION_MOVE) {
+ if (isTrackpadEvent && mDeferSetIsOnLeftEdge) {
+ // mIsOnLeftEdge is determined by the relative position between the down
+ // and the current motion event for trackpad gestures instead of zoning.
+ mIsOnLeftEdge = mEndPoint.x > mDownPoint.x;
+ mEdgeBackPlugin.setIsLeftPanel(mIsOnLeftEdge);
+ mDeferSetIsOnLeftEdge = false;
+ }
+
if ((ev.getEventTime() - ev.getDownTime()) > mLongPressTimeout) {
if (mAllowGesture) {
logGesture(SysUiStatsLog.BACK_GESTURE__TYPE__INCOMPLETE_LONG_PRESS);
@@ -1039,7 +1071,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
InputDevice.SOURCE_KEYBOARD);
ev.setDisplayId(mContext.getDisplay().getDisplayId());
- return InputManager.getInstance()
+ return mContext.getSystemService(InputManager.class)
.injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
index be615d63a3d7..c65f0aaab91f 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
@@ -17,20 +17,26 @@
package com.android.systemui.notetask
import android.app.KeyguardManager
+import android.app.admin.DevicePolicyManager
import android.content.ActivityNotFoundException
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
+import android.os.Build
import android.os.UserManager
import android.util.Log
-import com.android.internal.logging.UiEvent
-import com.android.internal.logging.UiEventLogger
+import androidx.annotation.VisibleForTesting
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.devicepolicy.areKeyguardShortcutsDisabled
import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity
+import com.android.systemui.settings.UserTracker
import com.android.systemui.util.kotlin.getOrNull
+import com.android.wm.shell.bubbles.Bubble
import com.android.wm.shell.bubbles.Bubbles
+import com.android.wm.shell.bubbles.Bubbles.BubbleExpandListener
import java.util.Optional
+import java.util.concurrent.atomic.AtomicReference
import javax.inject.Inject
/**
@@ -41,18 +47,42 @@ import javax.inject.Inject
* Currently, we only support a single task per time.
*/
@SysUISingleton
-internal class NoteTaskController
+class NoteTaskController
@Inject
constructor(
private val context: Context,
private val resolver: NoteTaskInfoResolver,
+ private val eventLogger: NoteTaskEventLogger,
private val optionalBubbles: Optional<Bubbles>,
- private val optionalKeyguardManager: Optional<KeyguardManager>,
private val optionalUserManager: Optional<UserManager>,
+ private val optionalKeyguardManager: Optional<KeyguardManager>,
@NoteTaskEnabledKey private val isEnabled: Boolean,
- private val uiEventLogger: UiEventLogger,
+ private val devicePolicyManager: DevicePolicyManager,
+ private val userTracker: UserTracker,
) {
+ @VisibleForTesting val infoReference = AtomicReference<NoteTaskInfo?>()
+
+ /** @see BubbleExpandListener */
+ fun onBubbleExpandChanged(isExpanding: Boolean, key: String?) {
+ if (!isEnabled) return
+
+ if (key != Bubble.KEY_APP_BUBBLE) return
+
+ val info = infoReference.getAndSet(null)
+
+ // Safe guard mechanism, this callback should only be called for app bubbles.
+ if (info?.launchMode != NoteTaskLaunchMode.AppBubble) return
+
+ if (isExpanding) {
+ logDebug { "onBubbleExpandChanged - expanding: $info" }
+ eventLogger.logNoteTaskOpened(info)
+ } else {
+ logDebug { "onBubbleExpandChanged - collapsing: $info" }
+ eventLogger.logNoteTaskClosed(info)
+ }
+ }
+
/**
* Shows a note task. How the task is shown will depend on when the method is invoked.
*
@@ -69,32 +99,62 @@ constructor(
* That will let users open other apps in full screen, and take contextual notes.
*/
@JvmOverloads
- fun showNoteTask(isInMultiWindowMode: Boolean = false, uiEvent: ShowNoteTaskUiEvent? = null) {
-
+ fun showNoteTask(
+ entryPoint: NoteTaskEntryPoint,
+ isInMultiWindowMode: Boolean = false,
+ ) {
if (!isEnabled) return
val bubbles = optionalBubbles.getOrNull() ?: return
- val keyguardManager = optionalKeyguardManager.getOrNull() ?: return
val userManager = optionalUserManager.getOrNull() ?: return
+ val keyguardManager = optionalKeyguardManager.getOrNull() ?: return
// TODO(b/249954038): We should handle direct boot (isUserUnlocked). For now, we do nothing.
if (!userManager.isUserUnlocked) return
- val noteTaskInfo = resolver.resolveInfo() ?: return
+ val isKeyguardLocked = keyguardManager.isKeyguardLocked
+ // KeyguardQuickAffordanceInteractor blocks the quick affordance from showing in the
+ // keyguard if it is not allowed by the admin policy. Here we block any other way to show
+ // note task when the screen is locked.
+ if (
+ isKeyguardLocked &&
+ devicePolicyManager.areKeyguardShortcutsDisabled(userId = userTracker.userId)
+ ) {
+ logDebug { "Enterprise policy disallows launching note app when the screen is locked." }
+ return
+ }
+
+ val info =
+ resolver.resolveInfo(
+ entryPoint = entryPoint,
+ isInMultiWindowMode = isInMultiWindowMode,
+ isKeyguardLocked = isKeyguardLocked,
+ )
+ ?: return
- uiEvent?.let { uiEventLogger.log(it, noteTaskInfo.uid, noteTaskInfo.packageName) }
+ infoReference.set(info)
// TODO(b/266686199): We should handle when app not available. For now, we log.
- val intent = noteTaskInfo.toCreateNoteIntent()
+ val intent = createNoteIntent(info)
try {
- if (isInMultiWindowMode || keyguardManager.isKeyguardLocked) {
- context.startActivity(intent)
- } else {
- bubbles.showOrHideAppBubble(intent)
+ logDebug { "onShowNoteTask - start: $info" }
+ when (info.launchMode) {
+ is NoteTaskLaunchMode.AppBubble -> {
+ bubbles.showOrHideAppBubble(intent)
+ // App bubble logging happens on `onBubbleExpandChanged`.
+ logDebug { "onShowNoteTask - opened as app bubble: $info" }
+ }
+ is NoteTaskLaunchMode.Activity -> {
+ context.startActivity(intent)
+ eventLogger.logNoteTaskOpened(info)
+ logDebug { "onShowNoteTask - opened as activity: $info" }
+ }
}
+ logDebug { "onShowNoteTask - success: $info" }
} catch (e: ActivityNotFoundException) {
- Log.e(TAG, "Activity not found for action: $ACTION_CREATE_NOTE.", e)
+ logDebug { "onShowNoteTask - failed: $info" }
}
+ logDebug { "onShowNoteTask - compoleted: $info" }
}
/**
@@ -119,41 +179,12 @@ constructor(
enabledState,
PackageManager.DONT_KILL_APP,
)
- }
-
- /** IDs of UI events accepted by [showNoteTask]. */
- enum class ShowNoteTaskUiEvent(private val _id: Int) : UiEventLogger.UiEventEnum {
- @UiEvent(doc = "User opened a note by tapping on the lockscreen shortcut.")
- NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE(1294),
- /* ktlint-disable max-line-length */
- @UiEvent(
- doc =
- "User opened a note by pressing the stylus tail button while the screen was unlocked."
- )
- NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON(1295),
- @UiEvent(
- doc =
- "User opened a note by pressing the stylus tail button while the screen was locked."
- )
- NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON_LOCKED(1296),
- @UiEvent(doc = "User opened a note by tapping on an app shortcut.")
- NOTE_OPENED_VIA_SHORTCUT(1297);
-
- override fun getId() = _id
+ logDebug { "setNoteTaskShortcutEnabled - completed: $isEnabled" }
}
companion object {
- private val TAG = NoteTaskController::class.simpleName.orEmpty()
-
- private fun NoteTaskInfoResolver.NoteTaskInfo.toCreateNoteIntent(): Intent {
- return Intent(ACTION_CREATE_NOTE)
- .setPackage(packageName)
- .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- // EXTRA_USE_STYLUS_MODE does not mean a stylus is in-use, but a stylus entrypoint
- // was used to start it.
- .putExtra(INTENT_EXTRA_USE_STYLUS_MODE, true)
- }
+ val TAG = NoteTaskController::class.simpleName.orEmpty()
// TODO(b/254604589): Use final KeyEvent.KEYCODE_* instead.
const val NOTE_TASK_KEY_EVENT = 311
@@ -165,3 +196,17 @@ constructor(
const val INTENT_EXTRA_USE_STYLUS_MODE = "android.intent.extra.USE_STYLUS_MODE"
}
}
+
+private fun createNoteIntent(info: NoteTaskInfo): Intent =
+ Intent(NoteTaskController.ACTION_CREATE_NOTE)
+ .setPackage(info.packageName)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ // EXTRA_USE_STYLUS_MODE does not mean a stylus is in-use, but a stylus entrypoint
+ // was used to start it.
+ .putExtra(NoteTaskController.INTENT_EXTRA_USE_STYLUS_MODE, true)
+
+private inline fun logDebug(message: () -> String) {
+ if (Build.IS_DEBUGGABLE) {
+ Log.d(NoteTaskController.TAG, message())
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEnabledKey.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEnabledKey.kt
index e0bf1da2f652..a2563919955a 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEnabledKey.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEnabledKey.kt
@@ -19,4 +19,4 @@ package com.android.systemui.notetask
import javax.inject.Qualifier
/** Key associated with a [Boolean] flag that enables or disables the note task feature. */
-@Qualifier internal annotation class NoteTaskEnabledKey
+@Qualifier annotation class NoteTaskEnabledKey
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEntryPoint.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEntryPoint.kt
new file mode 100644
index 000000000000..acc537a8eb36
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEntryPoint.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2023 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.notetask
+
+import com.android.systemui.notetask.quickaffordance.NoteTaskQuickAffordanceConfig
+import com.android.systemui.notetask.shortcut.LaunchNoteTaskActivity
+import com.android.systemui.screenshot.AppClipsTrampolineActivity
+
+/**
+ * Supported entry points for [NoteTaskController.showNoteTask].
+ *
+ * An entry point represents where the note task has ben called from. In rare cases, it may
+ * represent a "re-entry" (i.e., [APP_CLIPS]).
+ */
+enum class NoteTaskEntryPoint {
+
+ /** @see [LaunchNoteTaskActivity] */
+ WIDGET_PICKER_SHORTCUT,
+
+ /** @see [NoteTaskQuickAffordanceConfig] */
+ QUICK_AFFORDANCE,
+
+ /** @see [NoteTaskInitializer.callbacks] */
+ TAIL_BUTTON,
+
+ /** @see [AppClipsTrampolineActivity] */
+ APP_CLIPS,
+}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEventLogger.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEventLogger.kt
new file mode 100644
index 000000000000..16dd16ee137e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEventLogger.kt
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2023 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.notetask
+
+import com.android.internal.logging.UiEvent
+import com.android.internal.logging.UiEventLogger
+import com.android.systemui.notetask.NoteTaskEntryPoint.APP_CLIPS
+import com.android.systemui.notetask.NoteTaskEntryPoint.QUICK_AFFORDANCE
+import com.android.systemui.notetask.NoteTaskEntryPoint.TAIL_BUTTON
+import com.android.systemui.notetask.NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT
+import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE
+import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_OPENED_VIA_SHORTCUT
+import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON
+import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON_LOCKED
+import javax.inject.Inject
+
+/**
+ * A wrapper around [UiEventLogger] specialized in the note taking UI events.
+ *
+ * if the accepted [NoteTaskInfo] contains a [NoteTaskInfo.entryPoint], it will be logged as the
+ * correct [NoteTaskUiEvent]. If null, it will be ignored.
+ *
+ * @see NoteTaskController for usage examples.
+ */
+class NoteTaskEventLogger @Inject constructor(private val uiEventLogger: UiEventLogger) {
+
+ /** Logs a [NoteTaskInfo] as an **open** [NoteTaskUiEvent], including package name and uid. */
+ fun logNoteTaskOpened(info: NoteTaskInfo) {
+ val event =
+ when (info.entryPoint) {
+ TAIL_BUTTON -> {
+ if (info.isKeyguardLocked) {
+ NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON_LOCKED
+ } else {
+ NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON
+ }
+ }
+ WIDGET_PICKER_SHORTCUT -> NOTE_OPENED_VIA_SHORTCUT
+ QUICK_AFFORDANCE -> NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE
+ APP_CLIPS -> return
+ null -> return
+ }
+ uiEventLogger.log(event, info.uid, info.packageName)
+ }
+
+ /** Logs a [NoteTaskInfo] as a **closed** [NoteTaskUiEvent], including package name and uid. */
+ fun logNoteTaskClosed(info: NoteTaskInfo) {
+ val event =
+ when (info.entryPoint) {
+ TAIL_BUTTON -> {
+ if (info.isKeyguardLocked) {
+ NoteTaskUiEvent.NOTE_CLOSED_VIA_STYLUS_TAIL_BUTTON_LOCKED
+ } else {
+ NoteTaskUiEvent.NOTE_CLOSED_VIA_STYLUS_TAIL_BUTTON
+ }
+ }
+ WIDGET_PICKER_SHORTCUT -> return
+ QUICK_AFFORDANCE -> return
+ APP_CLIPS -> return
+ null -> return
+ }
+ uiEventLogger.log(event, info.uid, info.packageName)
+ }
+
+ /** IDs of UI events accepted by [NoteTaskController]. */
+ enum class NoteTaskUiEvent(private val _id: Int) : UiEventLogger.UiEventEnum {
+
+ @UiEvent(doc = "User opened a note by tapping on the lockscreen shortcut.")
+ NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE(1294),
+
+ @UiEvent(doc = "User opened a note by pressing the stylus tail button while the screen was unlocked.") // ktlint-disable max-line-length
+ NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON(1295),
+
+ @UiEvent(doc = "User opened a note by pressing the stylus tail button while the screen was locked.") // ktlint-disable max-line-length
+ NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON_LOCKED(1296),
+
+ @UiEvent(doc = "User opened a note by tapping on an app shortcut.")
+ NOTE_OPENED_VIA_SHORTCUT(1297),
+
+ @UiEvent(doc = "Note closed via a tail button while device is unlocked")
+ NOTE_CLOSED_VIA_STYLUS_TAIL_BUTTON(1311),
+
+ @UiEvent(doc = "Note closed via a tail button while device is locked")
+ NOTE_CLOSED_VIA_STYLUS_TAIL_BUTTON_LOCKED(1312);
+
+ override fun getId() = _id
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfo.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfo.kt
new file mode 100644
index 000000000000..28d76474efba
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfo.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2023 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.notetask
+
+/** Contextual information required to launch a Note Task by [NoteTaskController]. */
+data class NoteTaskInfo(
+ val packageName: String,
+ val uid: Int,
+ val entryPoint: NoteTaskEntryPoint? = null,
+ val isInMultiWindowMode: Boolean = false,
+ val isKeyguardLocked: Boolean = false,
+) {
+
+ val launchMode: NoteTaskLaunchMode =
+ if (isInMultiWindowMode || isKeyguardLocked) {
+ NoteTaskLaunchMode.Activity
+ } else {
+ NoteTaskLaunchMode.AppBubble
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfoResolver.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfoResolver.kt
index bd822d40b950..0f75f9591074 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfoResolver.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfoResolver.kt
@@ -19,51 +19,58 @@ package com.android.systemui.notetask
import android.app.role.RoleManager
import android.content.Context
import android.content.pm.PackageManager
+import android.content.pm.PackageManager.ApplicationInfoFlags
import android.os.UserHandle
import android.util.Log
import javax.inject.Inject
-internal class NoteTaskInfoResolver
+class NoteTaskInfoResolver
@Inject
constructor(
private val context: Context,
private val roleManager: RoleManager,
private val packageManager: PackageManager,
) {
- fun resolveInfo(): NoteTaskInfo? {
+
+ fun resolveInfo(
+ entryPoint: NoteTaskEntryPoint? = null,
+ isInMultiWindowMode: Boolean = false,
+ isKeyguardLocked: Boolean = false,
+ ): NoteTaskInfo? {
// TODO(b/267634412): Select UserHandle depending on where the user initiated note-taking.
val user = context.user
- val packageName = roleManager.getRoleHoldersAsUser(ROLE_NOTES, user).firstOrNull()
+ val packageName =
+ roleManager.getRoleHoldersAsUser(RoleManager.ROLE_NOTES, user).firstOrNull()
if (packageName.isNullOrEmpty()) return null
- return NoteTaskInfo(packageName, packageManager.getUidOf(packageName, user))
+ return NoteTaskInfo(
+ packageName = packageName,
+ uid = packageManager.getUidOf(packageName, user),
+ entryPoint = entryPoint,
+ isInMultiWindowMode = isInMultiWindowMode,
+ isKeyguardLocked = isKeyguardLocked,
+ )
}
- /** Package name and kernel user-ID of a note-taking app. */
- data class NoteTaskInfo(val packageName: String, val uid: Int)
-
companion object {
private val TAG = NoteTaskInfoResolver::class.simpleName.orEmpty()
- private val EMPTY_APPLICATION_INFO_FLAGS = PackageManager.ApplicationInfoFlags.of(0)!!
+ // TODO(b/265912743): Use RoleManager.NOTES_ROLE instead.
+ const val ROLE_NOTES = "android.app.role.NOTES"
+
+ private val EMPTY_APPLICATION_INFO_FLAGS = ApplicationInfoFlags.of(0)!!
/**
* Returns the kernel user-ID of [packageName] for a [user]. Returns zero if the app cannot
* be found.
*/
- private fun PackageManager.getUidOf(packageName: String, user: UserHandle): Int {
- val applicationInfo =
- try {
- getApplicationInfoAsUser(packageName, EMPTY_APPLICATION_INFO_FLAGS, user)
- } catch (e: PackageManager.NameNotFoundException) {
- Log.e(TAG, "Couldn't find notes app UID", e)
- return 0
- }
- return applicationInfo.uid
- }
-
- // TODO(b/265912743): Use RoleManager.NOTES_ROLE instead.
- const val ROLE_NOTES = "android.app.role.NOTES"
+ private fun PackageManager.getUidOf(packageName: String, user: UserHandle): Int =
+ try {
+ getApplicationInfoAsUser(packageName, EMPTY_APPLICATION_INFO_FLAGS, user).uid
+ } catch (e: PackageManager.NameNotFoundException) {
+ Log.e(TAG, "Couldn't find notes app UID", e)
+ 0
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt
index d40bf2b49975..fb3c0cb54f84 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt
@@ -13,13 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.android.systemui.notetask
-import android.app.KeyguardManager
+import android.view.KeyEvent
import androidx.annotation.VisibleForTesting
import com.android.systemui.statusbar.CommandQueue
-import com.android.systemui.util.kotlin.getOrNull
import com.android.wm.shell.bubbles.Bubbles
import java.util.Optional
import javax.inject.Inject
@@ -28,41 +26,28 @@ import javax.inject.Inject
internal class NoteTaskInitializer
@Inject
constructor(
- private val optionalBubbles: Optional<Bubbles>,
- private val noteTaskController: NoteTaskController,
+ private val controller: NoteTaskController,
private val commandQueue: CommandQueue,
+ private val optionalBubbles: Optional<Bubbles>,
@NoteTaskEnabledKey private val isEnabled: Boolean,
- private val optionalKeyguardManager: Optional<KeyguardManager>,
) {
@VisibleForTesting
val callbacks =
object : CommandQueue.Callbacks {
override fun handleSystemKey(keyCode: Int) {
- if (keyCode == NoteTaskController.NOTE_TASK_KEY_EVENT) {
- showNoteTask()
+ if (keyCode == KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL) {
+ controller.showNoteTask(NoteTaskEntryPoint.TAIL_BUTTON)
}
}
}
- private fun showNoteTask() {
- val uiEvent =
- if (optionalKeyguardManager.isKeyguardLocked) {
- NoteTaskController.ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON_LOCKED
- } else {
- NoteTaskController.ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON
- }
- noteTaskController.showNoteTask(uiEvent = uiEvent)
- }
-
fun initialize() {
- if (isEnabled && optionalBubbles.isPresent) {
- commandQueue.addCallback(callbacks)
- }
- noteTaskController.setNoteTaskShortcutEnabled(isEnabled)
+ controller.setNoteTaskShortcutEnabled(isEnabled)
+
+ // Guard against feature not being enabled or mandatory dependencies aren't available.
+ if (!isEnabled || optionalBubbles.isEmpty) return
+
+ commandQueue.addCallback(callbacks)
}
}
-
-private val Optional<KeyguardManager>.isKeyguardLocked: Boolean
- // If there's no KeyguardManager, assume that the keyguard is not locked.
- get() = getOrNull()?.isKeyguardLocked ?: false
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskLaunchMode.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskLaunchMode.kt
new file mode 100644
index 000000000000..836e103f4d69
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskLaunchMode.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2023 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.notetask
+
+import android.content.Context
+import com.android.wm.shell.bubbles.Bubbles
+
+/**
+ * Supported ways for launching a note taking experience.
+ *
+ * @see [NoteTaskController.showNoteTask]
+ */
+sealed class NoteTaskLaunchMode {
+
+ /** @see Bubbles.showOrHideAppBubble */
+ object AppBubble : NoteTaskLaunchMode()
+
+ /** @see Context.startActivity */
+ object Activity : NoteTaskLaunchMode()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt
index b8800a242d06..ba8999c068e3 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt
@@ -36,7 +36,7 @@ import java.util.Optional
/** Compose all dependencies required by Note Task feature. */
@Module(includes = [NoteTaskQuickAffordanceModule::class])
-internal interface NoteTaskModule {
+interface NoteTaskModule {
@[Binds IntoMap ClassKey(LaunchNoteTaskActivity::class)]
fun LaunchNoteTaskActivity.bindNoteTaskLauncherActivity(): Activity
@@ -51,7 +51,7 @@ internal interface NoteTaskModule {
featureFlags: FeatureFlags,
roleManager: RoleManager,
): Boolean {
- val isRoleAvailable = roleManager.isRoleAvailable(NoteTaskInfoResolver.ROLE_NOTES)
+ val isRoleAvailable = roleManager.isRoleAvailable(RoleManager.ROLE_NOTES)
val isFeatureEnabled = featureFlags.isEnabled(Flags.NOTE_TASKS)
return isRoleAvailable && isFeatureEnabled
}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/OWNERS b/packages/SystemUI/src/com/android/systemui/notetask/OWNERS
index 7ccb316dbca5..0ec996be72de 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/OWNERS
+++ b/packages/SystemUI/src/com/android/systemui/notetask/OWNERS
@@ -5,4 +5,6 @@ juliacr@google.com
madym@google.com
mgalhardo@google.com
petrcermak@google.com
+stevenckng@google.com
+tkachenkoi@google.com
vanjan@google.com \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfig.kt
index 43869ccda2b1..30660c492baa 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfig.kt
@@ -27,12 +27,12 @@ import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanc
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.OnTriggeredResult
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.PickerScreenState
import com.android.systemui.notetask.NoteTaskController
-import com.android.systemui.notetask.NoteTaskController.ShowNoteTaskUiEvent
import com.android.systemui.notetask.NoteTaskEnabledKey
+import com.android.systemui.notetask.NoteTaskEntryPoint
import javax.inject.Inject
import kotlinx.coroutines.flow.flowOf
-internal class NoteTaskQuickAffordanceConfig
+class NoteTaskQuickAffordanceConfig
@Inject
constructor(
context: Context,
@@ -66,7 +66,7 @@ constructor(
override fun onTriggered(expandable: Expandable?): OnTriggeredResult {
noteTaskController.showNoteTask(
- uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE
+ entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE,
)
return OnTriggeredResult.Handled
}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceModule.kt b/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceModule.kt
index 7cb932aa1916..2d63dbcb82fa 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceModule.kt
@@ -22,7 +22,7 @@ import dagger.Module
import dagger.multibindings.IntoSet
@Module
-internal interface NoteTaskQuickAffordanceModule {
+interface NoteTaskQuickAffordanceModule {
@[Binds IntoSet]
fun NoteTaskQuickAffordanceConfig.bindNoteTaskQuickAffordance(): KeyguardQuickAffordanceConfig
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt
index 6ab0da6fe3b3..8ced46461dbb 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt
@@ -33,10 +33,10 @@ import javax.inject.Inject
* launched, creating a new shortcut for [CreateNoteTaskShortcutActivity], and will finish.
*
* @see <a
- * href="https://developer.android.com/develop/ui/views/launch/shortcuts/creating-shortcuts#custom-pinned">Creating
- * a custom shortcut activity</a>
+ * href="https://developer.android.com/develop/ui/views/launch/shortcuts/creating-shortcuts#custom-pinned">Creating
+ * a custom shortcut activity</a>
*/
-internal class CreateNoteTaskShortcutActivity @Inject constructor() : ComponentActivity() {
+class CreateNoteTaskShortcutActivity @Inject constructor() : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt
index 3ac5bfa09aaa..80fce6ae288b 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt
@@ -21,11 +21,11 @@ import android.content.Intent
import android.os.Bundle
import androidx.activity.ComponentActivity
import com.android.systemui.notetask.NoteTaskController
-import com.android.systemui.notetask.NoteTaskController.ShowNoteTaskUiEvent
+import com.android.systemui.notetask.NoteTaskEntryPoint
import javax.inject.Inject
/** Activity responsible for launching the note experience, and finish. */
-internal class LaunchNoteTaskActivity
+class LaunchNoteTaskActivity
@Inject
constructor(
private val noteTaskController: NoteTaskController,
@@ -35,8 +35,8 @@ constructor(
super.onCreate(savedInstanceState)
noteTaskController.showNoteTask(
+ entryPoint = NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT,
isInMultiWindowMode = isInMultiWindowMode,
- uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_SHORTCUT,
)
finish()
@@ -49,7 +49,7 @@ constructor(
return Intent(context, LaunchNoteTaskActivity::class.java).apply {
// Intent's action must be set in shortcuts, or an exception will be thrown.
// TODO(b/254606432): Use Intent.ACTION_CREATE_NOTE instead.
- action = NoteTaskController.ACTION_CREATE_NOTE
+ action = Intent.ACTION_CREATE_NOTE
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index 2522e1c5b798..7a42642f2667 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -154,6 +154,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
private final Intent mOpenBatterySettings = settings(Intent.ACTION_POWER_USAGE_SUMMARY);
private final Intent mOpenBatterySaverSettings =
settings(Settings.ACTION_BATTERY_SAVER_SETTINGS);
+ private final boolean mUseExtraSaverConfirmation;
private int mBatteryLevel;
private int mBucket;
@@ -197,6 +198,8 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
mDialogLaunchAnimator = dialogLaunchAnimator;
mUiEventLogger = uiEventLogger;
mUserTracker = userTracker;
+ mUseExtraSaverConfirmation =
+ mContext.getResources().getBoolean(R.bool.config_extra_battery_saver_confirmation);
}
@Override
@@ -644,7 +647,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
}
private void showStartSaverConfirmation(Bundle extras) {
- if (mSaverConfirmation != null) return;
+ if (mSaverConfirmation != null || mUseExtraSaverConfirmation) return;
final SystemUIDialog d = new SystemUIDialog(mContext);
final boolean confirmOnly = extras.getBoolean(BatterySaverUtils.EXTRA_CONFIRM_TEXT_ONLY);
final int batterySaverTriggerMode =
@@ -679,6 +682,10 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
resolver,
Secure.LOW_POWER_WARNING_ACKNOWLEDGED,
1, mUserTracker.getUserId());
+ Secure.putIntForUser(
+ resolver,
+ Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED,
+ 1, mUserTracker.getUserId());
});
} else {
d.setTitle(R.string.battery_saver_confirmation_title);
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
index 8ad2f867a073..79167f276576 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
@@ -16,7 +16,11 @@ package com.android.systemui.privacy
import android.content.Context
import android.util.AttributeSet
+import android.view.Gravity.CENTER_VERTICAL
+import android.view.Gravity.END
import android.view.ViewGroup
+import android.view.ViewGroup.LayoutParams.MATCH_PARENT
+import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.widget.ImageView
import android.widget.LinearLayout
import com.android.settingslib.Utils
@@ -35,7 +39,7 @@ class OngoingPrivacyChip @JvmOverloads constructor(
private var iconSize = 0
private var iconColor = 0
- private lateinit var iconsContainer: LinearLayout
+ private val iconsContainer: LinearLayout
var privacyList = emptyList<PrivacyItem>()
set(value) {
@@ -43,11 +47,13 @@ class OngoingPrivacyChip @JvmOverloads constructor(
updateView(PrivacyChipBuilder(context, field))
}
- override fun onFinishInflate() {
- super.onFinishInflate()
-
+ init {
+ inflate(context, R.layout.ongoing_privacy_chip, this)
+ id = R.id.privacy_chip
+ layoutParams = LayoutParams(WRAP_CONTENT, MATCH_PARENT, CENTER_VERTICAL or END)
+ clipChildren = true
+ clipToPadding = true
iconsContainer = requireViewById(R.id.icons_container)
-
updateResources()
}
@@ -107,6 +113,6 @@ class OngoingPrivacyChip @JvmOverloads constructor(
val padding = context.resources
.getDimensionPixelSize(R.dimen.ongoing_appops_chip_side_padding)
iconsContainer.setPaddingRelative(padding, 0, padding, 0)
- iconsContainer.background = context.getDrawable(R.drawable.privacy_chip_bg)
+ iconsContainer.background = context.getDrawable(R.drawable.statusbar_privacy_chip_bg)
}
} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qrcodescanner/dagger/QRCodeScannerModule.kt b/packages/SystemUI/src/com/android/systemui/qrcodescanner/dagger/QRCodeScannerModule.kt
index ff3ec72e6bae..d40112fd5660 100644
--- a/packages/SystemUI/src/com/android/systemui/qrcodescanner/dagger/QRCodeScannerModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/qrcodescanner/dagger/QRCodeScannerModule.kt
@@ -26,8 +26,7 @@ import dagger.multibindings.StringKey
@Module
interface QRCodeScannerModule {
- /**
- */
+ /** */
@Binds
@IntoMap
@StringKey(QRCodeScannerTile.TILE_SPEC)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.kt b/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.kt
index be93550158c6..c70cce9fec26 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.kt
@@ -183,7 +183,7 @@ class AutoAddTracker @VisibleForTesting constructor(
}
fun getRestoredTilePosition(tile: String): Int =
- restoredTiles?.get(tile)?.index ?: QSTileHost.POSITION_AT_END
+ restoredTiles?.get(tile)?.index ?: QSHost.POSITION_AT_END
/**
* Returns `true` if the tile has been auto-added before
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index e1289a61d45d..a7aac5a4824d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -135,7 +135,7 @@ public class QSAnimator implements QSHost.Callback, PagedTileLayout.PageListener
private int mNumQuickTiles;
private int mLastQQSTileHeight;
private float mLastPosition;
- private final QSTileHost mHost;
+ private final QSHost mHost;
private final Executor mExecutor;
private boolean mShowCollapsedOnKeyguard;
private int mQQSTop;
@@ -146,7 +146,7 @@ public class QSAnimator implements QSHost.Callback, PagedTileLayout.PageListener
@Inject
public QSAnimator(QS qs, QuickQSPanel quickPanel, QuickStatusBarHeader quickStatusBarHeader,
QSPanelController qsPanelController,
- QuickQSPanelController quickQSPanelController, QSTileHost qsTileHost,
+ QuickQSPanelController quickQSPanelController, QSHost qsTileHost,
@Main Executor executor, TunerService tunerService,
QSExpansionPathInterpolator qsExpansionPathInterpolator) {
mQs = qs;
@@ -330,12 +330,8 @@ public class QSAnimator implements QSHost.Callback, PagedTileLayout.PageListener
// Offset the translation animation on the views
// (that goes from 0 to getOffsetTranslation)
- int offsetWithQSBHTranslation =
- yOffset - mQuickStatusBarHeader.getOffsetTranslation();
- qqsTranslationYBuilder.addFloat(quickTileView, "translationY", 0,
- offsetWithQSBHTranslation);
- translationYBuilder.addFloat(tileView, "translationY",
- -offsetWithQSBHTranslation, 0);
+ qqsTranslationYBuilder.addFloat(quickTileView, "translationY", 0, yOffset);
+ translationYBuilder.addFloat(tileView, "translationY", -yOffset, 0);
translationXBuilder.addFloat(quickTileView, "translationX", 0, xOffset);
translationXBuilder.addFloat(tileView, "translationX", -xOffset, 0);
@@ -489,7 +485,7 @@ public class QSAnimator implements QSHost.Callback, PagedTileLayout.PageListener
if (specs.isEmpty()) {
// specs should not be empty in a valid secondary page, as we scrolled to it.
// We may crash later on because there's a null animator.
- specs = mQsPanelController.getHost().mTileSpecs;
+ specs = mHost.getSpecs();
Log.e(TAG, "Trying to create animators for empty page " + page + ". Tiles: " + specs);
// return null;
}
@@ -614,7 +610,7 @@ public class QSAnimator implements QSHost.Callback, PagedTileLayout.PageListener
View commonView = mQs.getView();
getRelativePositionInt(qsPosition, view1, commonView);
getRelativePositionInt(qqsPosition, view2, commonView);
- return (qsPosition[1] - qqsPosition[1]) - mQuickStatusBarHeader.getOffsetTranslation();
+ return qsPosition[1] - qqsPosition[1];
}
private boolean isIconInAnimatedRow(int count) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index 0c242d9da25f..b7f9f6bc0e4a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -53,7 +53,6 @@ public class QSContainerImpl extends FrameLayout implements Dumpable {
private boolean mQsDisabled;
private int mContentHorizontalPadding = -1;
private boolean mClippingEnabled;
- private boolean mUseCombinedHeaders;
public QSContainerImpl(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -68,10 +67,6 @@ public class QSContainerImpl extends FrameLayout implements Dumpable {
setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
}
- void setUseCombinedHeaders(boolean useCombinedHeaders) {
- mUseCombinedHeaders = useCombinedHeaders;
- }
-
@Override
public boolean hasOverlappingRendering() {
return false;
@@ -150,8 +145,7 @@ public class QSContainerImpl extends FrameLayout implements Dumpable {
void updateResources(QSPanelController qsPanelController,
QuickStatusBarHeaderController quickStatusBarHeaderController) {
int topPadding = QSUtils.getQsHeaderSystemIconsAreaHeight(mContext);
- if (mUseCombinedHeaders
- && !LargeScreenUtils.shouldUseLargeScreenShadeHeader(mContext.getResources())) {
+ if (!LargeScreenUtils.shouldUseLargeScreenShadeHeader(mContext.getResources())) {
topPadding = mContext.getResources()
.getDimensionPixelSize(R.dimen.large_screen_shade_header_height);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java
index 28b4c8228d38..73a5faabda3b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java
@@ -22,8 +22,6 @@ import android.content.res.Configuration;
import android.view.MotionEvent;
import android.view.View;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.qs.dagger.QSScope;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -66,15 +64,13 @@ public class QSContainerImplController extends ViewController<QSContainerImpl> {
QSPanelController qsPanelController,
QuickStatusBarHeaderController quickStatusBarHeaderController,
ConfigurationController configurationController,
- FalsingManager falsingManager,
- FeatureFlags featureFlags) {
+ FalsingManager falsingManager) {
super(view);
mQsPanelController = qsPanelController;
mQuickStatusBarHeaderController = quickStatusBarHeaderController;
mConfigurationController = configurationController;
mFalsingManager = falsingManager;
mQSPanelContainer = mView.getQSPanelContainer();
- view.setUseCombinedHeaders(featureFlags.isEnabled(Flags.COMBINED_QS_HEADERS));
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index d1f02dceb292..e55445c9990b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -227,7 +227,6 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
(v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
// Lazily update animators whenever the scrolling changes
mQSAnimator.requestAnimatorUpdate();
- mHeader.setExpandedScrollAmount(scrollY);
if (mScrollListener != null) {
mScrollListener.onQsPanelScrollChanged(scrollY);
}
@@ -647,8 +646,6 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
int heightDiff = getHeightDiff();
float panelTranslationY = translationScaleY * heightDiff;
- // Let the views animate their contents correctly by giving them the necessary context.
- mHeader.setExpansion(onKeyguardAndExpanded, expansion, panelTranslationY);
if (expansion < 1 && expansion > 0.99) {
if (mQuickQSPanelController.switchTileLayout(false)) {
mHeader.updateResources();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
index 1da30ade951b..a71e6ddb6abd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
@@ -14,15 +14,48 @@
package com.android.systemui.qs;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.res.Resources;
+import android.os.Build;
+import android.provider.Settings;
import com.android.internal.logging.InstanceId;
import com.android.internal.logging.UiEventLogger;
+import com.android.systemui.R;
+import com.android.systemui.plugins.qs.QSFactory;
import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.plugins.qs.QSTileView;
+import com.android.systemui.util.leak.GarbageMonitor;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.List;
public interface QSHost {
+ String TILES_SETTING = Settings.Secure.QS_TILES;
+ int POSITION_AT_END = -1;
+
+ /**
+ * Returns the default QS tiles for the context.
+ * @param context the context to obtain the resources from
+ * @return a list of specs of the default tiles
+ */
+ static List<String> getDefaultSpecs(Context context) {
+ final ArrayList<String> tiles = new ArrayList();
+
+ final Resources res = context.getResources();
+ final String defaultTileList = res.getString(R.string.quick_settings_tiles_default);
+
+ tiles.addAll(Arrays.asList(defaultTileList.split(",")));
+ if (Build.IS_DEBUGGABLE
+ && GarbageMonitor.ADD_MEMORY_TILE_TO_DEFAULT_ON_DEBUGGABLE_BUILDS) {
+ tiles.add(GarbageMonitor.MemoryTile.TILE_SPEC);
+ }
+ return tiles;
+ }
+
void warn(String message, Throwable t);
void collapsePanels();
void forceCollapsePanels();
@@ -37,6 +70,44 @@ public interface QSHost {
void removeTile(String tileSpec);
void removeTiles(Collection<String> specs);
+ List<String> getSpecs();
+ /**
+ * Create a view for a tile, iterating over all possible {@link QSFactory}.
+ *
+ * @see QSFactory#createTileView
+ */
+ QSTileView createTileView(Context themedContext, QSTile tile, boolean collapsedView);
+ /** Create a {@link QSTile} of a {@code tileSpec} type. */
+ QSTile createTile(String tileSpec);
+
+ /**
+ * Add a tile to the end
+ *
+ * @param spec string matching a pre-defined tilespec
+ */
+ void addTile(String spec);
+
+ /**
+ * Add a tile into the requested spot, or at the end if the position is greater than the number
+ * of tiles.
+ * @param spec string matching a pre-defined tilespec
+ * @param requestPosition -1 for end, 0 for beginning, or X for insertion at position X
+ */
+ void addTile(String spec, int requestPosition);
+ void addTile(ComponentName tile);
+
+ /**
+ * Adds a custom tile to the set of current tiles.
+ * @param tile the component name of the {@link android.service.quicksettings.TileService}
+ * @param end if true, the tile will be added at the end. If false, at the beginning.
+ */
+ void addTile(ComponentName tile, boolean end);
+ void removeTileByUser(ComponentName tile);
+ void changeTilesByUser(List<String> previousTiles, List<String> newTiles);
+
+ boolean isTileAdded(ComponentName componentName, int userId);
+ void setTileAdded(ComponentName componentName, int userId, boolean added);
+
int indexOf(String tileSpec);
InstanceId getNewInstanceId();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index a0be151e15a1..b476521f1975 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -79,7 +79,6 @@ public class QSPanel extends LinearLayout implements Tunable {
protected boolean mExpanded;
protected boolean mListening;
- @Nullable protected QSTileHost mHost;
private final List<OnConfigurationChangedListener> mOnConfigurationChangedListeners =
new ArrayList<>();
@@ -104,7 +103,6 @@ public class QSPanel extends LinearLayout implements Tunable {
private final Rect mClippingRect = new Rect();
private ViewGroup mMediaHostView;
private boolean mShouldMoveMediaOnExpansion = true;
- private boolean mUsingCombinedHeaders = false;
private QSLogger mQsLogger;
/**
* Specifies if we can collapse to QQS in current state. In split shade that should be always
@@ -155,10 +153,6 @@ public class QSPanel extends LinearLayout implements Tunable {
}
}
- void setUsingCombinedHeaders(boolean usingCombinedHeaders) {
- mUsingCombinedHeaders = usingCombinedHeaders;
- }
-
protected void setHorizontalContentContainerClipping() {
mHorizontalContentContainer.setClipChildren(true);
mHorizontalContentContainer.setClipToPadding(false);
@@ -364,11 +358,6 @@ public class QSPanel extends LinearLayout implements Tunable {
}
}
- @Nullable
- public QSTileHost getHost() {
- return mHost;
- }
-
public void updateResources() {
updatePadding();
@@ -383,9 +372,7 @@ public class QSPanel extends LinearLayout implements Tunable {
protected void updatePadding() {
final Resources res = mContext.getResources();
- int paddingTop = res.getDimensionPixelSize(
- mUsingCombinedHeaders ? R.dimen.qs_panel_padding_top_combined_headers
- : R.dimen.qs_panel_padding_top);
+ int paddingTop = res.getDimensionPixelSize(R.dimen.qs_panel_padding_top);
int paddingBottom = res.getDimensionPixelSize(R.dimen.qs_panel_padding_bottom);
setPaddingRelative(getPaddingStart(),
paddingTop,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
index 01dbb1825208..83b373d5e626 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
@@ -17,7 +17,6 @@
package com.android.systemui.qs;
import static com.android.systemui.classifier.Classifier.QS_SWIPE_SIDE;
-import static com.android.systemui.flags.Flags.COMBINED_QS_HEADERS;
import static com.android.systemui.media.dagger.MediaModule.QS_PANEL;
import static com.android.systemui.qs.QSPanel.QS_SHOW_BRIGHTNESS;
import static com.android.systemui.qs.dagger.QSFragmentModule.QS_USING_MEDIA_PLAYER;
@@ -28,7 +27,6 @@ import android.view.View;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.media.controls.ui.MediaHierarchyManager;
import com.android.systemui.media.controls.ui.MediaHost;
import com.android.systemui.media.controls.ui.MediaHostState;
@@ -73,7 +71,7 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
@Inject
QSPanelController(QSPanel view, TunerService tunerService,
- QSTileHost qstileHost, QSCustomizerController qsCustomizerController,
+ QSHost qsHost, QSCustomizerController qsCustomizerController,
@Named(QS_USING_MEDIA_PLAYER) boolean usingMediaPlayer,
@Named(QS_PANEL) MediaHost mediaHost,
QSTileRevealController.Factory qsTileRevealControllerFactory,
@@ -81,9 +79,8 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
QSLogger qsLogger, BrightnessController.Factory brightnessControllerFactory,
BrightnessSliderController.Factory brightnessSliderFactory,
FalsingManager falsingManager,
- StatusBarKeyguardViewManager statusBarKeyguardViewManager,
- FeatureFlags featureFlags) {
- super(view, qstileHost, qsCustomizerController, usingMediaPlayer, mediaHost,
+ StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
+ super(view, qsHost, qsCustomizerController, usingMediaPlayer, mediaHost,
metricsLogger, uiEventLogger, qsLogger, dumpManager);
mTunerService = tunerService;
mQsCustomizerController = qsCustomizerController;
@@ -96,7 +93,6 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
mBrightnessController = brightnessControllerFactory.create(mBrightnessSliderController);
mBrightnessMirrorHandler = new BrightnessMirrorHandler(mBrightnessController);
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
- mView.setUsingCombinedHeaders(featureFlags.isEnabled(COMBINED_QS_HEADERS));
}
@Override
@@ -176,12 +172,6 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
mBrightnessMirrorHandler.setController(brightnessMirrorController);
}
- /** Get the QSTileHost this panel uses. */
- public QSTileHost getHost() {
- return mHost;
- }
-
-
/** Update appearance of QSPanel. */
public void updateResources() {
mView.updateResources();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
index bbdf6cc70541..2668d2e36731 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
@@ -64,7 +64,7 @@ import kotlin.jvm.functions.Function1;
public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewController<T>
implements Dumpable{
private static final String TAG = "QSPanelControllerBase";
- protected final QSTileHost mHost;
+ protected final QSHost mHost;
private final QSCustomizerController mQsCustomizerController;
private final boolean mUsingMediaPlayer;
protected final MediaHost mMediaHost;
@@ -128,7 +128,7 @@ public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewContr
protected QSPanelControllerBase(
T view,
- QSTileHost host,
+ QSHost host,
QSCustomizerController qsCustomizerController,
@Named(QS_USING_MEDIA_PLAYER) boolean usingMediaPlayer,
MediaHost mediaHost,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index 98af9dfe7f37..0ead97976ad9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -18,7 +18,6 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
-import android.os.Build;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings.Secure;
@@ -56,17 +55,14 @@ import com.android.systemui.settings.UserFileManager;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.phone.AutoTileManager;
import com.android.systemui.statusbar.phone.CentralSurfaces;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
-import com.android.systemui.util.leak.GarbageMonitor;
import com.android.systemui.util.settings.SecureSettings;
import org.jetbrains.annotations.NotNull;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
@@ -94,16 +90,13 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final int MAX_QS_INSTANCE_ID = 1 << 20;
- public static final int POSITION_AT_END = -1;
- public static final String TILES_SETTING = Secure.QS_TILES;
-
// Shared prefs that hold tile lifecycle info.
@VisibleForTesting
static final String TILES = "tiles_prefs";
private final Context mContext;
private final LinkedHashMap<String, QSTile> mTiles = new LinkedHashMap<>();
- protected final ArrayList<String> mTileSpecs = new ArrayList<>();
+ private final ArrayList<String> mTileSpecs = new ArrayList<>();
private final TunerService mTunerService;
private final PluginManager mPluginManager;
private final DumpManager mDumpManager;
@@ -117,7 +110,6 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
private final List<Callback> mCallbacks = new ArrayList<>();
@Nullable
private AutoTileManager mAutoTiles;
- private final StatusBarIconController mIconController;
private final ArrayList<QSFactory> mQsFactories = new ArrayList<>();
private int mCurrentUser;
private final Optional<CentralSurfaces> mCentralSurfacesOptional;
@@ -135,7 +127,6 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
@Inject
public QSTileHost(Context context,
- StatusBarIconController iconController,
QSFactory defaultFactory,
@Main Executor mainExecutor,
PluginManager pluginManager,
@@ -152,7 +143,6 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
TileLifecycleManager.Factory tileLifecycleManagerFactory,
UserFileManager userFileManager
) {
- mIconController = iconController;
mContext = context;
mUserContext = context;
mTunerService = tunerService;
@@ -186,10 +176,6 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
});
}
- public StatusBarIconController getIconController() {
- return mIconController;
- }
-
@Override
public InstanceId getNewInstanceId() {
return mInstanceIdSequence.newInstanceId();
@@ -438,12 +424,7 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
addTile(spec, POSITION_AT_END);
}
- /**
- * Add a tile into the requested spot, or at the end if the position is greater than the number
- * of tiles.
- * @param spec string matching a pre-defined tilespec
- * @param requestPosition -1 for end, 0 for beginning, or X for insertion at position X
- */
+ @Override
public void addTile(String spec, int requestPosition) {
mMainExecutor.execute(() ->
changeTileSpecs(tileSpecs -> {
@@ -483,15 +464,12 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
}
}
+ @Override
public void addTile(ComponentName tile) {
addTile(tile, /* end */ false);
}
- /**
- * Adds a custom tile to the set of current tiles.
- * @param tile the component name of the {@link android.service.quicksettings.TileService}
- * @param end if true, the tile will be added at the end. If false, at the beginning.
- */
+ @Override
public void addTile(ComponentName tile, boolean end) {
String spec = CustomTile.toSpec(tile);
addTile(spec, end ? POSITION_AT_END : 0);
@@ -501,6 +479,7 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
* This will call through {@link #changeTilesByUser}. It should only be used when a tile is
* removed by a <b>user action</b> like {@code adb}.
*/
+ @Override
public void removeTileByUser(ComponentName tile) {
mMainExecutor.execute(() -> {
List<String> newSpecs = new ArrayList<>(mTileSpecs);
@@ -519,6 +498,7 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
* that are removed.
*/
@MainThread
+ @Override
public void changeTilesByUser(List<String> previousTiles, List<String> newTiles) {
final List<String> copy = new ArrayList<>(previousTiles);
final int NP = copy.size();
@@ -542,8 +522,8 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
saveTilesToSettings(newTiles);
}
- /** Create a {@link QSTile} of a {@code tileSpec} type. */
@Nullable
+ @Override
public QSTile createTile(String tileSpec) {
for (int i = 0; i < mQsFactories.size(); i++) {
QSTile t = mQsFactories.get(i).createTile(tileSpec);
@@ -554,11 +534,7 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
return null;
}
- /**
- * Create a view for a tile, iterating over all possible {@link QSFactory}.
- *
- * @see QSFactory#createTileView
- */
+ @Override
public QSTileView createTileView(Context themedContext, QSTile tile, boolean collapsedView) {
for (int i = 0; i < mQsFactories.size(); i++) {
QSTileView view = mQsFactories.get(i)
@@ -578,6 +554,7 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
* tile.
* @param userId the user to check
*/
+ @Override
public boolean isTileAdded(ComponentName componentName, int userId) {
return mUserFileManager
.getSharedPreferences(TILES, 0, userId)
@@ -593,6 +570,7 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
* @param userId the user for this tile
* @param added {@code true} if the tile is being added, {@code false} otherwise
*/
+ @Override
public void setTileAdded(ComponentName componentName, int userId, boolean added) {
mUserFileManager.getSharedPreferences(TILES, 0, userId)
.edit()
@@ -600,6 +578,11 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
.apply();
}
+ @Override
+ public List<String> getSpecs() {
+ return mTileSpecs;
+ }
+
protected static List<String> loadTileSpecs(Context context, String tileList) {
final Resources res = context.getResources();
@@ -617,7 +600,7 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
if (tile.isEmpty()) continue;
if (tile.equals("default")) {
if (!addedDefault) {
- List<String> defaultSpecs = getDefaultSpecs(context);
+ List<String> defaultSpecs = QSHost.getDefaultSpecs(context);
for (String spec : defaultSpecs) {
if (!addedSpecs.contains(spec)) {
tiles.add(spec);
@@ -650,25 +633,6 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P
return tiles;
}
- /**
- * Returns the default QS tiles for the context.
- * @param context the context to obtain the resources from
- * @return a list of specs of the default tiles
- */
- public static List<String> getDefaultSpecs(Context context) {
- final ArrayList<String> tiles = new ArrayList<String>();
-
- final Resources res = context.getResources();
- final String defaultTileList = res.getString(R.string.quick_settings_tiles_default);
-
- tiles.addAll(Arrays.asList(defaultTileList.split(",")));
- if (Build.IS_DEBUGGABLE
- && GarbageMonitor.ADD_MEMORY_TILE_TO_DEFAULT_ON_DEBUGGABLE_BUILDS) {
- tiles.add(GarbageMonitor.MemoryTile.TILE_SPEC);
- }
- return tiles;
- }
-
@Override
public void dump(PrintWriter pw, String[] args) {
pw.println("QSTileHost:");
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
index 6aabe3b1ced1..2d543139a1b4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
@@ -48,7 +48,7 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel>
private final Provider<Boolean> mUsingCollapsedLandscapeMediaProvider;
@Inject
- QuickQSPanelController(QuickQSPanel view, QSTileHost qsTileHost,
+ QuickQSPanelController(QuickQSPanel view, QSHost qsHost,
QSCustomizerController qsCustomizerController,
@Named(QS_USING_MEDIA_PLAYER) boolean usingMediaPlayer,
@Named(QUICK_QS_PANEL) MediaHost mediaHost,
@@ -57,7 +57,7 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel>
MetricsLogger metricsLogger, UiEventLogger uiEventLogger, QSLogger qsLogger,
DumpManager dumpManager
) {
- super(view, qsTileHost, qsCustomizerController, usingMediaPlayer, mediaHost, metricsLogger,
+ super(view, qsHost, qsCustomizerController, usingMediaPlayer, mediaHost, metricsLogger,
uiEventLogger, qsLogger, dumpManager);
mUsingCollapsedLandscapeMediaProvider = usingCollapsedLandscapeMediaProvider;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index e696d131267f..691a1a14444a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -20,35 +20,15 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.graphics.Color;
-import android.graphics.Rect;
import android.util.AttributeSet;
-import android.util.Pair;
-import android.view.DisplayCutout;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
-import android.view.WindowInsets;
import android.widget.FrameLayout;
-import android.widget.LinearLayout;
-import android.widget.Space;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.internal.policy.SystemBarUtils;
-import com.android.settingslib.Utils;
import com.android.systemui.R;
-import com.android.systemui.battery.BatteryMeterView;
-import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider;
-import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager;
-import com.android.systemui.statusbar.phone.StatusIconContainer;
-import com.android.systemui.statusbar.policy.Clock;
-import com.android.systemui.statusbar.policy.VariableDateView;
import com.android.systemui.util.LargeScreenUtils;
-import java.util.List;
-
/**
* View that contains the top-most bits of the QS panel (primarily the status bar with date, time,
* battery, carrier info and privacy icons) and also contains the {@link QuickQSPanel}.
@@ -58,182 +38,30 @@ public class QuickStatusBarHeader extends FrameLayout {
private boolean mExpanded;
private boolean mQsDisabled;
- @Nullable
- private TouchAnimator mAlphaAnimator;
- @Nullable
- private TouchAnimator mTranslationAnimator;
- @Nullable
- private TouchAnimator mIconsAlphaAnimator;
- private TouchAnimator mIconsAlphaAnimatorFixed;
-
protected QuickQSPanel mHeaderQsPanel;
- private View mDatePrivacyView;
- private View mDateView;
- // DateView next to clock. Visible on QQS
- private VariableDateView mClockDateView;
- private View mStatusIconsView;
- private View mContainer;
-
- private View mQSCarriers;
- private ViewGroup mClockContainer;
- private Clock mClockView;
- private Space mDatePrivacySeparator;
- private View mClockIconsSeparator;
- private boolean mShowClockIconsSeparator;
- private View mRightLayout;
- private View mDateContainer;
- private View mPrivacyContainer;
-
- private BatteryMeterView mBatteryRemainingIcon;
- private StatusIconContainer mIconContainer;
- private View mPrivacyChip;
-
- @Nullable
- private TintedIconManager mTintedIconManager;
- @Nullable
- private QSExpansionPathInterpolator mQSExpansionPathInterpolator;
- private StatusBarContentInsetsProvider mInsetsProvider;
-
- private int mRoundedCornerPadding = 0;
- private int mWaterfallTopInset;
- private int mCutOutPaddingLeft;
- private int mCutOutPaddingRight;
- private float mKeyguardExpansionFraction;
- private int mTextColorPrimary = Color.TRANSPARENT;
- private int mTopViewMeasureHeight;
-
- @NonNull
- private List<String> mRssiIgnoredSlots = List.of();
- private boolean mIsSingleCarrier;
-
- private boolean mHasCenterCutout;
- private boolean mConfigShowBatteryEstimate;
-
- private boolean mUseCombinedQSHeader;
public QuickStatusBarHeader(Context context, AttributeSet attrs) {
super(context, attrs);
}
- /**
- * How much the view containing the clock and QQS will translate down when QS is fully expanded.
- *
- * This matches the measured height of the view containing the date and privacy icons.
- */
- public int getOffsetTranslation() {
- return mTopViewMeasureHeight;
- }
-
@Override
protected void onFinishInflate() {
super.onFinishInflate();
-
mHeaderQsPanel = findViewById(R.id.quick_qs_panel);
- mDatePrivacyView = findViewById(R.id.quick_status_bar_date_privacy);
- mStatusIconsView = findViewById(R.id.quick_qs_status_icons);
- mQSCarriers = findViewById(R.id.carrier_group);
- mContainer = findViewById(R.id.qs_container);
- mIconContainer = findViewById(R.id.statusIcons);
- mPrivacyChip = findViewById(R.id.privacy_chip);
- mDateView = findViewById(R.id.date);
- mClockDateView = findViewById(R.id.date_clock);
- mClockIconsSeparator = findViewById(R.id.separator);
- mRightLayout = findViewById(R.id.rightLayout);
- mDateContainer = findViewById(R.id.date_container);
- mPrivacyContainer = findViewById(R.id.privacy_container);
-
- mClockContainer = findViewById(R.id.clock_container);
- mClockView = findViewById(R.id.clock);
- mDatePrivacySeparator = findViewById(R.id.space);
- // Tint for the battery icons are handled in setupHost()
- mBatteryRemainingIcon = findViewById(R.id.batteryRemainingIcon);
updateResources();
- Configuration config = mContext.getResources().getConfiguration();
- setDatePrivacyContainersWidth(config.orientation == Configuration.ORIENTATION_LANDSCAPE);
-
- updateBatteryMode();
-
- mIconsAlphaAnimatorFixed = new TouchAnimator.Builder()
- .addFloat(mIconContainer, "alpha", 0, 1)
- .addFloat(mBatteryRemainingIcon, "alpha", 0, 1)
- .build();
- }
-
- void onAttach(TintedIconManager iconManager,
- QSExpansionPathInterpolator qsExpansionPathInterpolator,
- List<String> rssiIgnoredSlots,
- StatusBarContentInsetsProvider insetsProvider,
- boolean useCombinedQSHeader) {
- mUseCombinedQSHeader = useCombinedQSHeader;
- mTintedIconManager = iconManager;
- mRssiIgnoredSlots = rssiIgnoredSlots;
- mInsetsProvider = insetsProvider;
- int fillColor = Utils.getColorAttrDefaultColor(getContext(),
- android.R.attr.textColorPrimary);
-
- // Set the correct tint for the status icons so they contrast
- iconManager.setTint(fillColor);
-
- mQSExpansionPathInterpolator = qsExpansionPathInterpolator;
- updateAnimators();
- }
-
- void setIsSingleCarrier(boolean isSingleCarrier) {
- mIsSingleCarrier = isSingleCarrier;
- updateAlphaAnimator();
- }
-
- public QuickQSPanel getHeaderQsPanel() {
- return mHeaderQsPanel;
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- if (mDatePrivacyView.getMeasuredHeight() != mTopViewMeasureHeight) {
- mTopViewMeasureHeight = mDatePrivacyView.getMeasuredHeight();
- post(this::updateAnimators);
- }
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
updateResources();
- setDatePrivacyContainersWidth(newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE);
- }
-
- @Override
- public void onRtlPropertiesChanged(int layoutDirection) {
- super.onRtlPropertiesChanged(layoutDirection);
- updateResources();
- }
-
- private void setDatePrivacyContainersWidth(boolean landscape) {
- LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mDateContainer.getLayoutParams();
- lp.width = landscape ? WRAP_CONTENT : 0;
- lp.weight = landscape ? 0f : 1f;
- mDateContainer.setLayoutParams(lp);
-
- lp = (LinearLayout.LayoutParams) mPrivacyContainer.getLayoutParams();
- lp.width = landscape ? WRAP_CONTENT : 0;
- lp.weight = landscape ? 0f : 1f;
- mPrivacyContainer.setLayoutParams(lp);
- }
-
- private void updateBatteryMode() {
- if (mConfigShowBatteryEstimate && !mHasCenterCutout) {
- mBatteryRemainingIcon.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE);
- } else {
- mBatteryRemainingIcon.setPercentShowMode(BatteryMeterView.MODE_ON);
- }
}
@Override
public boolean onTouchEvent(MotionEvent event) {
- // If using combined headers, only react to touches inside QuickQSPanel
- if (!mUseCombinedQSHeader || event.getY() > mHeaderQsPanel.getTop()) {
+ // Only react to touches inside QuickQSPanel
+ if (event.getY() > mHeaderQsPanel.getTop()) {
return super.onTouchEvent(event);
} else {
return false;
@@ -245,193 +73,29 @@ public class QuickStatusBarHeader extends FrameLayout {
boolean largeScreenHeaderActive =
LargeScreenUtils.shouldUseLargeScreenShadeHeader(resources);
- boolean gone = largeScreenHeaderActive || mUseCombinedQSHeader || mQsDisabled;
- mStatusIconsView.setVisibility(gone ? View.GONE : View.VISIBLE);
- mDatePrivacyView.setVisibility(gone ? View.GONE : View.VISIBLE);
-
- mConfigShowBatteryEstimate = resources.getBoolean(R.bool.config_showBatteryEstimateQSBH);
-
- mRoundedCornerPadding = resources.getDimensionPixelSize(
- R.dimen.rounded_corner_content_padding);
-
- int qsOffsetHeight = SystemBarUtils.getQuickQsOffsetHeight(mContext);
-
- mDatePrivacyView.getLayoutParams().height =
- Math.max(qsOffsetHeight, mDatePrivacyView.getMinimumHeight());
- mDatePrivacyView.setLayoutParams(mDatePrivacyView.getLayoutParams());
-
- mStatusIconsView.getLayoutParams().height =
- Math.max(qsOffsetHeight, mStatusIconsView.getMinimumHeight());
- mStatusIconsView.setLayoutParams(mStatusIconsView.getLayoutParams());
-
ViewGroup.LayoutParams lp = getLayoutParams();
if (mQsDisabled) {
- lp.height = mStatusIconsView.getLayoutParams().height;
+ lp.height = 0;
} else {
lp.height = WRAP_CONTENT;
}
setLayoutParams(lp);
- int textColor = Utils.getColorAttrDefaultColor(mContext, android.R.attr.textColorPrimary);
- if (textColor != mTextColorPrimary) {
- int textColorSecondary = Utils.getColorAttrDefaultColor(mContext,
- android.R.attr.textColorSecondary);
- mTextColorPrimary = textColor;
- mClockView.setTextColor(textColor);
- if (mTintedIconManager != null) {
- mTintedIconManager.setTint(textColor);
- }
- mBatteryRemainingIcon.updateColors(mTextColorPrimary, textColorSecondary,
- mTextColorPrimary);
- }
-
MarginLayoutParams qqsLP = (MarginLayoutParams) mHeaderQsPanel.getLayoutParams();
if (largeScreenHeaderActive) {
qqsLP.topMargin = mContext.getResources()
.getDimensionPixelSize(R.dimen.qqs_layout_margin_top);
- } else if (!mUseCombinedQSHeader) {
- qqsLP.topMargin = qsOffsetHeight;
} else {
qqsLP.topMargin = mContext.getResources()
.getDimensionPixelSize(R.dimen.large_screen_shade_header_min_height);
}
mHeaderQsPanel.setLayoutParams(qqsLP);
-
- updateBatteryMode();
- updateHeadersPadding();
- updateAnimators();
-
- updateClockDatePadding();
}
- private void updateClockDatePadding() {
- int startPadding = mContext.getResources()
- .getDimensionPixelSize(R.dimen.status_bar_left_clock_starting_padding);
- int endPadding = mContext.getResources()
- .getDimensionPixelSize(R.dimen.status_bar_left_clock_end_padding);
- mClockView.setPaddingRelative(
- startPadding,
- mClockView.getPaddingTop(),
- endPadding,
- mClockView.getPaddingBottom()
- );
-
- MarginLayoutParams lp = (MarginLayoutParams) mClockDateView.getLayoutParams();
- lp.setMarginStart(endPadding);
- mClockDateView.setLayoutParams(lp);
- }
-
- private void updateAnimators() {
- if (mUseCombinedQSHeader) {
- mTranslationAnimator = null;
- return;
- }
- updateAlphaAnimator();
- int offset = mTopViewMeasureHeight;
-
- mTranslationAnimator = new TouchAnimator.Builder()
- .addFloat(mContainer, "translationY", 0, offset)
- .setInterpolator(mQSExpansionPathInterpolator != null
- ? mQSExpansionPathInterpolator.getYInterpolator()
- : null)
- .build();
- }
-
- private void updateAlphaAnimator() {
- if (mUseCombinedQSHeader) {
- mAlphaAnimator = null;
- return;
- }
- TouchAnimator.Builder builder = new TouchAnimator.Builder()
- // These views appear on expanding down
- .addFloat(mDateView, "alpha", 0, 0, 1)
- .addFloat(mClockDateView, "alpha", 1, 0, 0)
- .addFloat(mQSCarriers, "alpha", 0, 1)
- .setListener(new TouchAnimator.ListenerAdapter() {
- @Override
- public void onAnimationAtEnd() {
- super.onAnimationAtEnd();
- if (!mIsSingleCarrier) {
- mIconContainer.addIgnoredSlots(mRssiIgnoredSlots);
- }
- // Make it gone so there's enough room for carrier names
- mClockDateView.setVisibility(View.GONE);
- }
-
- @Override
- public void onAnimationStarted() {
- mClockDateView.setVisibility(View.VISIBLE);
- mClockDateView.setFreezeSwitching(true);
- setSeparatorVisibility(false);
- if (!mIsSingleCarrier) {
- mIconContainer.addIgnoredSlots(mRssiIgnoredSlots);
- }
- }
-
- @Override
- public void onAnimationAtStart() {
- super.onAnimationAtStart();
- mClockDateView.setFreezeSwitching(false);
- mClockDateView.setVisibility(View.VISIBLE);
- setSeparatorVisibility(mShowClockIconsSeparator);
- // In QQS we never ignore RSSI.
- mIconContainer.removeIgnoredSlots(mRssiIgnoredSlots);
- }
- });
- mAlphaAnimator = builder.build();
- }
-
- void setChipVisibility(boolean visibility) {
- if (visibility) {
- // Animates the icons and battery indicator from alpha 0 to 1, when the chip is visible
- mIconsAlphaAnimator = mIconsAlphaAnimatorFixed;
- mIconsAlphaAnimator.setPosition(mKeyguardExpansionFraction);
- } else {
- mIconsAlphaAnimator = null;
- mIconContainer.setAlpha(1);
- mBatteryRemainingIcon.setAlpha(1);
- }
-
- }
-
- /** */
public void setExpanded(boolean expanded, QuickQSPanelController quickQSPanelController) {
if (mExpanded == expanded) return;
mExpanded = expanded;
quickQSPanelController.setExpanded(expanded);
- updateEverything();
- }
-
- /**
- * Animates the inner contents based on the given expansion details.
- *
- * @param forceExpanded whether we should show the state expanded forcibly
- * @param expansionFraction how much the QS panel is expanded/pulled out (up to 1f)
- * @param panelTranslationY how much the panel has physically moved down vertically (required
- * for keyguard animations only)
- */
- public void setExpansion(boolean forceExpanded, float expansionFraction,
- float panelTranslationY) {
- final float keyguardExpansionFraction = forceExpanded ? 1f : expansionFraction;
-
- if (mAlphaAnimator != null) {
- mAlphaAnimator.setPosition(keyguardExpansionFraction);
- }
- if (mTranslationAnimator != null) {
- mTranslationAnimator.setPosition(keyguardExpansionFraction);
- }
- if (mIconsAlphaAnimator != null) {
- mIconsAlphaAnimator.setPosition(keyguardExpansionFraction);
- }
- // If forceExpanded (we are opening QS from lockscreen), the animators have been set to
- // position = 1f.
- if (forceExpanded) {
- setAlpha(expansionFraction);
- } else {
- setAlpha(1);
- }
-
- mKeyguardExpansionFraction = keyguardExpansionFraction;
}
public void disable(int state1, int state2, boolean animate) {
@@ -439,133 +103,13 @@ public class QuickStatusBarHeader extends FrameLayout {
if (disabled == mQsDisabled) return;
mQsDisabled = disabled;
mHeaderQsPanel.setDisabledByPolicy(disabled);
- mStatusIconsView.setVisibility(mQsDisabled ? View.GONE : View.VISIBLE);
updateResources();
}
- @Override
- public WindowInsets onApplyWindowInsets(WindowInsets insets) {
- // Handle padding of the views
- DisplayCutout cutout = insets.getDisplayCutout();
-
- Pair<Integer, Integer> sbInsets = mInsetsProvider
- .getStatusBarContentInsetsForCurrentRotation();
- boolean hasCornerCutout = mInsetsProvider.currentRotationHasCornerCutout();
-
- mDatePrivacyView.setPadding(sbInsets.first, 0, sbInsets.second, 0);
- mStatusIconsView.setPadding(sbInsets.first, 0, sbInsets.second, 0);
- LinearLayout.LayoutParams datePrivacySeparatorLayoutParams =
- (LinearLayout.LayoutParams) mDatePrivacySeparator.getLayoutParams();
- LinearLayout.LayoutParams mClockIconsSeparatorLayoutParams =
- (LinearLayout.LayoutParams) mClockIconsSeparator.getLayoutParams();
-
- Rect topCutout = cutout == null ? null : cutout.getBoundingRectTop();
- if (topCutout == null || topCutout.isEmpty() || hasCornerCutout) {
- datePrivacySeparatorLayoutParams.width = 0;
- mDatePrivacySeparator.setVisibility(View.GONE);
- mClockIconsSeparatorLayoutParams.width = 0;
- setSeparatorVisibility(false);
- mShowClockIconsSeparator = false;
- mHasCenterCutout = false;
- } else {
- datePrivacySeparatorLayoutParams.width = topCutout.width();
- mDatePrivacySeparator.setVisibility(View.VISIBLE);
- mClockIconsSeparatorLayoutParams.width = topCutout.width();
- mShowClockIconsSeparator = true;
- setSeparatorVisibility(mKeyguardExpansionFraction == 0f);
- mHasCenterCutout = true;
- }
-
- mDatePrivacySeparator.setLayoutParams(datePrivacySeparatorLayoutParams);
- mClockIconsSeparator.setLayoutParams(mClockIconsSeparatorLayoutParams);
- mCutOutPaddingLeft = sbInsets.first;
- mCutOutPaddingRight = sbInsets.second;
- mWaterfallTopInset = cutout == null ? 0 : cutout.getWaterfallInsets().top;
-
- updateBatteryMode();
- updateHeadersPadding();
- return super.onApplyWindowInsets(insets);
- }
-
- /**
- * Sets the visibility of the separator between clock and icons.
- *
- * This separator is "visible" when there is a center cutout, to block that space. In that
- * case, the clock and the layout on the right (containing the icons and the battery meter) are
- * set to weight 1 to take the available space.
- * @param visible whether the separator between clock and icons should be visible.
- */
- private void setSeparatorVisibility(boolean visible) {
- int newVisibility = visible ? View.VISIBLE : View.GONE;
- if (mClockIconsSeparator.getVisibility() == newVisibility) return;
-
- mClockIconsSeparator.setVisibility(visible ? View.VISIBLE : View.GONE);
- mQSCarriers.setVisibility(visible ? View.GONE : View.VISIBLE);
-
- LinearLayout.LayoutParams lp =
- (LinearLayout.LayoutParams) mClockContainer.getLayoutParams();
- lp.width = visible ? 0 : WRAP_CONTENT;
- lp.weight = visible ? 1f : 0f;
- mClockContainer.setLayoutParams(lp);
-
- lp = (LinearLayout.LayoutParams) mRightLayout.getLayoutParams();
- lp.width = visible ? 0 : WRAP_CONTENT;
- lp.weight = visible ? 1f : 0f;
- mRightLayout.setLayoutParams(lp);
- }
-
- private void updateHeadersPadding() {
- setContentMargins(mDatePrivacyView, 0, 0);
- setContentMargins(mStatusIconsView, 0, 0);
- int paddingLeft = 0;
- int paddingRight = 0;
-
- FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
- int leftMargin = lp.leftMargin;
- int rightMargin = lp.rightMargin;
-
- // The clock might collide with cutouts, let's shift it out of the way.
- // We only do that if the inset is bigger than our own padding, since it's nicer to
- // align with
- if (mCutOutPaddingLeft > 0) {
- // if there's a cutout, let's use at least the rounded corner inset
- int cutoutPadding = Math.max(mCutOutPaddingLeft, mRoundedCornerPadding);
- paddingLeft = Math.max(cutoutPadding - leftMargin, 0);
- }
- if (mCutOutPaddingRight > 0) {
- // if there's a cutout, let's use at least the rounded corner inset
- int cutoutPadding = Math.max(mCutOutPaddingRight, mRoundedCornerPadding);
- paddingRight = Math.max(cutoutPadding - rightMargin, 0);
- }
-
- mDatePrivacyView.setPadding(paddingLeft,
- mWaterfallTopInset,
- paddingRight,
- 0);
- mStatusIconsView.setPadding(paddingLeft,
- mWaterfallTopInset,
- paddingRight,
- 0);
- }
-
- public void updateEverything() {
- post(() -> setClickable(!mExpanded));
- }
-
private void setContentMargins(View view, int marginStart, int marginEnd) {
MarginLayoutParams lp = (MarginLayoutParams) view.getLayoutParams();
lp.setMarginStart(marginStart);
lp.setMarginEnd(marginEnd);
view.setLayoutParams(lp);
}
-
- /**
- * Scroll the headers away.
- *
- * @param scrollY the scroll of the QSPanel container
- */
- public void setExpandedScrollAmount(int scrollY) {
- mStatusIconsView.setScrollY(scrollY);
- mDatePrivacyView.setScrollY(scrollY);
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
index ccaab1adaf26..64960e6ce23e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
@@ -16,154 +16,38 @@
package com.android.systemui.qs;
-import android.os.Bundle;
-
-import com.android.internal.colorextraction.ColorExtractor;
-import com.android.systemui.R;
-import com.android.systemui.battery.BatteryMeterViewController;
-import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.demomode.DemoMode;
-import com.android.systemui.demomode.DemoModeController;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
-import com.android.systemui.qs.carrier.QSCarrierGroupController;
import com.android.systemui.qs.dagger.QSScope;
-import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
-import com.android.systemui.statusbar.phone.StatusBarLocation;
-import com.android.systemui.statusbar.phone.StatusIconContainer;
-import com.android.systemui.statusbar.policy.Clock;
-import com.android.systemui.statusbar.policy.VariableDateViewController;
import com.android.systemui.util.ViewController;
-import java.util.List;
-
import javax.inject.Inject;
/**
* Controller for {@link QuickStatusBarHeader}.
*/
@QSScope
-class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader> implements
- ChipVisibilityListener {
+class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader> {
- private final QSCarrierGroupController mQSCarrierGroupController;
private final QuickQSPanelController mQuickQSPanelController;
- private final Clock mClockView;
- private final StatusBarIconController mStatusBarIconController;
- private final DemoModeController mDemoModeController;
- private final StatusIconContainer mIconContainer;
- private final StatusBarIconController.TintedIconManager mIconManager;
- private final DemoMode mDemoModeReceiver;
- private final QSExpansionPathInterpolator mQSExpansionPathInterpolator;
- private final FeatureFlags mFeatureFlags;
- private final BatteryMeterViewController mBatteryMeterViewController;
- private final StatusBarContentInsetsProvider mInsetsProvider;
-
- private final VariableDateViewController mVariableDateViewControllerDateView;
- private final VariableDateViewController mVariableDateViewControllerClockDateView;
- private final HeaderPrivacyIconsController mPrivacyIconsController;
-
private boolean mListening;
- private SysuiColorExtractor mColorExtractor;
- private ColorExtractor.OnColorsChangedListener mOnColorsChangedListener;
-
@Inject
QuickStatusBarHeaderController(QuickStatusBarHeader view,
- HeaderPrivacyIconsController headerPrivacyIconsController,
- StatusBarIconController statusBarIconController,
- DemoModeController demoModeController,
- QuickQSPanelController quickQSPanelController,
- QSCarrierGroupController.Builder qsCarrierGroupControllerBuilder,
- SysuiColorExtractor colorExtractor,
- QSExpansionPathInterpolator qsExpansionPathInterpolator,
- FeatureFlags featureFlags,
- VariableDateViewController.Factory variableDateViewControllerFactory,
- BatteryMeterViewController batteryMeterViewController,
- StatusBarContentInsetsProvider statusBarContentInsetsProvider,
- StatusBarIconController.TintedIconManager.Factory tintedIconManagerFactory) {
+ QuickQSPanelController quickQSPanelController
+ ) {
super(view);
- mPrivacyIconsController = headerPrivacyIconsController;
- mStatusBarIconController = statusBarIconController;
- mDemoModeController = demoModeController;
mQuickQSPanelController = quickQSPanelController;
- mQSExpansionPathInterpolator = qsExpansionPathInterpolator;
- mFeatureFlags = featureFlags;
- mBatteryMeterViewController = batteryMeterViewController;
- mInsetsProvider = statusBarContentInsetsProvider;
-
- mQSCarrierGroupController = qsCarrierGroupControllerBuilder
- .setQSCarrierGroup(mView.findViewById(R.id.carrier_group))
- .build();
- mClockView = mView.findViewById(R.id.clock);
- mIconContainer = mView.findViewById(R.id.statusIcons);
- mVariableDateViewControllerDateView = variableDateViewControllerFactory.create(
- mView.requireViewById(R.id.date)
- );
- mVariableDateViewControllerClockDateView = variableDateViewControllerFactory.create(
- mView.requireViewById(R.id.date_clock)
- );
-
- mIconManager = tintedIconManagerFactory.create(mIconContainer, StatusBarLocation.QS);
- mDemoModeReceiver = new ClockDemoModeReceiver(mClockView);
- mColorExtractor = colorExtractor;
- mOnColorsChangedListener = (extractor, which) -> {
- final boolean lightTheme = mColorExtractor.getNeutralColors().supportsDarkText();
- mClockView.onColorsChanged(lightTheme);
- };
- mColorExtractor.addOnColorsChangedListener(mOnColorsChangedListener);
-
- // Don't need to worry about tuner settings for this icon
- mBatteryMeterViewController.ignoreTunerUpdates();
- }
-
- @Override
- protected void onInit() {
- mBatteryMeterViewController.init();
}
@Override
protected void onViewAttached() {
- mPrivacyIconsController.onParentVisible();
- mPrivacyIconsController.setChipVisibilityListener(this);
- mIconContainer.addIgnoredSlot(
- getResources().getString(com.android.internal.R.string.status_bar_managed_profile));
- mIconContainer.addIgnoredSlot(
- getResources().getString(com.android.internal.R.string.status_bar_alarm_clock));
- mIconContainer.setShouldRestrictIcons(false);
- mStatusBarIconController.addIconGroup(mIconManager);
-
- mView.setIsSingleCarrier(mQSCarrierGroupController.isSingleCarrier());
- mQSCarrierGroupController
- .setOnSingleCarrierChangedListener(mView::setIsSingleCarrier);
-
- List<String> rssiIgnoredSlots = List.of(
- getResources().getString(com.android.internal.R.string.status_bar_mobile)
- );
-
- mView.onAttach(mIconManager, mQSExpansionPathInterpolator, rssiIgnoredSlots,
- mInsetsProvider, mFeatureFlags.isEnabled(Flags.COMBINED_QS_HEADERS));
-
- mDemoModeController.addCallback(mDemoModeReceiver);
-
- mVariableDateViewControllerDateView.init();
- mVariableDateViewControllerClockDateView.init();
}
@Override
protected void onViewDetached() {
- mColorExtractor.removeOnColorsChangedListener(mOnColorsChangedListener);
- mPrivacyIconsController.onParentInvisible();
- mStatusBarIconController.removeIconGroup(mIconManager);
- mQSCarrierGroupController.setOnSingleCarrierChangedListener(null);
- mDemoModeController.removeCallback(mDemoModeReceiver);
setListening(false);
}
public void setListening(boolean listening) {
- mQSCarrierGroupController.setListening(listening);
-
if (listening == mListening) {
return;
}
@@ -174,48 +58,9 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
if (mQuickQSPanelController.switchTileLayout(false)) {
mView.updateResources();
}
-
- if (listening) {
- mPrivacyIconsController.startListening();
- } else {
- mPrivacyIconsController.stopListening();
- }
- }
-
- @Override
- public void onChipVisibilityRefreshed(boolean visible) {
- mView.setChipVisibility(visible);
}
public void setContentMargins(int marginStart, int marginEnd) {
mQuickQSPanelController.setContentMargins(marginStart, marginEnd);
}
-
- private static class ClockDemoModeReceiver implements DemoMode {
- private Clock mClockView;
-
- @Override
- public List<String> demoCommands() {
- return List.of(COMMAND_CLOCK);
- }
-
- ClockDemoModeReceiver(Clock clockView) {
- mClockView = clockView;
- }
-
- @Override
- public void dispatchDemoCommand(String command, Bundle args) {
- mClockView.dispatchDemoCommand(command, args);
- }
-
- @Override
- public void onDemoModeStarted() {
- mClockView.onDemoModeStarted();
- }
-
- @Override
- public void onDemoModeFinished() {
- mClockView.onDemoModeFinished();
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
index 97390112c3ed..a319fb8d8756 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
@@ -40,7 +40,7 @@ import com.android.systemui.plugins.qs.QSContainerController;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.qs.QSEditEvent;
import com.android.systemui.qs.QSFragment;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.dagger.QSScope;
import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -57,7 +57,7 @@ import javax.inject.Inject;
@QSScope
public class QSCustomizerController extends ViewController<QSCustomizer> {
private final TileQueryHelper mTileQueryHelper;
- private final QSTileHost mQsTileHost;
+ private final QSHost mQsHost;
private final TileAdapter mTileAdapter;
private final ScreenLifecycle mScreenLifecycle;
private final KeyguardStateController mKeyguardStateController;
@@ -104,12 +104,12 @@ public class QSCustomizerController extends ViewController<QSCustomizer> {
@Inject
protected QSCustomizerController(QSCustomizer view, TileQueryHelper tileQueryHelper,
- QSTileHost qsTileHost, TileAdapter tileAdapter, ScreenLifecycle screenLifecycle,
+ QSHost qsHost, TileAdapter tileAdapter, ScreenLifecycle screenLifecycle,
KeyguardStateController keyguardStateController, LightBarController lightBarController,
ConfigurationController configurationController, UiEventLogger uiEventLogger) {
super(view);
mTileQueryHelper = tileQueryHelper;
- mQsTileHost = qsTileHost;
+ mQsHost = qsHost;
mTileAdapter = tileAdapter;
mScreenLifecycle = screenLifecycle;
mKeyguardStateController = keyguardStateController;
@@ -175,7 +175,7 @@ public class QSCustomizerController extends ViewController<QSCustomizer> {
private void reset() {
- mTileAdapter.resetTileSpecs(QSTileHost.getDefaultSpecs(getContext()));
+ mTileAdapter.resetTileSpecs(QSHost.getDefaultSpecs(getContext()));
}
public boolean isCustomizing() {
@@ -192,7 +192,7 @@ public class QSCustomizerController extends ViewController<QSCustomizer> {
mView.show(x, y, mTileAdapter);
mUiEventLogger.log(QSEditEvent.QS_EDIT_OPEN);
}
- mTileQueryHelper.queryTiles(mQsTileHost);
+ mTileQueryHelper.queryTiles(mQsHost);
mKeyguardStateController.addCallback(mKeyguardCallback);
mView.updateNavColors(mLightBarController);
}
@@ -258,13 +258,13 @@ public class QSCustomizerController extends ViewController<QSCustomizer> {
private void save() {
if (mTileQueryHelper.isFinished()) {
- mTileAdapter.saveSpecs(mQsTileHost);
+ mTileAdapter.saveSpecs(mQsHost);
}
}
private void setTileSpecs() {
List<String> specs = new ArrayList<>();
- for (QSTile tile : mQsTileHost.getTiles()) {
+ for (QSTile tile : mQsHost.getTiles()) {
specs.add(tile.getTileSpec());
}
mTileAdapter.setTileSpecs(specs);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index d84b12c714bd..6a05684a74e8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -45,7 +45,7 @@ import androidx.recyclerview.widget.RecyclerView.ViewHolder;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.R;
import com.android.systemui.qs.QSEditEvent;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.customize.TileAdapter.Holder;
import com.android.systemui.qs.customize.TileQueryHelper.TileInfo;
import com.android.systemui.qs.customize.TileQueryHelper.TileStateListener;
@@ -91,7 +91,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
private ItemDecoration mDecoration;
private final MarginTileDecoration mMarginDecoration;
private final int mMinNumTiles;
- private final QSTileHost mHost;
+ private final QSHost mHost;
private int mEditIndex;
private int mTileDividerIndex;
private int mFocusIndex;
@@ -117,7 +117,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
@Inject
public TileAdapter(
@QSThemedContext Context context,
- QSTileHost qsHost,
+ QSHost qsHost,
UiEventLogger uiEventLogger) {
mContext = context;
mHost = qsHost;
@@ -176,7 +176,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
mMarginDecoration.setHalfMargin(halfMargin);
}
- public void saveSpecs(QSTileHost host) {
+ public void saveSpecs(QSHost host) {
List<String> newSpecs = new ArrayList<>();
clearAccessibilityState();
for (int i = 1; i < mTiles.size() && mTiles.get(i) != null; i++) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
index 32a7916da70f..d9f448493591 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
@@ -38,7 +38,7 @@ import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTile.State;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.dagger.QSScope;
import com.android.systemui.qs.external.CustomTile;
import com.android.systemui.qs.tileimpl.QSTileImpl.DrawableIcon;
@@ -85,7 +85,7 @@ public class TileQueryHelper {
mListener = listener;
}
- public void queryTiles(QSTileHost host) {
+ public void queryTiles(QSHost host) {
mTiles.clear();
mSpecs.clear();
mFinished = false;
@@ -97,7 +97,7 @@ public class TileQueryHelper {
return mFinished;
}
- private void addCurrentAndStockTiles(QSTileHost host) {
+ private void addCurrentAndStockTiles(QSHost host) {
String stock = mContext.getString(R.string.quick_settings_tiles_stock);
String current = Settings.Secure.getString(mContext.getContentResolver(),
Settings.Secure.QS_TILES);
@@ -153,14 +153,14 @@ public class TileQueryHelper {
private class TileCollector implements QSTile.Callback {
private final List<TilePair> mQSTileList = new ArrayList<>();
- private final QSTileHost mQSTileHost;
+ private final QSHost mQSHost;
- TileCollector(List<QSTile> tilesToAdd, QSTileHost host) {
+ TileCollector(List<QSTile> tilesToAdd, QSHost host) {
for (QSTile tile: tilesToAdd) {
TilePair pair = new TilePair(tile);
mQSTileList.add(pair);
}
- mQSTileHost = host;
+ mQSHost = host;
if (tilesToAdd.isEmpty()) {
mBgExecutor.execute(this::finished);
}
@@ -168,7 +168,7 @@ public class TileQueryHelper {
private void finished() {
notifyTilesChanged(false);
- addPackageTiles(mQSTileHost);
+ addPackageTiles(mQSHost);
}
private void startListening() {
@@ -207,7 +207,7 @@ public class TileQueryHelper {
}
}
- private void addPackageTiles(final QSTileHost host) {
+ private void addPackageTiles(final QSHost host) {
mBgExecutor.execute(() -> {
Collection<QSTile> params = host.getTiles();
PackageManager pm = mContext.getPackageManager();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
index 01eb636f75d6..ce6b8d499ee0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
@@ -24,10 +24,8 @@ import android.view.LayoutInflater;
import android.view.View;
import com.android.systemui.R;
-import com.android.systemui.battery.BatteryMeterView;
import com.android.systemui.dagger.qualifiers.RootView;
import com.android.systemui.plugins.qs.QS;
-import com.android.systemui.privacy.OngoingPrivacyChip;
import com.android.systemui.qs.QSContainerImpl;
import com.android.systemui.qs.QSFooter;
import com.android.systemui.qs.QSFooterView;
@@ -37,7 +35,6 @@ import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QuickQSPanel;
import com.android.systemui.qs.QuickStatusBarHeader;
import com.android.systemui.qs.customize.QSCustomizer;
-import com.android.systemui.statusbar.phone.StatusIconContainer;
import javax.inject.Named;
@@ -106,12 +103,6 @@ public interface QSFragmentModule {
/** */
@Provides
- static BatteryMeterView providesBatteryMeterView(QuickStatusBarHeader quickStatusBarHeader) {
- return quickStatusBarHeader.findViewById(R.id.batteryRemainingIcon);
- }
-
- /** */
- @Provides
static QSFooterView providesQSFooterView(@RootView View view) {
return view.findViewById(R.id.qs_footer);
}
@@ -144,18 +135,4 @@ public interface QSFragmentModule {
static boolean providesQSUsingCollapsedLandscapeMedia(Context context) {
return useCollapsedMediaInLandscape(context.getResources());
}
-
- /** */
- @Provides
- @QSScope
- static OngoingPrivacyChip providesPrivacyChip(QuickStatusBarHeader qsHeader) {
- return qsHeader.findViewById(R.id.privacy_chip);
- }
-
- /** */
- @Provides
- @QSScope
- static StatusIconContainer providesStatusIconContainer(QuickStatusBarHeader qsHeader) {
- return qsHeader.findViewById(R.id.statusIcons);
- }
} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
index 27ae1710467b..431d6e847207 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
@@ -67,7 +67,7 @@ public interface QSModule {
static AutoTileManager provideAutoTileManager(
Context context,
AutoAddTracker.Builder autoAddTrackerBuilder,
- QSTileHost host,
+ QSHost host,
@Background Handler handler,
SecureSettings secureSettings,
HotspotController hotspotController,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
index e86bd7a30490..9f93e4926532 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
@@ -76,7 +76,8 @@ public class TileServiceManager {
this(tileServices, handler, userTracker, new TileLifecycleManager(handler,
tileServices.getContext(), tileServices,
new PackageManagerAdapter(tileServices.getContext()), broadcastDispatcher,
- new Intent().setComponent(component), userTracker.getUserHandle()));
+ new Intent(TileService.ACTION_QS_TILE).setComponent(component),
+ userTracker.getUserHandle()));
}
@VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceRequestController.kt b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceRequestController.kt
index 237b66e79ee5..d9e5580fc14c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceRequestController.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceRequestController.kt
@@ -25,13 +25,13 @@ import android.os.RemoteException
import android.util.Log
import androidx.annotation.VisibleForTesting
import com.android.internal.statusbar.IAddTileResultCallback
+import com.android.systemui.R
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.qs.QSTileHost
+import com.android.systemui.qs.QSHost
+import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.commandline.Command
import com.android.systemui.statusbar.commandline.CommandRegistry
import com.android.systemui.statusbar.phone.SystemUIDialog
-import com.android.systemui.R
-import com.android.systemui.statusbar.CommandQueue
import java.io.PrintWriter
import java.util.concurrent.atomic.AtomicBoolean
import java.util.function.Consumer
@@ -40,14 +40,14 @@ import javax.inject.Inject
private const val TAG = "TileServiceRequestController"
/**
- * Controller to interface between [TileRequestDialog] and [QSTileHost].
+ * Controller to interface between [TileRequestDialog] and [QSHost].
*/
class TileServiceRequestController constructor(
- private val qsTileHost: QSTileHost,
+ private val qsHost: QSHost,
private val commandQueue: CommandQueue,
private val commandRegistry: CommandRegistry,
private val eventLogger: TileRequestDialogEventLogger,
- private val dialogCreator: () -> TileRequestDialog = { TileRequestDialog(qsTileHost.context) }
+ private val dialogCreator: () -> TileRequestDialog = { TileRequestDialog(qsHost.context) }
) {
companion object {
@@ -93,7 +93,7 @@ class TileServiceRequestController constructor(
}
private fun addTile(componentName: ComponentName) {
- qsTileHost.addTile(componentName, true)
+ qsHost.addTile(componentName, true)
}
@VisibleForTesting
@@ -158,7 +158,7 @@ class TileServiceRequestController constructor(
private fun isTileAlreadyAdded(componentName: ComponentName): Boolean {
val spec = CustomTile.toSpec(componentName)
- return qsTileHost.indexOf(spec) != -1
+ return qsHost.indexOf(spec) != -1
}
inner class TileServiceRequestCommand : Command {
@@ -194,13 +194,13 @@ class TileServiceRequestController constructor(
private val commandQueue: CommandQueue,
private val commandRegistry: CommandRegistry
) {
- fun create(qsTileHost: QSTileHost): TileServiceRequestController {
+ fun create(qsHost: QSHost): TileServiceRequestController {
return TileServiceRequestController(
- qsTileHost,
+ qsHost,
commandQueue,
commandRegistry,
TileRequestDialogEventLogger()
)
}
}
-} \ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
index 84a18d8dd365..adc71657e680 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
@@ -39,7 +39,7 @@ import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -68,22 +68,24 @@ public class TileServices extends IQSService.Stub {
private final Context mContext;
private final Handler mMainHandler;
private final Provider<Handler> mHandlerProvider;
- private final QSTileHost mHost;
+ private final QSHost mHost;
private final KeyguardStateController mKeyguardStateController;
private final BroadcastDispatcher mBroadcastDispatcher;
private final CommandQueue mCommandQueue;
private final UserTracker mUserTracker;
+ private final StatusBarIconController mStatusBarIconController;
private int mMaxBound = DEFAULT_MAX_BOUND;
@Inject
public TileServices(
- QSTileHost host,
+ QSHost host,
@Main Provider<Handler> handlerProvider,
BroadcastDispatcher broadcastDispatcher,
UserTracker userTracker,
KeyguardStateController keyguardStateController,
- CommandQueue commandQueue) {
+ CommandQueue commandQueue,
+ StatusBarIconController statusBarIconController) {
mHost = host;
mKeyguardStateController = keyguardStateController;
mContext = mHost.getContext();
@@ -92,6 +94,7 @@ public class TileServices extends IQSService.Stub {
mMainHandler = mHandlerProvider.get();
mUserTracker = userTracker;
mCommandQueue = commandQueue;
+ mStatusBarIconController = statusBarIconController;
mCommandQueue.addCallback(mRequestListeningCallback);
}
@@ -99,7 +102,7 @@ public class TileServices extends IQSService.Stub {
return mContext;
}
- public QSTileHost getHost() {
+ public QSHost getHost() {
return mHost;
}
@@ -131,8 +134,7 @@ public class TileServices extends IQSService.Stub {
mTiles.remove(tile.getComponent());
final String slot = tile.getComponent().getClassName();
// TileServices doesn't know how to add more than 1 icon per slot, so remove all
- mMainHandler.post(() -> mHost.getIconController()
- .removeAllIconsForExternalSlot(slot));
+ mMainHandler.post(() -> mStatusBarIconController.removeAllIconsForSlot(slot));
}
}
@@ -309,7 +311,7 @@ public class TileServices extends IQSService.Stub {
mMainHandler.post(new Runnable() {
@Override
public void run() {
- StatusBarIconController iconController = mHost.getIconController();
+ StatusBarIconController iconController = mStatusBarIconController;
iconController.setIcon(componentName.getClassName(), statusIcon);
iconController.setExternalIcon(componentName.getClassName());
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt
index 03bb7a0f45da..8387c1dd60a5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt
@@ -71,8 +71,8 @@ interface FooterActionsInteractor {
/**
* Show the device monitoring dialog, expanded from [expandable] if it's not null.
*
- * Important: [quickSettingsContext] *must* be the [Context] associated to the [Quick Settings
- * fragment][com.android.systemui.qs.QSFragment].
+ * Important: [quickSettingsContext] *must* be the [Context] associated to the
+ * [Quick Settings fragment][com.android.systemui.qs.QSFragment].
*/
fun showDeviceMonitoringDialog(quickSettingsContext: Context, expandable: Expandable?)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt
index fbf32b3b99ea..f170ac1d9d4e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt
@@ -196,9 +196,9 @@ class FooterActionsViewModel(
* Observe the device monitoring dialog requests and show the dialog accordingly. This function
* will suspend indefinitely and will need to be cancelled to stop observing.
*
- * Important: [quickSettingsContext] must be the [Context] associated to the [Quick Settings
- * fragment][com.android.systemui.qs.QSFragment], and the call to this function must be
- * cancelled when that fragment is destroyed.
+ * Important: [quickSettingsContext] must be the [Context] associated to the
+ * [Quick Settings fragment][com.android.systemui.qs.QSFragment], and the call to this function
+ * must be cancelled when that fragment is destroyed.
*/
suspend fun observeDeviceMonitoringDialogRequests(quickSettingsContext: Context) {
footerActionsInteractor.deviceMonitoringDialogRequests.collect {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FontScalingTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/FontScalingTile.kt
index 9b4ac1b3437e..a915ddba4f1c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FontScalingTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FontScalingTile.kt
@@ -18,6 +18,7 @@ package com.android.systemui.qs.tiles
import android.content.Intent
import android.os.Handler
import android.os.Looper
+import android.provider.Settings
import android.view.View
import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.logging.MetricsLogger
@@ -72,9 +73,7 @@ constructor(
}
override fun newTileState(): QSTile.State {
- val state = QSTile.State()
- state.handlesLongClick = false
- return state
+ return QSTile.State()
}
override fun handleClick(view: View?) {
@@ -98,7 +97,7 @@ constructor(
}
override fun getLongClickIntent(): Intent? {
- return null
+ return Intent(Settings.ACTION_TEXT_READING_SETTINGS)
}
override fun getTileLabel(): CharSequence {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
index 645b1256e5f1..346acf958e51 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
@@ -16,7 +16,7 @@
package com.android.systemui.recents;
-import static com.android.systemui.shared.recents.utilities.Utilities.isTablet;
+import static com.android.systemui.shared.recents.utilities.Utilities.isLargeScreen;
import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE;
import static com.android.systemui.util.leak.RotationUtils.ROTATION_NONE;
import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE;
@@ -265,7 +265,7 @@ public class ScreenPinningRequest implements View.OnClickListener,
.setLayoutDirection(View.LAYOUT_DIRECTION_LOCALE);
View buttons = mLayout.findViewById(R.id.screen_pinning_buttons);
if (!QuickStepContract.isGesturalMode(mNavBarMode)
- && hasSoftNavigationBar(mContext.getDisplayId()) && !isTablet(mContext)) {
+ && hasSoftNavigationBar(mContext.getDisplayId()) && !isLargeScreen(mContext)) {
buttons.setLayoutDirection(View.LAYOUT_DIRECTION_LOCALE);
swapChildrenIfRtlAndVertical(buttons);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
index dd21be971b36..30509e23d186 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
@@ -124,8 +124,9 @@ class ScreenRecordPermissionDialog(
/**
* Starts screen capture after some countdown
+ *
* @param captureTarget target to capture (could be e.g. a task) or null to record the whole
- * screen
+ * screen
*/
private fun requestScreenCapture(captureTarget: MediaProjectionCaptureTarget?) {
val userContext = userContextProvider.userContext
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt
index 310baafbae1a..a8f99bef2423 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt
@@ -70,7 +70,7 @@ object ActionIntentCreator {
/**
* @return an ACTION_EDIT intent for the given URI, directed to config_screenshotEditor if
- * available.
+ * available.
*/
fun createEditIntent(uri: Uri, context: Context): Intent {
val editIntent = Intent(Intent.ACTION_EDIT)
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/WorkProfileMessageController.kt b/packages/SystemUI/src/com/android/systemui/screenshot/WorkProfileMessageController.kt
index 1b728b8aa9cc..236213cb023f 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/WorkProfileMessageController.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/WorkProfileMessageController.kt
@@ -44,7 +44,7 @@ constructor(
/**
* @return a populated WorkProfileFirstRunData object if a work profile first run message should
- * be shown
+ * be shown
*/
fun onScreenshotTaken(userHandle: UserHandle?): WorkProfileFirstRunData? {
if (userHandle == null) return null
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivity.java b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivity.java
index 1946b8eaee5b..eda38e45c98a 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivity.java
@@ -50,6 +50,7 @@ import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.notetask.NoteTaskController;
+import com.android.systemui.notetask.NoteTaskEntryPoint;
import com.android.systemui.settings.UserTracker;
import com.android.wm.shell.bubbles.Bubbles;
@@ -239,9 +240,8 @@ public class AppClipsTrampolineActivity extends Activity {
// Broadcast no longer required, setting it to null.
mKillAppClipsBroadcastIntent = null;
- // Expand the note bubble before returning the result. As App Clips API is only
- // available when in a bubble, isInMultiWindowMode is always false below.
- mNoteTaskController.showNoteTask(false);
+ // Expand the note bubble before returning the result.
+ mNoteTaskController.showNoteTask(NoteTaskEntryPoint.APP_CLIPS);
setResult(RESULT_OK, convertedData);
finish();
}
diff --git a/packages/SystemUI/src/com/android/systemui/scrim/ScrimDrawable.java b/packages/SystemUI/src/com/android/systemui/scrim/ScrimDrawable.java
index b36f0d7bacfc..10e2afe0baa9 100644
--- a/packages/SystemUI/src/com/android/systemui/scrim/ScrimDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/scrim/ScrimDrawable.java
@@ -27,6 +27,7 @@ import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.Rect;
+import android.graphics.RectF;
import android.graphics.Xfermode;
import android.graphics.drawable.Drawable;
import android.view.animation.DecelerateInterpolator;
@@ -41,7 +42,11 @@ import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
public class ScrimDrawable extends Drawable {
private static final String TAG = "ScrimDrawable";
+ private boolean mShouldUseLargeScreenSize;
private final Paint mPaint;
+ private final Path mPath = new Path();
+ private final RectF mBoundsRectF = new RectF();
+
private int mAlpha = 255;
private int mMainColor;
private ValueAnimator mColorAnimation;
@@ -49,11 +54,13 @@ public class ScrimDrawable extends Drawable {
private float mCornerRadius;
private ConcaveInfo mConcaveInfo;
private int mBottomEdgePosition;
+ private float mBottomEdgeRadius = -1;
private boolean mCornerRadiusEnabled;
public ScrimDrawable() {
mPaint = new Paint();
mPaint.setStyle(Paint.Style.FILL);
+ mShouldUseLargeScreenSize = false;
}
/**
@@ -133,6 +140,10 @@ public class ScrimDrawable extends Drawable {
return PixelFormat.TRANSLUCENT;
}
+ public void setShouldUseLargeScreenSize(boolean v) {
+ mShouldUseLargeScreenSize = v;
+ }
+
/**
* Corner radius used by either concave or convex corners.
*/
@@ -191,6 +202,10 @@ public class ScrimDrawable extends Drawable {
invalidateSelf();
}
+ public void setBottomEdgeRadius(float radius) {
+ mBottomEdgeRadius = radius;
+ }
+
@Override
public void draw(@NonNull Canvas canvas) {
mPaint.setColor(mMainColor);
@@ -198,9 +213,46 @@ public class ScrimDrawable extends Drawable {
if (mConcaveInfo != null) {
drawConcave(canvas);
} else if (mCornerRadiusEnabled && mCornerRadius > 0) {
- canvas.drawRoundRect(getBounds().left, getBounds().top, getBounds().right,
- getBounds().bottom,
- /* x radius*/ mCornerRadius, /* y radius*/ mCornerRadius, mPaint);
+ float topEdgeRadius = mCornerRadius;
+ float bottomEdgeRadius = mBottomEdgeRadius == -1.0 ? mCornerRadius : mBottomEdgeRadius;
+
+ mBoundsRectF.set(getBounds());
+
+ // When the back gesture causes the notification scrim to be scaled down,
+ // this offset "reveals" the rounded bottom edge as it "pulls away".
+ // We must *not* make this adjustment on largescreen shades (where the corner is sharp).
+ if (!mShouldUseLargeScreenSize && mBottomEdgeRadius != -1) {
+ mBoundsRectF.bottom -= bottomEdgeRadius;
+ }
+
+ // We need a box with rounded corners but its lower corners are not rounded on large
+ // screen devices in "portrait" orientation.
+ // Thus, we cannot draw a symmetric rounded rectangle via canvas.drawRoundRect()
+ // and must build a box with different corner radii at the top and at the bottom.
+ // Additionally, when the scrim is pushed to the very bottom of the screen, do not draw
+ // anything (drawing a rounded box with these specifications is not possible).
+ // TODO(b/271030611) perhaps this could be accomplished via Path.addRoundRect instead?
+ if (mBoundsRectF.bottom - mBoundsRectF.top > bottomEdgeRadius) {
+ mPath.reset();
+ mPath.moveTo(mBoundsRectF.right, mBoundsRectF.top + topEdgeRadius);
+ mPath.cubicTo(mBoundsRectF.right, mBoundsRectF.top + topEdgeRadius,
+ mBoundsRectF.right, mBoundsRectF.top,
+ mBoundsRectF.right - topEdgeRadius, mBoundsRectF.top);
+ mPath.lineTo(mBoundsRectF.left + topEdgeRadius, mBoundsRectF.top);
+ mPath.cubicTo(mBoundsRectF.left + topEdgeRadius, mBoundsRectF.top,
+ mBoundsRectF.left, mBoundsRectF.top,
+ mBoundsRectF.left, mBoundsRectF.top + topEdgeRadius);
+ mPath.lineTo(mBoundsRectF.left, mBoundsRectF.bottom - bottomEdgeRadius);
+ mPath.cubicTo(mBoundsRectF.left, mBoundsRectF.bottom - bottomEdgeRadius,
+ mBoundsRectF.left, mBoundsRectF.bottom,
+ mBoundsRectF.left + bottomEdgeRadius, mBoundsRectF.bottom);
+ mPath.lineTo(mBoundsRectF.right - bottomEdgeRadius, mBoundsRectF.bottom);
+ mPath.cubicTo(mBoundsRectF.right - bottomEdgeRadius, mBoundsRectF.bottom,
+ mBoundsRectF.right, mBoundsRectF.bottom,
+ mBoundsRectF.right, mBoundsRectF.bottom - bottomEdgeRadius);
+ mPath.close();
+ canvas.drawPath(mPath, mPaint);
+ }
} else {
canvas.drawRect(getBounds().left, getBounds().top, getBounds().right,
getBounds().bottom, mPaint);
diff --git a/packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java b/packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java
index f68e0429ef7c..fc89a9e637ec 100644
--- a/packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java
+++ b/packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java
@@ -20,6 +20,7 @@ import static java.lang.Float.isNaN;
import android.annotation.NonNull;
import android.content.Context;
+import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PorterDuff;
@@ -37,6 +38,7 @@ import androidx.core.graphics.ColorUtils;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.colorextraction.ColorExtractor;
+import com.android.systemui.util.LargeScreenUtils;
import java.util.concurrent.Executor;
@@ -102,6 +104,13 @@ public class ScrimView extends View {
@Override
protected void onDraw(Canvas canvas) {
if (mDrawable.getAlpha() > 0) {
+ Resources res = getResources();
+ // Scrim behind notification shade has sharp (not rounded) corners on large screens
+ // which scrim itself cannot know, so we set it here.
+ if (mDrawable instanceof ScrimDrawable) {
+ ((ScrimDrawable) mDrawable).setShouldUseLargeScreenSize(
+ LargeScreenUtils.shouldUseLargeScreenShadeHeader(res));
+ }
mDrawable.draw(canvas);
}
}
@@ -170,6 +179,15 @@ public class ScrimView extends View {
});
}
+ /**
+ * Set corner radius of the bottom edge of the Notification scrim.
+ */
+ public void setBottomEdgeRadius(float radius) {
+ if (mDrawable instanceof ScrimDrawable) {
+ ((ScrimDrawable) mDrawable).setBottomEdgeRadius(radius);
+ }
+ }
+
@VisibleForTesting
Drawable getDrawable() {
return mDrawable;
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt b/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
index 287e8101f86d..33a3125d1c68 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
@@ -19,6 +19,7 @@ package com.android.systemui.settings
import android.content.Context
import android.content.pm.UserInfo
import android.os.UserHandle
+import java.util.concurrent.CountDownLatch
import java.util.concurrent.Executor
/**
@@ -67,14 +68,25 @@ interface UserTracker : UserContentResolverProvider, UserContextProvider {
interface Callback {
/**
+ * Same as {@link onUserChanging(Int, Context, CountDownLatch)} but the latch will be
+ * auto-decremented after the completion of this method.
+ */
+ @JvmDefault
+ fun onUserChanging(newUser: Int, userContext: Context) {}
+
+ /**
* Notifies that the current user is being changed.
* Override this method to run things while the screen is frozen for the user switch.
* Please use {@link #onUserChanged} if the task doesn't need to push the unfreezing of the
* screen further. Please be aware that code executed in this callback will lengthen the
- * user switch duration.
+ * user switch duration. When overriding this method, countDown() MUST be called on the
+ * latch once execution is complete.
*/
@JvmDefault
- fun onUserChanging(newUser: Int, userContext: Context) {}
+ fun onUserChanging(newUser: Int, userContext: Context, latch: CountDownLatch) {
+ onUserChanging(newUser, userContext)
+ latch.countDown()
+ }
/**
* Notifies that the current user has changed.
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
index 3a5d0a7e0d26..0b2ae05b7c9b 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
@@ -182,9 +182,22 @@ open class UserTrackerImpl internal constructor(
Log.i(TAG, "Switching to user $newUserId")
setUserIdInternal(newUserId)
- notifySubscribers {
- onUserChanging(newUserId, userContext)
- }.await()
+
+ val list = synchronized(callbacks) {
+ callbacks.toList()
+ }
+ val latch = CountDownLatch(list.size)
+ list.forEach {
+ val callback = it.callback.get()
+ if (callback != null) {
+ it.executor.execute {
+ callback.onUserChanging(userId, userContext, latch)
+ }
+ } else {
+ latch.countDown()
+ }
+ }
+ latch.await()
}
@WorkerThread
@@ -224,25 +237,18 @@ open class UserTrackerImpl internal constructor(
}
}
- private inline fun notifySubscribers(
- crossinline action: UserTracker.Callback.() -> Unit
- ): CountDownLatch {
+ private inline fun notifySubscribers(crossinline action: UserTracker.Callback.() -> Unit) {
val list = synchronized(callbacks) {
callbacks.toList()
}
- val latch = CountDownLatch(list.size)
list.forEach {
if (it.callback.get() != null) {
it.executor.execute {
it.callback.get()?.action()
- latch.countDown()
}
- } else {
- latch.countDown()
}
}
- return latch
}
override fun dump(pw: PrintWriter, args: Array<out String>) {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManager.kt b/packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManager.kt
index e360ec20bd9b..a78b0aa97ea1 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManager.kt
@@ -31,7 +31,7 @@ operator fun ConstraintChange?.plus(other: ConstraintChange?): ConstraintChange?
/**
* Contains all changes that need to be performed to the different [ConstraintSet] in
- * [LargeScreenShadeHeaderController].
+ * [ShadeHeaderController].
*/
data class ConstraintsChanges(
val qqsConstraintsChanges: ConstraintChange? = null,
@@ -46,7 +46,7 @@ data class ConstraintsChanges(
}
/**
- * Determines [ConstraintChanges] for [LargeScreenShadeHeaderController] based on configurations.
+ * Determines [ConstraintChanges] for [ShadeHeaderController] based on configurations.
*
* Given that the number of different scenarios is not that large, having specific methods instead
* of a full map between state and [ConstraintSet] was preferred.
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationController.kt b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationController.kt
index 639172f9e37a..b445000c467d 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationController.kt
@@ -48,7 +48,10 @@ constructor(
setOf(
ViewIdToTranslate(R.id.quick_settings_panel, START, filterShade),
ViewIdToTranslate(R.id.notification_stack_scroller, END, filterShade),
- ViewIdToTranslate(R.id.rightLayout, END, filterShade),
+ ViewIdToTranslate(R.id.statusIcons, END, filterShade),
+ ViewIdToTranslate(R.id.privacy_container, END, filterShade),
+ ViewIdToTranslate(R.id.batteryRemainingIcon, END, filterShade),
+ ViewIdToTranslate(R.id.carrier_group, END, filterShade),
ViewIdToTranslate(R.id.clock, START, filterShade),
ViewIdToTranslate(R.id.date, START, filterShade)),
progressProvider = progressProvider)
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index f4640ad2e3cd..b1987c151e5f 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -23,6 +23,7 @@ import static android.view.View.VISIBLE;
import static androidx.constraintlayout.widget.ConstraintSet.END;
import static androidx.constraintlayout.widget.ConstraintSet.PARENT_ID;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION;
import static com.android.keyguard.KeyguardClockSwitch.LARGE;
import static com.android.keyguard.KeyguardClockSwitch.SMALL;
import static com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE;
@@ -71,6 +72,7 @@ import android.os.VibrationEffect;
import android.provider.Settings;
import android.transition.ChangeBounds;
import android.transition.Transition;
+import android.transition.TransitionListenerAdapter;
import android.transition.TransitionManager;
import android.transition.TransitionSet;
import android.transition.TransitionValues;
@@ -98,6 +100,7 @@ import android.widget.FrameLayout;
import androidx.constraintlayout.widget.ConstraintSet;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.policy.SystemBarUtils;
@@ -293,7 +296,19 @@ public final class NotificationPanelViewController implements Dumpable {
* custom clock animation is in use.
*/
private static final int KEYGUARD_STATUS_VIEW_CUSTOM_CLOCK_MOVE_DURATION = 1000;
+ /**
+ * Whether the Shade should animate to reflect Back gesture progress.
+ * To minimize latency at runtime, we cache this, else we'd be reading it every time
+ * updateQsExpansion() is called... and it's called very often.
+ *
+ * Whenever we change this flag, SysUI is restarted, so it's never going to be "stale".
+ */
+ public final boolean mAnimateBack;
+ /**
+ * The minimum scale to "squish" the Shade and associated elements down to, for Back gesture
+ */
+ public static final float SHADE_BACK_ANIM_MIN_SCALE = 0.9f;
private final StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
private final Resources mResources;
private final KeyguardStateController mKeyguardStateController;
@@ -336,7 +351,7 @@ public final class NotificationPanelViewController implements Dumpable {
private final ScrimController mScrimController;
private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
private final TapAgainViewController mTapAgainViewController;
- private final LargeScreenShadeHeaderController mLargeScreenShadeHeaderController;
+ private final ShadeHeaderController mShadeHeaderController;
private final boolean mVibrateOnOpening;
private final VelocityTracker mVelocityTracker = VelocityTracker.obtain();
private final FlingAnimationUtils mFlingAnimationUtilsClosing;
@@ -353,6 +368,7 @@ public final class NotificationPanelViewController implements Dumpable {
private final NotificationGutsManager mGutsManager;
private final AlternateBouncerInteractor mAlternateBouncerInteractor;
private final QuickSettingsController mQsController;
+ private final InteractionJankMonitor mInteractionJankMonitor;
private long mDownTime;
private boolean mTouchSlopExceededBeforeDown;
@@ -361,6 +377,8 @@ public final class NotificationPanelViewController implements Dumpable {
private CentralSurfaces mCentralSurfaces;
private HeadsUpManagerPhone mHeadsUpManager;
private float mExpandedHeight = 0;
+ /** The current squish amount for the predictive back animation */
+ private float mCurrentBackProgress = 0.0f;
private boolean mTracking;
private boolean mHintAnimationRunning;
private KeyguardBottomAreaView mKeyguardBottomArea;
@@ -465,7 +483,7 @@ public final class NotificationPanelViewController implements Dumpable {
private int mPanelAlpha;
private Runnable mPanelAlphaEndAction;
private float mBottomAreaShadeAlpha;
- private final ValueAnimator mBottomAreaShadeAlphaAnimator;
+ final ValueAnimator mBottomAreaShadeAlphaAnimator;
private final AnimatableProperty mPanelAlphaAnimator = AnimatableProperty.from("panelAlpha",
NotificationPanelView::setPanelAlphaInternal,
NotificationPanelView::getCurrentPanelAlpha,
@@ -597,7 +615,6 @@ public final class NotificationPanelViewController implements Dumpable {
private int mLockscreenToDreamingTransitionTranslationY;
private int mGoneToDreamingTransitionTranslationY;
private int mLockscreenToOccludedTransitionTranslationY;
- private boolean mUnocclusionTransitionFlagEnabled = false;
private final Runnable mFlingCollapseRunnable = () -> fling(0, false /* expand */,
mNextCollapseSpeedUpFactor, false /* expandBecauseOfFalsing */);
@@ -643,6 +660,19 @@ public final class NotificationPanelViewController implements Dumpable {
step.getTransitionState() == TransitionState.RUNNING;
};
+ private final TransitionListenerAdapter mKeyguardStatusAlignmentTransitionListener =
+ new TransitionListenerAdapter() {
+ @Override
+ public void onTransitionCancel(Transition transition) {
+ mInteractionJankMonitor.cancel(CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION);
+ }
+
+ @Override
+ public void onTransitionEnd(Transition transition) {
+ mInteractionJankMonitor.end(CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION);
+ }
+ };
+
@Inject
public NotificationPanelViewController(NotificationPanelView view,
@Main Handler handler,
@@ -693,7 +723,7 @@ public final class NotificationPanelViewController implements Dumpable {
FragmentService fragmentService,
ContentResolver contentResolver,
RecordingController recordingController,
- LargeScreenShadeHeaderController largeScreenShadeHeaderController,
+ ShadeHeaderController shadeHeaderController,
ScreenOffAnimationController screenOffAnimationController,
LockscreenGestureLogger lockscreenGestureLogger,
ShadeExpansionStateManager shadeExpansionStateManager,
@@ -707,6 +737,7 @@ public final class NotificationPanelViewController implements Dumpable {
NotificationStackSizeCalculator notificationStackSizeCalculator,
UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
ShadeTransitionController shadeTransitionController,
+ InteractionJankMonitor interactionJankMonitor,
SystemClock systemClock,
KeyguardBottomAreaViewModel keyguardBottomAreaViewModel,
KeyguardBottomAreaInteractor keyguardBottomAreaInteractor,
@@ -721,6 +752,7 @@ public final class NotificationPanelViewController implements Dumpable {
DumpManager dumpManager,
KeyguardLongPressViewModel keyguardLongPressViewModel,
KeyguardInteractor keyguardInteractor) {
+ mInteractionJankMonitor = interactionJankMonitor;
keyguardStateController.addCallback(new KeyguardStateController.Callback() {
@Override
public void onKeyguardFadingAwayChanged() {
@@ -813,9 +845,10 @@ public final class NotificationPanelViewController implements Dumpable {
mSplitShadeEnabled =
LargeScreenUtils.shouldUseSplitNotificationShade(mResources);
mView.setWillNotDraw(!DEBUG_DRAWABLE);
- mLargeScreenShadeHeaderController = largeScreenShadeHeaderController;
+ mShadeHeaderController = shadeHeaderController;
mLayoutInflater = layoutInflater;
mFeatureFlags = featureFlags;
+ mAnimateBack = mFeatureFlags.isEnabled(Flags.WM_SHADE_ANIMATE_BACK_GESTURE);
mFalsingCollector = falsingCollector;
mPowerManager = powerManager;
mWakeUpCoordinator = coordinator;
@@ -886,7 +919,6 @@ public final class NotificationPanelViewController implements Dumpable {
mNotificationPanelUnfoldAnimationController = unfoldComponent.map(
SysUIUnfoldComponent::getNotificationPanelUnfoldAnimationController);
- mUnocclusionTransitionFlagEnabled = featureFlags.isEnabled(Flags.UNOCCLUSION_TRANSITION);
updateUserSwitcherFlags();
mKeyguardBottomAreaViewModel = keyguardBottomAreaViewModel;
mKeyguardBottomAreaInteractor = keyguardBottomAreaInteractor;
@@ -1040,67 +1072,55 @@ public final class NotificationPanelViewController implements Dumpable {
}
mTapAgainViewController.init();
- mLargeScreenShadeHeaderController.init();
+ mShadeHeaderController.init();
mKeyguardUnfoldTransition.ifPresent(u -> u.setup(mView));
mNotificationPanelUnfoldAnimationController.ifPresent(controller ->
controller.setup(mNotificationContainerParent));
- if (mUnocclusionTransitionFlagEnabled) {
- // Dreaming->Lockscreen
- collectFlow(mView, mKeyguardTransitionInteractor.getDreamingToLockscreenTransition(),
- mDreamingToLockscreenTransition, mMainDispatcher);
- collectFlow(mView, mDreamingToLockscreenTransitionViewModel.getLockscreenAlpha(),
- setTransitionAlpha(mNotificationStackScrollLayoutController),
- mMainDispatcher);
- collectFlow(mView, mDreamingToLockscreenTransitionViewModel.lockscreenTranslationY(
- mDreamingToLockscreenTransitionTranslationY),
- setTransitionY(mNotificationStackScrollLayoutController),
- mMainDispatcher);
-
- // Occluded->Lockscreen
- collectFlow(mView, mKeyguardTransitionInteractor.getOccludedToLockscreenTransition(),
- mOccludedToLockscreenTransition, mMainDispatcher);
- collectFlow(mView, mOccludedToLockscreenTransitionViewModel.getLockscreenAlpha(),
- setTransitionAlpha(mNotificationStackScrollLayoutController),
- mMainDispatcher);
- collectFlow(mView, mOccludedToLockscreenTransitionViewModel.lockscreenTranslationY(
- mOccludedToLockscreenTransitionTranslationY),
- setTransitionY(mNotificationStackScrollLayoutController),
- mMainDispatcher);
-
- // Lockscreen->Dreaming
- collectFlow(mView, mKeyguardTransitionInteractor.getLockscreenToDreamingTransition(),
- mLockscreenToDreamingTransition, mMainDispatcher);
- collectFlow(mView, mLockscreenToDreamingTransitionViewModel.getLockscreenAlpha(),
- setTransitionAlpha(mNotificationStackScrollLayoutController),
- mMainDispatcher);
- collectFlow(mView, mLockscreenToDreamingTransitionViewModel.lockscreenTranslationY(
- mLockscreenToDreamingTransitionTranslationY),
- setTransitionY(mNotificationStackScrollLayoutController),
- mMainDispatcher);
-
- // Gone->Dreaming
- collectFlow(mView, mKeyguardTransitionInteractor.getGoneToDreamingTransition(),
- mGoneToDreamingTransition, mMainDispatcher);
- collectFlow(mView, mGoneToDreamingTransitionViewModel.getLockscreenAlpha(),
- setTransitionAlpha(mNotificationStackScrollLayoutController),
- mMainDispatcher);
- collectFlow(mView, mGoneToDreamingTransitionViewModel.lockscreenTranslationY(
- mGoneToDreamingTransitionTranslationY),
- setTransitionY(mNotificationStackScrollLayoutController),
- mMainDispatcher);
-
- // Lockscreen->Occluded
- collectFlow(mView, mKeyguardTransitionInteractor.getLockscreenToOccludedTransition(),
- mLockscreenToOccludedTransition, mMainDispatcher);
- collectFlow(mView, mLockscreenToOccludedTransitionViewModel.getLockscreenAlpha(),
- setTransitionAlpha(mNotificationStackScrollLayoutController),
- mMainDispatcher);
- collectFlow(mView, mLockscreenToOccludedTransitionViewModel.lockscreenTranslationY(
- mLockscreenToOccludedTransitionTranslationY),
- setTransitionY(mNotificationStackScrollLayoutController),
- mMainDispatcher);
- }
+ // Dreaming->Lockscreen
+ collectFlow(mView, mKeyguardTransitionInteractor.getDreamingToLockscreenTransition(),
+ mDreamingToLockscreenTransition, mMainDispatcher);
+ collectFlow(mView, mDreamingToLockscreenTransitionViewModel.getLockscreenAlpha(),
+ setTransitionAlpha(mNotificationStackScrollLayoutController), mMainDispatcher);
+ collectFlow(mView, mDreamingToLockscreenTransitionViewModel.lockscreenTranslationY(
+ mDreamingToLockscreenTransitionTranslationY),
+ setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
+
+ // Occluded->Lockscreen
+ collectFlow(mView, mKeyguardTransitionInteractor.getOccludedToLockscreenTransition(),
+ mOccludedToLockscreenTransition, mMainDispatcher);
+ collectFlow(mView, mOccludedToLockscreenTransitionViewModel.getLockscreenAlpha(),
+ setTransitionAlpha(mNotificationStackScrollLayoutController), mMainDispatcher);
+ collectFlow(mView, mOccludedToLockscreenTransitionViewModel.lockscreenTranslationY(
+ mOccludedToLockscreenTransitionTranslationY),
+ setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
+
+ // Lockscreen->Dreaming
+ collectFlow(mView, mKeyguardTransitionInteractor.getLockscreenToDreamingTransition(),
+ mLockscreenToDreamingTransition, mMainDispatcher);
+ collectFlow(mView, mLockscreenToDreamingTransitionViewModel.getLockscreenAlpha(),
+ setTransitionAlpha(mNotificationStackScrollLayoutController), mMainDispatcher);
+ collectFlow(mView, mLockscreenToDreamingTransitionViewModel.lockscreenTranslationY(
+ mLockscreenToDreamingTransitionTranslationY),
+ setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
+
+ // Gone->Dreaming
+ collectFlow(mView, mKeyguardTransitionInteractor.getGoneToDreamingTransition(),
+ mGoneToDreamingTransition, mMainDispatcher);
+ collectFlow(mView, mGoneToDreamingTransitionViewModel.getLockscreenAlpha(),
+ setTransitionAlpha(mNotificationStackScrollLayoutController), mMainDispatcher);
+ collectFlow(mView, mGoneToDreamingTransitionViewModel.lockscreenTranslationY(
+ mGoneToDreamingTransitionTranslationY),
+ setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
+
+ // Lockscreen->Occluded
+ collectFlow(mView, mKeyguardTransitionInteractor.getLockscreenToOccludedTransition(),
+ mLockscreenToOccludedTransition, mMainDispatcher);
+ collectFlow(mView, mLockscreenToOccludedTransitionViewModel.getLockscreenAlpha(),
+ setTransitionAlpha(mNotificationStackScrollLayoutController), mMainDispatcher);
+ collectFlow(mView, mLockscreenToOccludedTransitionViewModel.lockscreenTranslationY(
+ mLockscreenToOccludedTransitionTranslationY),
+ setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
}
@VisibleForTesting
@@ -1197,6 +1217,7 @@ public final class NotificationPanelViewController implements Dumpable {
}
private void onSplitShadeEnabledChanged() {
+ mShadeLog.logSplitShadeChanged(mSplitShadeEnabled);
// when we switch between split shade and regular shade we want to enforce setting qs to
// the default state: expanded for split shade and collapsed otherwise
if (!isOnKeyguard() && mPanelExpanded) {
@@ -1553,6 +1574,7 @@ public final class NotificationPanelViewController implements Dumpable {
int statusConstraint = shouldBeCentered ? PARENT_ID : R.id.qs_edge_guideline;
constraintSet.connect(R.id.keyguard_status_view, END, statusConstraint, END);
if (animate) {
+ mInteractionJankMonitor.begin(mView, CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION);
ChangeBounds transition = new ChangeBounds();
if (mSplitShadeEnabled) {
// Excluding media from the transition on split-shade, as it doesn't transition
@@ -1576,6 +1598,7 @@ public final class NotificationPanelViewController implements Dumpable {
// The clock container can sometimes be null. If it is, just fall back to the
// old animation rather than setting up the custom animations.
if (clockContainerView == null || clockContainerView.getChildCount() == 0) {
+ transition.addListener(mKeyguardStatusAlignmentTransitionListener);
TransitionManager.beginDelayedTransition(
mNotificationContainerParent, transition);
} else {
@@ -1594,10 +1617,11 @@ public final class NotificationPanelViewController implements Dumpable {
adapter.setDuration(KEYGUARD_STATUS_VIEW_CUSTOM_CLOCK_MOVE_DURATION);
adapter.addTarget(clockView);
set.addTransition(adapter);
-
+ set.addListener(mKeyguardStatusAlignmentTransitionListener);
TransitionManager.beginDelayedTransition(mNotificationContainerParent, set);
}
} else {
+ transition.addListener(mKeyguardStatusAlignmentTransitionListener);
TransitionManager.beginDelayedTransition(
mNotificationContainerParent, transition);
}
@@ -1777,7 +1801,7 @@ public final class NotificationPanelViewController implements Dumpable {
if (animate && !isFullyCollapsed()) {
animateCloseQs(true);
} else {
- mQsController.closeQs();
+ closeQsIfPossible();
}
mNotificationStackScrollLayoutController.setOverScrollAmount(0f, true /* onTop */, animate,
!animate /* cancelAnimators */);
@@ -1914,7 +1938,6 @@ public final class NotificationPanelViewController implements Dumpable {
// we want to perform an overshoot animation when flinging open
final boolean addOverscroll =
expand
- && !mSplitShadeEnabled // Split shade has its own overscroll logic
&& mStatusBarStateController.getState() != KEYGUARD
&& mOverExpansion == 0.0f
&& vel >= 0;
@@ -1965,6 +1988,14 @@ public final class NotificationPanelViewController implements Dumpable {
if (mFixedDuration != NO_FIXED_DURATION) {
animator.setDuration(mFixedDuration);
}
+
+ // Reset Predictive Back animation's transform after Shade is completely hidden.
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ resetBackTransformation();
+ }
+ });
}
animator.addListener(new AnimatorListenerAdapter() {
private boolean mCancelled;
@@ -2189,6 +2220,53 @@ public final class NotificationPanelViewController implements Dumpable {
}
}
+ /**
+ * When the back gesture triggers a fully-expanded shade --> QQS shade collapse transition,
+ * the expansionFraction goes down from 1.0 --> 0.0 (collapsing), so the current "squish" amount
+ * (mCurrentBackProgress) must be un-applied from various UI elements in tandem, such that,
+ * as the shade ends up in its half-expanded state (with QQS above), it is back at 100% scale.
+ * Without this, the shade would collapse, and stay squished.
+ */
+ public void adjustBackAnimationScale(float expansionFraction) {
+ if (expansionFraction > 0.0f) { // collapsing
+ float animatedFraction = expansionFraction * mCurrentBackProgress;
+ applyBackScaling(animatedFraction);
+ } else {
+ // collapsed! reset, so that if we re-expand shade, it won't start off "squished"
+ mCurrentBackProgress = 0;
+ }
+ }
+
+ //TODO(b/270981268): allow cancelling back animation mid-flight
+ /** Called when Back gesture has been committed (i.e. a back event has definitely occurred) */
+ public void onBackPressed() {
+ closeQsIfPossible();
+ }
+ /** Sets back progress. */
+ public void onBackProgressed(float progressFraction) {
+ // TODO: non-linearly transform progress fraction into squish amount (ease-in, linear out)
+ mCurrentBackProgress = progressFraction;
+ applyBackScaling(progressFraction);
+ }
+
+ /** Resets back progress. */
+ public void resetBackTransformation() {
+ mCurrentBackProgress = 0.0f;
+ applyBackScaling(0.0f);
+ }
+
+ /** Scales multiple elements in tandem to achieve the illusion of the QS+Shade shrinking
+ * as a single visual element (used by the Predictive Back Gesture preview animation).
+ * fraction = 0 implies "no scaling", and 1 means "scale down to minimum size (90%)".
+ */
+ public void applyBackScaling(float fraction) {
+ if (mNotificationContainerParent == null) {
+ return;
+ }
+ float scale = MathUtils.lerp(1.0f, SHADE_BACK_ANIM_MIN_SCALE, fraction);
+ mNotificationContainerParent.applyBackScaling(scale, mSplitShadeEnabled);
+ mScrimController.applyBackScaling(scale);
+ }
/** */
public float getLockscreenShadeDragProgress() {
// mTransitioningToFullShadeProgress > 0 means we're doing regular lockscreen to shade
@@ -2480,9 +2558,6 @@ public final class NotificationPanelViewController implements Dumpable {
}
private void onExpandingFinished() {
- if (!mUnocclusionTransitionFlagEnabled) {
- mScrimController.onExpandingFinished();
- }
mNotificationStackScrollLayoutController.onExpansionStopped();
mHeadsUpManager.onExpandingFinished();
mConversationNotificationManager.onNotificationPanelExpandStateChanged(isFullyCollapsed());
@@ -2590,9 +2665,14 @@ public final class NotificationPanelViewController implements Dumpable {
return;
}
mOverExpansion = overExpansion;
- // Translating the quick settings by half the overexpansion to center it in the background
- // frame
- mQsController.updateQsFrameTranslation();
+ if (mSplitShadeEnabled) {
+ mQsController.setOverScrollAmount((int) overExpansion);
+ mScrimController.setNotificationsOverScrollAmount((int) overExpansion);
+ } else {
+ // Translating the quick settings by half the overexpansion to center it in the
+ // background frame
+ mQsController.updateQsFrameTranslation();
+ }
mNotificationStackScrollLayoutController.setOverExpansion(overExpansion);
}
@@ -3332,7 +3412,7 @@ public final class NotificationPanelViewController implements Dumpable {
}
public void disable(int state1, int state2, boolean animated) {
- mLargeScreenShadeHeaderController.disable(state1, state2, animated);
+ mShadeHeaderController.disable(state1, state2, animated);
}
/**
@@ -3594,7 +3674,7 @@ public final class NotificationPanelViewController implements Dumpable {
private void fling(float vel, boolean expand, float collapseSpeedUpFactor,
boolean expandBecauseOfFalsing) {
- float target = expand ? getMaxPanelHeight() : 0;
+ float target = expand ? getMaxPanelTransitionDistance() : 0;
if (!expand) {
setClosing(true);
}
@@ -3679,7 +3759,7 @@ public final class NotificationPanelViewController implements Dumpable {
float maxPanelHeight = getMaxPanelTransitionDistance();
if (mHeightAnimator == null) {
// Split shade has its own overscroll logic
- if (mTracking && !mSplitShadeEnabled) {
+ if (mTracking) {
float overExpansionPixels = Math.max(0, h - maxPanelHeight);
setOverExpansionInternal(overExpansionPixels, true /* isFromGesture */);
}
@@ -4025,9 +4105,17 @@ public final class NotificationPanelViewController implements Dumpable {
return mExpandingFromHeadsUp;
}
- /** TODO: remove need for this delegate (b/254870148) */
- public void closeQs() {
- mQsController.closeQs();
+ /**
+ * We don't always want to close QS when requested as shade might be in a different state
+ * already e.g. when going from collapse to expand very quickly. In that case StatusBar
+ * window might send signal to collapse QS but we might be already expanding and in split
+ * shade QS are always expanded
+ */
+ private void closeQsIfPossible() {
+ boolean openOrOpening = isShadeFullyOpen() || isExpanding();
+ if (!(mSplitShadeEnabled && openOrOpening)) {
+ mQsController.closeQs();
+ }
}
/** TODO: remove need for this delegate (b/254870148) */
@@ -4855,6 +4943,11 @@ public final class NotificationPanelViewController implements Dumpable {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
+ if (QuickStepContract.ALLOW_BACK_GESTURE_IN_SHADE && mAnimateBack) {
+ // Cache the gesture insets now, so we can quickly query them during
+ // ACTION_MOVE and decide whether to intercept events for back gesture anim.
+ mQsController.updateGestureInsetsCache();
+ }
mShadeLog.logMotionEvent(event, "onTouch: down action");
startExpandMotion(x, y, false /* startTracking */, mExpandedHeight);
mMinExpandHeight = 0.0f;
@@ -4904,6 +4997,12 @@ public final class NotificationPanelViewController implements Dumpable {
}
break;
case MotionEvent.ACTION_MOVE:
+ // If the shade is half-collapsed, a horizontal swipe inwards from L/R edge
+ // must be routed to the back gesture (which shows a preview animation).
+ if (QuickStepContract.ALLOW_BACK_GESTURE_IN_SHADE && mAnimateBack
+ && mQsController.shouldBackBypassQuickSettings(x)) {
+ return false;
+ }
if (isFullyCollapsed()) {
// If panel is fully collapsed, reset haptic effect before adding movement.
mHasVibratedOnOpen = false;
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
index 60fa865b83bc..87350b465895 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
@@ -38,8 +38,6 @@ import com.android.keyguard.dagger.KeyguardBouncerComponent;
import com.android.systemui.R;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.dock.DockManager;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
@@ -132,7 +130,6 @@ public class NotificationShadeWindowViewController {
NotificationInsetsController notificationInsetsController,
AmbientState ambientState,
PulsingGestureListener pulsingGestureListener,
- FeatureFlags featureFlags,
KeyguardBouncerViewModel keyguardBouncerViewModel,
KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory,
AlternateBouncerInteractor alternateBouncerInteractor,
@@ -165,10 +162,8 @@ public class NotificationShadeWindowViewController {
keyguardBouncerViewModel,
keyguardBouncerComponentFactory);
- if (featureFlags.isEnabled(Flags.UNOCCLUSION_TRANSITION)) {
- collectFlow(mView, keyguardTransitionInteractor.getLockscreenToDreamingTransition(),
- mLockscreenToDreamingTransition);
- }
+ collectFlow(mView, keyguardTransitionInteractor.getLockscreenToDreamingTransition(),
+ mLockscreenToDreamingTransition);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt b/packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt
index de02115184b6..fb7c5c2e31fa 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt
@@ -29,8 +29,6 @@ import androidx.constraintlayout.widget.ConstraintSet.START
import androidx.constraintlayout.widget.ConstraintSet.TOP
import com.android.systemui.R
import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
import com.android.systemui.fragments.FragmentService
import com.android.systemui.navigationbar.NavigationModeController
import com.android.systemui.plugins.qs.QS
@@ -49,14 +47,13 @@ import kotlin.reflect.KMutableProperty0
internal const val INSET_DEBOUNCE_MILLIS = 500L
class NotificationsQSContainerController @Inject constructor(
- view: NotificationsQuickSettingsContainer,
- private val navigationModeController: NavigationModeController,
- private val overviewProxyService: OverviewProxyService,
- private val largeScreenShadeHeaderController: LargeScreenShadeHeaderController,
- private val shadeExpansionStateManager: ShadeExpansionStateManager,
- private val featureFlags: FeatureFlags,
- private val fragmentService: FragmentService,
- @Main private val delayableExecutor: DelayableExecutor
+ view: NotificationsQuickSettingsContainer,
+ private val navigationModeController: NavigationModeController,
+ private val overviewProxyService: OverviewProxyService,
+ private val shadeHeaderController: ShadeHeaderController,
+ private val shadeExpansionStateManager: ShadeExpansionStateManager,
+ private val fragmentService: FragmentService,
+ @Main private val delayableExecutor: DelayableExecutor
) : ViewController<NotificationsQuickSettingsContainer>(view), QSContainerController {
private var qsExpanded = false
@@ -75,8 +72,6 @@ class NotificationsQSContainerController @Inject constructor(
private var panelMarginHorizontal = 0
private var topMargin = 0
- private val useCombinedQSHeaders = featureFlags.isEnabled(Flags.COMBINED_QS_HEADERS)
-
private var isGestureNavigation = true
private var taskbarVisible = false
private val taskbarVisibilityListener: OverviewProxyListener = object : OverviewProxyListener {
@@ -184,7 +179,7 @@ class NotificationsQSContainerController @Inject constructor(
override fun setCustomizerShowing(showing: Boolean, animationDuration: Long) {
if (showing != isQSCustomizing) {
isQSCustomizing = showing
- largeScreenShadeHeaderController.startCustomizingAnimation(showing, animationDuration)
+ shadeHeaderController.startCustomizingAnimation(showing, animationDuration)
updateBottomSpacing()
}
}
@@ -250,9 +245,7 @@ class NotificationsQSContainerController @Inject constructor(
if (largeScreenShadeHeaderActive) {
constraintSet.constrainHeight(R.id.split_shade_status_bar, largeScreenShadeHeaderHeight)
} else {
- if (useCombinedQSHeaders) {
- constraintSet.constrainHeight(R.id.split_shade_status_bar, WRAP_CONTENT)
- }
+ constraintSet.constrainHeight(R.id.split_shade_status_bar, WRAP_CONTENT)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationsQuickSettingsContainer.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationsQuickSettingsContainer.java
index f73dde632051..7dff6ea99029 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationsQuickSettingsContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationsQuickSettingsContainer.java
@@ -20,6 +20,7 @@ import android.app.Fragment;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Canvas;
+import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import android.view.WindowInsets;
@@ -55,6 +56,13 @@ public class NotificationsQuickSettingsContainer extends ConstraintLayout
private QS mQs;
private View mQSContainer;
+ /**
+ * These are used to compute the bounding box containing the shade and the notification scrim,
+ * which is then used to drive the Back gesture animation.
+ */
+ private final Rect mUpperRect = new Rect();
+ private final Rect mBoundingBoxRect = new Rect();
+
@Nullable
private Consumer<Configuration> mConfigurationChangedListener;
@@ -172,4 +180,37 @@ public class NotificationsQuickSettingsContainer extends ConstraintLayout
public void applyConstraints(ConstraintSet constraintSet) {
constraintSet.applyTo(this);
}
+
+ /**
+ * Scale multiple elements in tandem, for the predictive back animation.
+ * This is how the Shade responds to the Back gesture (by scaling).
+ * Without the common center, individual elements will scale about their respective centers.
+ * Scaling the entire NotificationsQuickSettingsContainer will also resize the shade header
+ * (which we don't want).
+ */
+ public void applyBackScaling(float scale, boolean usingSplitShade) {
+ if (mStackScroller == null || mQSContainer == null) {
+ return;
+ }
+
+ mQSContainer.getBoundsOnScreen(mUpperRect);
+ mStackScroller.getBoundsOnScreen(mBoundingBoxRect);
+ mBoundingBoxRect.union(mUpperRect);
+
+ float cx = mBoundingBoxRect.centerX();
+ float cy = mBoundingBoxRect.centerY();
+
+ mQSContainer.setPivotX(cx);
+ mQSContainer.setPivotY(cy);
+ mQSContainer.setScaleX(scale);
+ mQSContainer.setScaleY(scale);
+
+ // When in large-screen split-shade mode, the notification stack scroller scales correctly
+ // only if the pivot point is at the left edge of the screen (because of its dimensions).
+ // When not in large-screen split-shade mode, we can scale correctly via the (cx,cy) above.
+ mStackScroller.setPivotX(usingSplitShade ? 0.0f : cx);
+ mStackScroller.setPivotY(cy);
+ mStackScroller.setScaleX(scale);
+ mStackScroller.setScaleY(scale);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
index d041212d24c7..6857f4cc9e8e 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
@@ -31,6 +31,7 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.app.Fragment;
import android.content.res.Resources;
+import android.graphics.Insets;
import android.graphics.Rect;
import android.graphics.Region;
import android.util.Log;
@@ -40,6 +41,9 @@ import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
+import android.view.WindowInsets;
+import android.view.WindowManager;
+import android.view.WindowMetrics;
import android.view.accessibility.AccessibilityManager;
import android.widget.FrameLayout;
@@ -56,7 +60,6 @@ import com.android.systemui.animation.Interpolators;
import com.android.systemui.classifier.Classifier;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.media.controls.pipeline.MediaDataManager;
import com.android.systemui.media.controls.ui.MediaHierarchyManager;
@@ -64,6 +67,7 @@ import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.screenrecord.RecordingController;
import com.android.systemui.shade.transition.ShadeTransitionController;
+import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShadeDepthController;
@@ -84,10 +88,10 @@ import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.LargeScreenUtils;
-import javax.inject.Inject;
-
import dagger.Lazy;
+import javax.inject.Inject;
+
/** Handles QuickSettings touch handling, expansion and animation state
* TODO (b/264460656) make this dumpable
*/
@@ -110,7 +114,7 @@ public class QuickSettingsController {
private final NotificationStackScrollLayoutController mNotificationStackScrollLayoutController;
private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
private final NotificationShadeDepthController mDepthController;
- private final LargeScreenShadeHeaderController mLargeScreenShadeHeaderController;
+ private final ShadeHeaderController mShadeHeaderController;
private final StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
private final KeyguardStateController mKeyguardStateController;
private final KeyguardBypassController mKeyguardBypassController;
@@ -194,7 +198,12 @@ public class QuickSettingsController {
private boolean mAnimatingHiddenFromCollapsed;
private boolean mVisible;
private float mExpansionHeight;
+ /**
+ * QS height when QS expansion fraction is 0 so when QS is collapsed. That state doesn't really
+ * exist for split shade so currently this value is always 0 then.
+ */
private int mMinExpansionHeight;
+ /** QS height when QS expansion fraction is 1 so qs is fully expanded */
private int mMaxExpansionHeight;
/** Expansion fraction of the notification shade */
private float mShadeExpandedFraction;
@@ -219,6 +228,13 @@ public class QuickSettingsController {
private boolean mAnimatorExpand;
/**
+ * The gesture inset currently in effect -- used to decide whether a back gesture should
+ * receive a horizontal swipe inwards from the left/right vertical edge of the screen.
+ * We cache this on ACTION_DOWN, and query it during both ACTION_DOWN and ACTION_MOVE events.
+ */
+ private Insets mCachedGestureInsets;
+
+ /**
* The amount of progress we are currently in if we're transitioning to the full shade.
* 0.0f means we're not transitioning yet, while 1 means we're all the way in the full
* shade. This value can also go beyond 1.1 when we're overshooting!
@@ -276,7 +292,7 @@ public class QuickSettingsController {
NotificationStackScrollLayoutController notificationStackScrollLayoutController,
LockscreenShadeTransitionController lockscreenShadeTransitionController,
NotificationShadeDepthController notificationShadeDepthController,
- LargeScreenShadeHeaderController largeScreenShadeHeaderController,
+ ShadeHeaderController shadeHeaderController,
StatusBarTouchableRegionManager statusBarTouchableRegionManager,
KeyguardStateController keyguardStateController,
KeyguardBypassController keyguardBypassController,
@@ -315,7 +331,7 @@ public class QuickSettingsController {
mNotificationStackScrollLayoutController = notificationStackScrollLayoutController;
mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
mDepthController = notificationShadeDepthController;
- mLargeScreenShadeHeaderController = largeScreenShadeHeaderController;
+ mShadeHeaderController = shadeHeaderController;
mStatusBarTouchableRegionManager = statusBarTouchableRegionManager;
mKeyguardStateController = keyguardStateController;
mKeyguardBypassController = keyguardBypassController;
@@ -396,20 +412,13 @@ public class QuickSettingsController {
mResources.getDimensionPixelSize(R.dimen.large_screen_shade_header_height);
int topMargin = mUseLargeScreenShadeHeader ? mLargeScreenShadeHeaderHeight :
mResources.getDimensionPixelSize(R.dimen.notification_panel_margin_top);
- mLargeScreenShadeHeaderController.setLargeScreenActive(mUseLargeScreenShadeHeader);
+ mShadeHeaderController.setLargeScreenActive(mUseLargeScreenShadeHeader);
mAmbientState.setStackTopMargin(topMargin);
- // TODO: When the flag is eventually removed, it means that we have a single view that is
- // the same height in QQS and in Large Screen (large_screen_shade_header_height). Eventually
- // the concept of largeScreenHeader or quickQsHeader will disappear outside of the class
- // that controls the view as the offset needs to be the same regardless.
- if (mUseLargeScreenShadeHeader || mFeatureFlags.isEnabled(Flags.COMBINED_QS_HEADERS)) {
- mQuickQsHeaderHeight = mLargeScreenShadeHeaderHeight;
- } else {
- mQuickQsHeaderHeight = SystemBarUtils.getQuickQsOffsetHeight(mPanelView.getContext());
- }
+ mQuickQsHeaderHeight = mLargeScreenShadeHeaderHeight;
mEnableClipping = mResources.getBoolean(R.bool.qs_enable_clipping);
+ updateGestureInsetsCache();
}
// TODO (b/265054088): move this and others to a CoreStartable
@@ -434,6 +443,11 @@ public class QuickSettingsController {
updateExpansionEnabledAmbient();
}
+ @VisibleForTesting
+ void setStatusBarMinHeight(int height) {
+ mStatusBarMinHeight = height;
+ }
+
int getHeaderHeight() {
return mQs.getHeader().getHeight();
}
@@ -468,6 +482,26 @@ public class QuickSettingsController {
|| touchX > mQsFrame.getX() + mQsFrame.getWidth();
}
+ /**
+ * Computes (and caches) the gesture insets for the current window. Intended to be called
+ * on ACTION_DOWN, and safely queried repeatedly thereafter during ACTION_MOVE events.
+ */
+ public void updateGestureInsetsCache() {
+ WindowManager wm = this.mPanelView.getContext().getSystemService(WindowManager.class);
+ WindowMetrics windowMetrics = wm.getCurrentWindowMetrics();
+ mCachedGestureInsets = windowMetrics.getWindowInsets().getInsets(
+ WindowInsets.Type.systemGestures());
+ }
+
+ /**
+ * Returns whether x coordinate lies in the vertical edges of the screen
+ * (the only place where a back gesture can be initiated).
+ */
+ public boolean shouldBackBypassQuickSettings(float touchX) {
+ return (touchX < mCachedGestureInsets.left)
+ || (touchX > mKeyguardStatusBar.getWidth() - mCachedGestureInsets.right);
+ }
+
/** Returns whether touch is within QS area */
private boolean isTouchInQsArea(float x, float y) {
if (isSplitShadeAndTouchXOutsideQs(x)) {
@@ -483,7 +517,8 @@ public class QuickSettingsController {
}
/** Returns whether or not event should open QS */
- private boolean isOpenQsEvent(MotionEvent event) {
+ @VisibleForTesting
+ boolean isOpenQsEvent(MotionEvent event) {
final int pointerCount = event.getPointerCount();
final int action = event.getActionMasked();
@@ -663,8 +698,15 @@ public class QuickSettingsController {
mDozing = dozing;
}
- /** set QS state to closed */
+ /**
+ * This method closes QS but in split shade it should be used only in special cases: to make
+ * sure QS closes when shade is closed as well. Otherwise it will result in QS disappearing
+ * from split shade
+ */
public void closeQs() {
+ if (mSplitShadeEnabled) {
+ mShadeLog.d("Closing QS while in split shade");
+ }
cancelExpansionAnimation();
setExpansionHeight(getMinExpansionHeight());
// qsExpandImmediate is a safety latch in case we're calling closeQS while we're in the
@@ -693,6 +735,7 @@ public class QuickSettingsController {
/** update Qs height state */
public void setExpansionHeight(float height) {
+ checkCorrectSplitShadeState(height);
int maxHeight = getMaxExpansionHeight();
height = Math.min(Math.max(
height, getMinExpansionHeight()), maxHeight);
@@ -714,6 +757,14 @@ public class QuickSettingsController {
}
}
+ /** TODO(b/269742565) Remove this logging */
+ private void checkCorrectSplitShadeState(float height) {
+ if (mSplitShadeEnabled && height == 0
+ && mPanelViewControllerLazy.get().isShadeFullyOpen()) {
+ Log.wtfStack(TAG, "qsExpansion set to 0 while split shade is expanding or open");
+ }
+ }
+
/** */
public void setHeightOverrideToDesiredHeight() {
if (isSizeChangeAnimationRunning() && isQsFragmentCreated()) {
@@ -803,6 +854,10 @@ public class QuickSettingsController {
}
}
+ void setOverScrollAmount(int overExpansion) {
+ mQs.setOverScrollAmount(overExpansion);
+ }
+
private void setOverScrolling(boolean overscrolling) {
mStackScrollerOverscrolling = overscrolling;
if (mQs != null) {
@@ -845,6 +900,11 @@ public class QuickSettingsController {
mTwoFingerExpandPossible = expandPossible;
}
+ @VisibleForTesting
+ boolean isTwoFingerExpandPossible() {
+ return mTwoFingerExpandPossible;
+ }
+
/** Called when Qs starts expanding */
private void onExpansionStarted() {
cancelExpansionAnimation();
@@ -899,6 +959,10 @@ public class QuickSettingsController {
getHeaderTranslation(),
squishiness
);
+ if (QuickStepContract.ALLOW_BACK_GESTURE_IN_SHADE
+ && mPanelViewControllerLazy.get().mAnimateBack) {
+ mPanelViewControllerLazy.get().adjustBackAnimationScale(adjustedExpansionFraction);
+ }
mMediaHierarchyManager.setQsExpansion(qsExpansionFraction);
int qsPanelBottomY = calculateBottomPosition(qsExpansionFraction);
mScrimController.setQsPosition(qsExpansionFraction, qsPanelBottomY);
@@ -920,9 +984,9 @@ public class QuickSettingsController {
float shadeExpandedFraction = mBarState == KEYGUARD
? mPanelViewControllerLazy.get().getLockscreenShadeDragProgress()
: mShadeExpandedFraction;
- mLargeScreenShadeHeaderController.setShadeExpandedFraction(shadeExpandedFraction);
- mLargeScreenShadeHeaderController.setQsExpandedFraction(qsExpansionFraction);
- mLargeScreenShadeHeaderController.setQsVisible(mVisible);
+ mShadeHeaderController.setShadeExpandedFraction(shadeExpandedFraction);
+ mShadeHeaderController.setQsExpandedFraction(qsExpansionFraction);
+ mShadeHeaderController.setQsVisible(mVisible);
}
/** */
@@ -1086,6 +1150,7 @@ public class QuickSettingsController {
float screenCornerRadius = mRecordingController.isRecording() ? 0 : mScreenCornerRadius;
radius = (int) MathUtils.lerp(screenCornerRadius, mScrimCornerRadius,
Math.min(top / (float) mScrimCornerRadius, 1f));
+ mScrimController.setNotificationBottomRadius(radius);
}
if (isQsFragmentCreated()) {
float qsTranslation = 0;
@@ -1361,7 +1426,8 @@ public class QuickSettingsController {
return mTouchAboveFalsingThreshold;
}
- private void onHeightChanged() {
+ @VisibleForTesting
+ void onHeightChanged() {
mMaxExpansionHeight = isQsFragmentCreated() ? mQs.getDesiredHeight() : 0;
if (mExpanded && mFullyExpanded) {
mExpansionHeight = mMaxExpansionHeight;
@@ -1391,7 +1457,7 @@ public class QuickSettingsController {
}
private void onScroll(int scrollY) {
- mLargeScreenShadeHeaderController.setQsScrollY(scrollY);
+ mShadeHeaderController.setQsScrollY(scrollY);
if (scrollY > 0 && !mFullyExpanded) {
// TODO (b/265193930): remove dependency on NPVC
// If we are scrolling QS, we should be fully expanded.
@@ -1477,18 +1543,31 @@ public class QuickSettingsController {
}
private void handleDown(MotionEvent event) {
- if (event.getActionMasked() == MotionEvent.ACTION_DOWN
- && shouldQuickSettingsIntercept(event.getX(), event.getY(), -1)) {
- mFalsingCollector.onQsDown();
- mShadeLog.logMotionEvent(event, "handleQsDown: down action, QS tracking enabled");
- mTracking = true;
- onExpansionStarted();
- mInitialHeightOnTouch = mExpansionHeight;
- mInitialTouchY = event.getY();
- mInitialTouchX = event.getX();
- // TODO (b/265193930): remove dependency on NPVC
- // If we interrupt an expansion gesture here, make sure to update the state correctly.
- mPanelViewControllerLazy.get().notifyExpandingFinished();
+ if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
+ // When the shade is fully-expanded, an inward swipe from the L/R edge should first
+ // allow the back gesture's animation to preview the shade animation (if enabled).
+ // (swipes starting closer to the center of the screen will not be affected)
+ if (QuickStepContract.ALLOW_BACK_GESTURE_IN_SHADE
+ && mPanelViewControllerLazy.get().mAnimateBack) {
+ updateGestureInsetsCache();
+ if (shouldBackBypassQuickSettings(event.getX())) {
+ return;
+ }
+ }
+ if (shouldQuickSettingsIntercept(event.getX(), event.getY(), -1)) {
+ mFalsingCollector.onQsDown();
+ mShadeLog.logMotionEvent(event,
+ "handleQsDown: down action, QS tracking enabled");
+ mTracking = true;
+ onExpansionStarted();
+ mInitialHeightOnTouch = mExpansionHeight;
+ mInitialTouchY = event.getY();
+ mInitialTouchX = event.getX();
+ // TODO (b/265193930): remove dependency on NPVC
+ // If we interrupt an expansion gesture here, make sure to update the state
+ // correctly.
+ mPanelViewControllerLazy.get().notifyExpandingFinished();
+ }
}
}
@@ -1666,7 +1745,8 @@ public class QuickSettingsController {
return false;
}
- private void onPanelExpansionChanged(ShadeExpansionChangeEvent event) {
+ @VisibleForTesting
+ void onPanelExpansionChanged(ShadeExpansionChangeEvent event) {
mShadeExpandedFraction = event.getFraction();
}
@@ -1710,12 +1790,16 @@ public class QuickSettingsController {
*/
private void flingQs(float vel, int type, final Runnable onFinishRunnable,
boolean isClick) {
+ mShadeLog.flingQs(type, isClick);
float target;
switch (type) {
case FLING_EXPAND:
target = getMaxExpansionHeight();
break;
case FLING_COLLAPSE:
+ if (mSplitShadeEnabled) { // TODO:(b/269742565) remove below log
+ Log.wtfStack(TAG, "FLING_COLLAPSE called in split shade");
+ }
target = getMinExpansionHeight();
break;
case FLING_HIDE:
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java
index 026673adb86b..c1369935db54 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java
@@ -270,8 +270,6 @@ public final class ShadeControllerImpl implements ShadeController {
// Ensure the panel is fully collapsed (just in case; bug 6765842, 7260868)
mNotificationPanelViewController.collapsePanel(false, false, 1.0f);
- mNotificationPanelViewController.closeQs();
-
mExpandedVisible = false;
notifyVisibilityChanged(false);
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt
index a1767cc5888d..f4b1cc5f71be 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt
@@ -107,7 +107,7 @@ class ShadeExpansionStateManager @Inject constructor() : ShadeStateEvents {
*
* @param fraction the fraction from the expansion in [0, 1]
* @param expanded whether the panel is currently expanded; this is independent from the
- * fraction as the panel also might be expanded if the fraction is 0.
+ * fraction as the panel also might be expanded if the fraction is 0.
* @param tracking whether we're currently tracking the user's gesture.
*/
fun onPanelExpansionChanged(
diff --git a/packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
index 9d8ed460dece..b79f32a6eae1 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
@@ -41,22 +41,21 @@ import com.android.systemui.battery.BatteryMeterViewController
import com.android.systemui.demomode.DemoMode
import com.android.systemui.demomode.DemoModeController
import com.android.systemui.dump.DumpManager
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
import com.android.systemui.qs.ChipVisibilityListener
import com.android.systemui.qs.HeaderPrivacyIconsController
import com.android.systemui.qs.carrier.QSCarrierGroup
import com.android.systemui.qs.carrier.QSCarrierGroupController
-import com.android.systemui.shade.LargeScreenShadeHeaderController.Companion.HEADER_TRANSITION_ID
-import com.android.systemui.shade.LargeScreenShadeHeaderController.Companion.QQS_HEADER_CONSTRAINT
-import com.android.systemui.shade.LargeScreenShadeHeaderController.Companion.QS_HEADER_CONSTRAINT
+import com.android.systemui.shade.ShadeHeaderController.Companion.HEADER_TRANSITION_ID
+import com.android.systemui.shade.ShadeHeaderController.Companion.LARGE_SCREEN_HEADER_CONSTRAINT
+import com.android.systemui.shade.ShadeHeaderController.Companion.LARGE_SCREEN_HEADER_TRANSITION_ID
+import com.android.systemui.shade.ShadeHeaderController.Companion.QQS_HEADER_CONSTRAINT
+import com.android.systemui.shade.ShadeHeaderController.Companion.QS_HEADER_CONSTRAINT
import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
import com.android.systemui.statusbar.phone.StatusBarIconController
import com.android.systemui.statusbar.phone.StatusBarLocation
import com.android.systemui.statusbar.phone.StatusIconContainer
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent.CentralSurfacesScope
-import com.android.systemui.statusbar.phone.dagger.StatusBarViewModule.LARGE_SCREEN_BATTERY_CONTROLLER
-import com.android.systemui.statusbar.phone.dagger.StatusBarViewModule.LARGE_SCREEN_SHADE_HEADER
+import com.android.systemui.statusbar.phone.dagger.StatusBarViewModule.SHADE_HEADER
import com.android.systemui.statusbar.policy.Clock
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.VariableDateView
@@ -67,30 +66,27 @@ import javax.inject.Inject
import javax.inject.Named
/**
- * Controller for QS header on Large Screen width (large screen + landscape).
+ * Controller for QS header.
*
- * Additionally, this serves as the staging ground for the combined QS headers. A single
- * [MotionLayout] that changes constraints depending on the configuration and can animate the
- * expansion of the headers in small screen portrait.
- *
- * [header] will be a [MotionLayout] if [Flags.COMBINED_QS_HEADERS] is enabled. In this case, the
- * [MotionLayout] has one transitions:
+ * [header] is a [MotionLayout] that has two transitions:
* * [HEADER_TRANSITION_ID]: [QQS_HEADER_CONSTRAINT] <-> [QS_HEADER_CONSTRAINT] for portrait
* handheld device configuration.
+ * * [LARGE_SCREEN_HEADER_TRANSITION_ID]: [LARGE_SCREEN_HEADER_CONSTRAINT] for all other
+ * configurations
*/
@CentralSurfacesScope
-class LargeScreenShadeHeaderController @Inject constructor(
- @Named(LARGE_SCREEN_SHADE_HEADER) private val header: View,
+class ShadeHeaderController
+@Inject
+constructor(
+ @Named(SHADE_HEADER) private val header: MotionLayout,
private val statusBarIconController: StatusBarIconController,
private val tintedIconManagerFactory: StatusBarIconController.TintedIconManager.Factory,
private val privacyIconsController: HeaderPrivacyIconsController,
private val insetsProvider: StatusBarContentInsetsProvider,
private val configurationController: ConfigurationController,
private val variableDateViewControllerFactory: VariableDateViewController.Factory,
- @Named(LARGE_SCREEN_BATTERY_CONTROLLER)
- private val batteryMeterViewController: BatteryMeterViewController,
+ @Named(SHADE_HEADER) private val batteryMeterViewController: BatteryMeterViewController,
private val dumpManager: DumpManager,
- private val featureFlags: FeatureFlags,
private val qsCarrierGroupControllerBuilder: QSCarrierGroupController.Builder,
private val combinedShadeHeadersConstraintManager: CombinedShadeHeadersConstraintManager,
private val demoModeController: DemoModeController,
@@ -98,30 +94,24 @@ class LargeScreenShadeHeaderController @Inject constructor(
) : ViewController<View>(header), Dumpable {
companion object {
- /** IDs for transitions and constraints for the [MotionLayout]. These are only used when
- * [Flags.COMBINED_QS_HEADERS] is enabled.
- */
- @VisibleForTesting
- internal val HEADER_TRANSITION_ID = R.id.header_transition
+ /** IDs for transitions and constraints for the [MotionLayout]. */
+ @VisibleForTesting internal val HEADER_TRANSITION_ID = R.id.header_transition
@VisibleForTesting
internal val LARGE_SCREEN_HEADER_TRANSITION_ID = R.id.large_screen_header_transition
- @VisibleForTesting
- internal val QQS_HEADER_CONSTRAINT = R.id.qqs_header_constraint
- @VisibleForTesting
- internal val QS_HEADER_CONSTRAINT = R.id.qs_header_constraint
+ @VisibleForTesting internal val QQS_HEADER_CONSTRAINT = R.id.qqs_header_constraint
+ @VisibleForTesting internal val QS_HEADER_CONSTRAINT = R.id.qs_header_constraint
@VisibleForTesting
internal val LARGE_SCREEN_HEADER_CONSTRAINT = R.id.large_screen_header_constraint
- private fun Int.stateToString() = when (this) {
- QQS_HEADER_CONSTRAINT -> "QQS Header"
- QS_HEADER_CONSTRAINT -> "QS Header"
- LARGE_SCREEN_HEADER_CONSTRAINT -> "Large Screen Header"
- else -> "Unknown state $this"
- }
+ private fun Int.stateToString() =
+ when (this) {
+ QQS_HEADER_CONSTRAINT -> "QQS Header"
+ QS_HEADER_CONSTRAINT -> "QS Header"
+ LARGE_SCREEN_HEADER_CONSTRAINT -> "Large Screen Header"
+ else -> "Unknown state $this"
+ }
}
- private val combinedHeaders = featureFlags.isEnabled(Flags.COMBINED_QS_HEADERS)
-
private lateinit var iconManager: StatusBarIconController.TintedIconManager
private lateinit var carrierIconSlots: List<String>
private lateinit var qsCarrierGroupController: QSCarrierGroupController
@@ -180,9 +170,7 @@ class LargeScreenShadeHeaderController @Inject constructor(
onHeaderStateChanged()
}
- /**
- * Expansion fraction of the QQS/QS shade. This is not the expansion between QQS <-> QS.
- */
+ /** Expansion fraction of the QQS/QS shade. This is not the expansion between QQS <-> QS. */
var shadeExpandedFraction = -1f
set(value) {
if (qsVisible && field != value) {
@@ -191,9 +179,7 @@ class LargeScreenShadeHeaderController @Inject constructor(
}
}
- /**
- * Expansion fraction of the QQS <-> QS animation.
- */
+ /** Expansion fraction of the QQS <-> QS animation. */
var qsExpandedFraction = -1f
set(value) {
if (visible && field != value) {
@@ -202,9 +188,7 @@ class LargeScreenShadeHeaderController @Inject constructor(
}
}
- /**
- * Current scroll of QS.
- */
+ /** Current scroll of QS. */
var qsScrollY = 0
set(value) {
if (field != value) {
@@ -213,40 +197,41 @@ class LargeScreenShadeHeaderController @Inject constructor(
}
}
- private val insetListener = View.OnApplyWindowInsetsListener { view, insets ->
- updateConstraintsForInsets(view as MotionLayout, insets)
- lastInsets = WindowInsets(insets)
+ private val insetListener =
+ View.OnApplyWindowInsetsListener { view, insets ->
+ updateConstraintsForInsets(view as MotionLayout, insets)
+ lastInsets = WindowInsets(insets)
- view.onApplyWindowInsets(insets)
- }
+ view.onApplyWindowInsets(insets)
+ }
- private val demoModeReceiver = object : DemoMode {
- override fun demoCommands() = listOf(DemoMode.COMMAND_CLOCK)
- override fun dispatchDemoCommand(command: String, args: Bundle) =
- clock.dispatchDemoCommand(command, args)
- override fun onDemoModeStarted() = clock.onDemoModeStarted()
- override fun onDemoModeFinished() = clock.onDemoModeFinished()
- }
+ private val demoModeReceiver =
+ object : DemoMode {
+ override fun demoCommands() = listOf(DemoMode.COMMAND_CLOCK)
+ override fun dispatchDemoCommand(command: String, args: Bundle) =
+ clock.dispatchDemoCommand(command, args)
+ override fun onDemoModeStarted() = clock.onDemoModeStarted()
+ override fun onDemoModeFinished() = clock.onDemoModeFinished()
+ }
- private val chipVisibilityListener: ChipVisibilityListener = object : ChipVisibilityListener {
- override fun onChipVisibilityRefreshed(visible: Boolean) {
- if (header is MotionLayout) {
+ private val chipVisibilityListener: ChipVisibilityListener =
+ object : ChipVisibilityListener {
+ override fun onChipVisibilityRefreshed(visible: Boolean) {
// If the privacy chip is visible, we hide the status icons and battery remaining
// icon, only in QQS.
- val update = combinedShadeHeadersConstraintManager
- .privacyChipVisibilityConstraints(visible)
+ val update =
+ combinedShadeHeadersConstraintManager.privacyChipVisibilityConstraints(visible)
header.updateAllConstraints(update)
}
}
- }
private val configurationControllerListener =
object : ConfigurationController.ConfigurationListener {
- override fun onConfigChanged(newConfig: Configuration?) {
- if (header !is MotionLayout) {
- val left = header.resources.getDimensionPixelSize(
- R.dimen.large_screen_shade_header_left_padding
- )
+ override fun onConfigChanged(newConfig: Configuration?) {
+ val left =
+ header.resources.getDimensionPixelSize(
+ R.dimen.large_screen_shade_header_left_padding
+ )
header.setPadding(
left,
header.paddingTop,
@@ -254,26 +239,21 @@ class LargeScreenShadeHeaderController @Inject constructor(
header.paddingBottom
)
}
- }
- override fun onDensityOrFontScaleChanged() {
- clock.setTextAppearance(R.style.TextAppearance_QS_Status)
- date.setTextAppearance(R.style.TextAppearance_QS_Status)
- qsCarrierGroup.updateTextAppearance(R.style.TextAppearance_QS_Status_Carriers)
- if (header is MotionLayout) {
+ override fun onDensityOrFontScaleChanged() {
+ clock.setTextAppearance(R.style.TextAppearance_QS_Status)
+ date.setTextAppearance(R.style.TextAppearance_QS_Status)
+ qsCarrierGroup.updateTextAppearance(R.style.TextAppearance_QS_Status_Carriers)
loadConstraints()
- header.minHeight = resources
- .getDimensionPixelSize(R.dimen.large_screen_shade_header_min_height)
+ header.minHeight =
+ resources.getDimensionPixelSize(R.dimen.large_screen_shade_header_min_height)
lastInsets?.let { updateConstraintsForInsets(header, it) }
+ updateResources()
}
- updateResources()
}
- }
override fun onInit() {
- if (header is MotionLayout) {
- variableDateViewControllerFactory.create(date as VariableDateView).init()
- }
+ variableDateViewControllerFactory.create(date as VariableDateView).init()
batteryMeterViewController.init()
// battery settings same as in QS icons
@@ -286,20 +266,10 @@ class LargeScreenShadeHeaderController @Inject constructor(
carrierIconSlots =
listOf(header.context.getString(com.android.internal.R.string.status_bar_mobile))
- qsCarrierGroupController = qsCarrierGroupControllerBuilder
- .setQSCarrierGroup(qsCarrierGroup)
- .build()
-
- if (!combinedHeaders) {
- // In the new header, we display alarm icon but we ignore it when not using the new
- // headers.
- iconContainer.addIgnoredSlot(
- context.getString(com.android.internal.R.string.status_bar_alarm_clock)
- )
- }
- if (combinedHeaders) {
- privacyIconsController.onParentVisible()
- }
+ qsCarrierGroupController =
+ qsCarrierGroupControllerBuilder.setQSCarrierGroup(qsCarrierGroup).build()
+
+ privacyIconsController.onParentVisible()
}
override fun onViewAttached() {
@@ -307,16 +277,14 @@ class LargeScreenShadeHeaderController @Inject constructor(
updateVisibility()
updateTransition()
- if (header is MotionLayout) {
- header.setOnApplyWindowInsetsListener(insetListener)
+ header.setOnApplyWindowInsetsListener(insetListener)
- clock.addOnLayoutChangeListener { v, _, _, _, _, _, _, _, _ ->
- val newPivot = if (v.isLayoutRtl) v.width.toFloat() else 0f
- v.pivotX = newPivot
- v.pivotY = v.height.toFloat() / 2
+ clock.addOnLayoutChangeListener { v, _, _, _, _, _, _, _, _ ->
+ val newPivot = if (v.isLayoutRtl) v.width.toFloat() else 0f
+ v.pivotX = newPivot
+ v.pivotY = v.height.toFloat() / 2
- qsCarrierGroup.setPaddingRelative((v.width * v.scaleX).toInt(), 0, 0, 0)
- }
+ qsCarrierGroup.setPaddingRelative((v.width * v.scaleX).toInt(), 0, 0, 0)
}
dumpManager.registerDumpable(this)
@@ -341,30 +309,30 @@ class LargeScreenShadeHeaderController @Inject constructor(
}
fun startCustomizingAnimation(show: Boolean, duration: Long) {
- header.animate()
- .setDuration(duration)
- .alpha(if (show) 0f else 1f)
- .setInterpolator(if (show) Interpolators.ALPHA_OUT else Interpolators.ALPHA_IN)
- .setListener(CustomizerAnimationListener(show))
- .start()
+ header
+ .animate()
+ .setDuration(duration)
+ .alpha(if (show) 0f else 1f)
+ .setInterpolator(if (show) Interpolators.ALPHA_OUT else Interpolators.ALPHA_IN)
+ .setListener(CustomizerAnimationListener(show))
+ .start()
}
private fun loadConstraints() {
- if (header is MotionLayout) {
- // Use resources.getXml instead of passing the resource id due to bug b/205018300
- header.getConstraintSet(QQS_HEADER_CONSTRAINT)
- .load(context, resources.getXml(R.xml.qqs_header))
- header.getConstraintSet(QS_HEADER_CONSTRAINT)
- .load(context, resources.getXml(R.xml.qs_header))
- header.getConstraintSet(LARGE_SCREEN_HEADER_CONSTRAINT)
- .load(context, resources.getXml(R.xml.large_screen_shade_header))
- }
+ // Use resources.getXml instead of passing the resource id due to bug b/205018300
+ header
+ .getConstraintSet(QQS_HEADER_CONSTRAINT)
+ .load(context, resources.getXml(R.xml.qqs_header))
+ header
+ .getConstraintSet(QS_HEADER_CONSTRAINT)
+ .load(context, resources.getXml(R.xml.qs_header))
+ header
+ .getConstraintSet(LARGE_SCREEN_HEADER_CONSTRAINT)
+ .load(context, resources.getXml(R.xml.large_screen_shade_header))
}
private fun updateConstraintsForInsets(view: MotionLayout, insets: WindowInsets) {
- val cutout = insets.displayCutout.also {
- this.cutout = it
- }
+ val cutout = insets.displayCutout.also { this.cutout = it }
val sbInsets: Pair<Int, Int> = insetsProvider.getStatusBarContentInsetsForCurrentRotation()
val cutoutLeft = sbInsets.first
@@ -373,8 +341,8 @@ class LargeScreenShadeHeaderController @Inject constructor(
updateQQSPaddings()
// Set these guides as the left/right limits for content that lives in the top row, using
// cutoutLeft and cutoutRight
- var changes = combinedShadeHeadersConstraintManager
- .edgesGuidelinesConstraints(
+ var changes =
+ combinedShadeHeadersConstraintManager.edgesGuidelinesConstraints(
if (view.isLayoutRtl) cutoutRight else cutoutLeft,
header.paddingStart,
if (view.isLayoutRtl) cutoutLeft else cutoutRight,
@@ -386,13 +354,14 @@ class LargeScreenShadeHeaderController @Inject constructor(
if (topCutout.isEmpty || hasCornerCutout) {
changes += combinedShadeHeadersConstraintManager.emptyCutoutConstraints()
} else {
- changes += combinedShadeHeadersConstraintManager.centerCutoutConstraints(
- view.isLayoutRtl,
- (view.width - view.paddingLeft - view.paddingRight - topCutout.width()) / 2
- )
+ changes +=
+ combinedShadeHeadersConstraintManager.centerCutoutConstraints(
+ view.isLayoutRtl,
+ (view.width - view.paddingLeft - view.paddingRight - topCutout.width()) / 2
+ )
}
} else {
- changes += combinedShadeHeadersConstraintManager.emptyCutoutConstraints()
+ changes += combinedShadeHeadersConstraintManager.emptyCutoutConstraints()
}
view.updateAllConstraints(changes)
@@ -406,7 +375,7 @@ class LargeScreenShadeHeaderController @Inject constructor(
}
private fun updateScrollY() {
- if (!largeScreenActive && combinedHeaders) {
+ if (!largeScreenActive) {
header.scrollY = qsScrollY
}
}
@@ -422,12 +391,6 @@ class LargeScreenShadeHeaderController @Inject constructor(
}
private fun onHeaderStateChanged() {
- if (largeScreenActive || combinedHeaders) {
- privacyIconsController.onParentVisible()
- } else {
- privacyIconsController.onParentInvisible()
- }
- updateVisibility()
updateTransition()
}
@@ -436,13 +399,14 @@ class LargeScreenShadeHeaderController @Inject constructor(
* be visible any time the QQS/QS shade is open.
*/
private fun updateVisibility() {
- val visibility = if (!largeScreenActive && !combinedHeaders || qsDisabled) {
- View.GONE
- } else if (qsVisible && !customizing) {
- View.VISIBLE
- } else {
- View.INVISIBLE
- }
+ val visibility =
+ if (qsDisabled) {
+ View.GONE
+ } else if (qsVisible && !customizing) {
+ View.VISIBLE
+ } else {
+ View.INVISIBLE
+ }
if (header.visibility != visibility) {
header.visibility = visibility
visible = visibility == View.VISIBLE
@@ -450,10 +414,6 @@ class LargeScreenShadeHeaderController @Inject constructor(
}
private fun updateTransition() {
- if (!combinedHeaders) {
- return
- }
- header as MotionLayout
if (largeScreenActive) {
logInstantEvent("Large screen constraints set")
header.setTransition(LARGE_SCREEN_HEADER_TRANSITION_ID)
@@ -467,7 +427,7 @@ class LargeScreenShadeHeaderController @Inject constructor(
}
private fun updatePosition() {
- if (header is MotionLayout && !largeScreenActive && visible) {
+ if (!largeScreenActive && visible) {
logInstantEvent("updatePosition: $qsExpandedFraction")
header.progress = qsExpandedFraction
updateBatteryMode()
@@ -475,11 +435,7 @@ class LargeScreenShadeHeaderController @Inject constructor(
}
private fun logInstantEvent(message: String) {
- Trace.instantForTrack(
- TRACE_TAG_APP,
- "LargeScreenHeaderController",
- message
- )
+ Trace.instantForTrack(TRACE_TAG_APP, "LargeScreenHeaderController", message)
}
private fun updateListeners() {
@@ -509,18 +465,16 @@ class LargeScreenShadeHeaderController @Inject constructor(
}
private fun updateQQSPaddings() {
- if (header is MotionLayout) {
- val clockPaddingStart = resources
- .getDimensionPixelSize(R.dimen.status_bar_left_clock_starting_padding)
- val clockPaddingEnd = resources
- .getDimensionPixelSize(R.dimen.status_bar_left_clock_end_padding)
- clock.setPaddingRelative(
- clockPaddingStart,
- clock.paddingTop,
- clockPaddingEnd,
- clock.paddingBottom
- )
- }
+ val clockPaddingStart =
+ resources.getDimensionPixelSize(R.dimen.status_bar_left_clock_starting_padding)
+ val clockPaddingEnd =
+ resources.getDimensionPixelSize(R.dimen.status_bar_left_clock_end_padding)
+ clock.setPaddingRelative(
+ clockPaddingStart,
+ clock.paddingTop,
+ clockPaddingEnd,
+ clock.paddingBottom
+ )
}
override fun dump(pw: PrintWriter, args: Array<out String>) {
@@ -530,10 +484,7 @@ class LargeScreenShadeHeaderController @Inject constructor(
pw.println("active: $largeScreenActive")
pw.println("qsExpandedFraction: $qsExpandedFraction")
pw.println("qsScrollY: $qsScrollY")
- if (combinedHeaders) {
- header as MotionLayout
- pw.println("currentState: ${header.currentState.stateToString()}")
- }
+ pw.println("currentState: ${header.currentState.stateToString()}")
}
private fun MotionLayout.updateConstraints(@IdRes state: Int, update: ConstraintChange) {
@@ -559,11 +510,10 @@ class LargeScreenShadeHeaderController @Inject constructor(
}
}
- @VisibleForTesting
- internal fun simulateViewDetached() = this.onViewDetached()
+ @VisibleForTesting internal fun simulateViewDetached() = this.onViewDetached()
inner class CustomizerAnimationListener(
- private val enteringCustomizing: Boolean,
+ private val enteringCustomizing: Boolean,
) : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator?) {
super.onAnimationEnd(animation)
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
index aa8c5b65e0fe..d34e127b194b 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
@@ -20,6 +20,9 @@ import android.view.MotionEvent
import com.android.systemui.log.dagger.ShadeLog
import com.android.systemui.plugins.log.LogBuffer
import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.shade.NotificationPanelViewController.FLING_COLLAPSE
+import com.android.systemui.shade.NotificationPanelViewController.FLING_EXPAND
+import com.android.systemui.shade.NotificationPanelViewController.FLING_HIDE
import com.google.errorprone.annotations.CompileTimeConstant
import javax.inject.Inject
@@ -241,18 +244,40 @@ class ShadeLogger @Inject constructor(@ShadeLog private val buffer: LogBuffer) {
)
}
- fun logLastFlingWasExpanding(
- expand: Boolean
- ) {
+ fun logLastFlingWasExpanding(expand: Boolean) {
buffer.log(
- TAG,
- LogLevel.VERBOSE,
- {
- bool1 = expand
- },
- {
- "NPVC mLastFlingWasExpanding set to: $bool1"
- }
+ TAG,
+ LogLevel.VERBOSE,
+ { bool1 = expand },
+ { "NPVC mLastFlingWasExpanding set to: $bool1" }
+ )
+ }
+
+ fun flingQs(flingType: Int, isClick: Boolean) {
+ buffer.log(
+ TAG,
+ LogLevel.VERBOSE,
+ {
+ str1 = flingTypeToString(flingType)
+ bool1 = isClick
+ },
+ { "QS fling with type $str1, originated from click: $isClick" }
+ )
+ }
+
+ private fun flingTypeToString(flingType: Int) = when (flingType) {
+ FLING_EXPAND -> "FLING_EXPAND"
+ FLING_COLLAPSE -> "FLING_COLLAPSE"
+ FLING_HIDE -> "FLING_HIDE"
+ else -> "UNKNOWN"
+ }
+
+ fun logSplitShadeChanged(splitShadeEnabled: Boolean) {
+ buffer.log(
+ TAG,
+ LogLevel.VERBOSE,
+ { bool1 = splitShadeEnabled },
+ { "Split shade state changed: split shade ${if (bool1) "enabled" else "disabled"}" }
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt
index 07820ecd513e..129d09ec3c14 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt
@@ -43,8 +43,6 @@ constructor(
shadeExpansionStateManager: ShadeExpansionStateManager,
dumpManager: DumpManager,
private val context: Context,
- private val splitShadeOverScrollerFactory: SplitShadeOverScroller.Factory,
- private val noOpOverScroller: NoOpOverScroller,
private val scrimShadeTransitionController: ScrimShadeTransitionController,
private val statusBarStateController: SysuiStatusBarStateController,
) {
@@ -57,17 +55,6 @@ constructor(
private var currentPanelState: Int? = null
private var lastShadeExpansionChangeEvent: ShadeExpansionChangeEvent? = null
- private val splitShadeOverScroller by lazy {
- splitShadeOverScrollerFactory.create({ qs }, { notificationStackScrollLayoutController })
- }
- private val shadeOverScroller: ShadeOverScroller
- get() =
- if (inSplitShade && isScreenUnlocked() && propertiesInitialized()) {
- splitShadeOverScroller
- } else {
- noOpOverScroller
- }
-
init {
updateResources()
configurationController.addCallback(
@@ -89,21 +76,14 @@ constructor(
private fun onPanelStateChanged(@PanelState state: Int) {
currentPanelState = state
- shadeOverScroller.onPanelStateChanged(state)
scrimShadeTransitionController.onPanelStateChanged(state)
}
private fun onPanelExpansionChanged(event: ShadeExpansionChangeEvent) {
lastShadeExpansionChangeEvent = event
- shadeOverScroller.onDragDownAmountChanged(event.dragDownPxAmount)
scrimShadeTransitionController.onPanelExpansionChanged(event)
}
- private fun propertiesInitialized() =
- this::qs.isInitialized &&
- this::notificationPanelViewController.isInitialized &&
- this::notificationStackScrollLayoutController.isInitialized
-
private fun dump(pw: PrintWriter) {
pw.println(
"""
diff --git a/packages/SystemUI/src/com/android/systemui/shade/transition/SplitShadeOverScroller.kt b/packages/SystemUI/src/com/android/systemui/shade/transition/SplitShadeOverScroller.kt
deleted file mode 100644
index f95125f5cb6c..000000000000
--- a/packages/SystemUI/src/com/android/systemui/shade/transition/SplitShadeOverScroller.kt
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.shade.transition
-
-import android.animation.Animator
-import android.animation.ValueAnimator
-import android.content.Context
-import android.content.res.Configuration
-import android.util.MathUtils
-import com.android.internal.annotations.VisibleForTesting
-import com.android.systemui.R
-import com.android.systemui.animation.Interpolators
-import com.android.systemui.dump.DumpManager
-import com.android.systemui.plugins.qs.QS
-import com.android.systemui.shade.PanelState
-import com.android.systemui.shade.STATE_CLOSED
-import com.android.systemui.shade.STATE_OPENING
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
-import com.android.systemui.statusbar.phone.ScrimController
-import com.android.systemui.statusbar.policy.ConfigurationController
-import dagger.assisted.Assisted
-import dagger.assisted.AssistedFactory
-import dagger.assisted.AssistedInject
-import java.io.PrintWriter
-
-class SplitShadeOverScroller
-@AssistedInject
-constructor(
- configurationController: ConfigurationController,
- dumpManager: DumpManager,
- private val context: Context,
- private val scrimController: ScrimController,
- @Assisted private val qSProvider: () -> QS,
- @Assisted private val nsslControllerProvider: () -> NotificationStackScrollLayoutController
-) : ShadeOverScroller {
-
- private var releaseOverScrollDuration = 0L
- private var maxOverScrollAmount = 0
- private var previousOverscrollAmount = 0
- private var dragDownAmount: Float = 0f
- @PanelState private var panelState: Int = STATE_CLOSED
-
- private var releaseOverScrollAnimator: Animator? = null
-
- private val qS: QS
- get() = qSProvider()
-
- private val nsslController: NotificationStackScrollLayoutController
- get() = nsslControllerProvider()
-
- init {
- updateResources()
- configurationController.addCallback(
- object : ConfigurationController.ConfigurationListener {
- override fun onConfigChanged(newConfig: Configuration?) {
- updateResources()
- }
- })
- dumpManager.registerCriticalDumpable("SplitShadeOverScroller") { printWriter, _ ->
- dump(printWriter)
- }
- }
-
- private fun updateResources() {
- val resources = context.resources
- maxOverScrollAmount = resources.getDimensionPixelSize(R.dimen.shade_max_over_scroll_amount)
- releaseOverScrollDuration =
- resources.getInteger(R.integer.lockscreen_shade_over_scroll_release_duration).toLong()
- }
-
- override fun onPanelStateChanged(@PanelState newPanelState: Int) {
- if (shouldReleaseOverscroll(previousState = panelState, newState = newPanelState)) {
- releaseOverScroll()
- }
- panelState = newPanelState
- }
-
- override fun onDragDownAmountChanged(newDragDownAmount: Float) {
- if (dragDownAmount == newDragDownAmount) {
- return
- }
- dragDownAmount = newDragDownAmount
- if (shouldOverscroll()) {
- overScroll(newDragDownAmount)
- }
- }
-
- private fun shouldOverscroll() = panelState == STATE_OPENING
-
- private fun shouldReleaseOverscroll(@PanelState previousState: Int, @PanelState newState: Int) =
- previousState == STATE_OPENING && newState != STATE_OPENING
-
- private fun overScroll(dragDownAmount: Float) {
- val overscrollAmount: Int = calculateOverscrollAmount(dragDownAmount)
- applyOverscroll(overscrollAmount)
- previousOverscrollAmount = overscrollAmount
- }
-
- private fun calculateOverscrollAmount(dragDownAmount: Float): Int {
- val fullHeight: Int = nsslController.height
- val fullHeightProgress: Float = MathUtils.saturate(dragDownAmount / fullHeight)
- return (fullHeightProgress * maxOverScrollAmount).toInt()
- }
-
- private fun applyOverscroll(overscrollAmount: Int) {
- qS.setOverScrollAmount(overscrollAmount)
- scrimController.setNotificationsOverScrollAmount(overscrollAmount)
- nsslController.setOverScrollAmount(overscrollAmount)
- }
-
- private fun releaseOverScroll() {
- val animator = ValueAnimator.ofInt(previousOverscrollAmount, 0)
- animator.addUpdateListener {
- val overScrollAmount = it.animatedValue as Int
- qS.setOverScrollAmount(overScrollAmount)
- scrimController.setNotificationsOverScrollAmount(overScrollAmount)
- nsslController.setOverScrollAmount(overScrollAmount)
- }
- animator.interpolator = Interpolators.STANDARD
- animator.duration = releaseOverScrollDuration
- animator.start()
- releaseOverScrollAnimator = animator
- previousOverscrollAmount = 0
- }
-
- @VisibleForTesting
- internal fun finishAnimations() {
- releaseOverScrollAnimator?.end()
- releaseOverScrollAnimator = null
- }
-
- private fun dump(pw: PrintWriter) {
- pw.println(
- """
- SplitShadeOverScroller:
- Resources:
- releaseOverScrollDuration: $releaseOverScrollDuration
- maxOverScrollAmount: $maxOverScrollAmount
- State:
- previousOverscrollAmount: $previousOverscrollAmount
- dragDownAmount: $dragDownAmount
- panelState: $panelState
- """.trimIndent())
- }
-
- @AssistedFactory
- fun interface Factory {
- fun create(
- qSProvider: () -> QS,
- nsslControllerProvider: () -> NotificationStackScrollLayoutController
- ): SplitShadeOverScroller
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
index 84b40e05d808..77d98d266a3e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
@@ -234,7 +234,7 @@ public abstract class AlertingNotificationManager {
/**
* @param key
- * @return true if the entry is pinned
+ * @return true if the entry is (pinned and expanded) or (has an active remote input)
*/
public boolean isSticky(String key) {
AlertEntry alerting = mAlertEntries.get(key);
@@ -256,15 +256,6 @@ public abstract class AlertingNotificationManager {
return 0;
}
- @VisibleForTesting
- public long getCalculatedEarliestRemovalTime(String key) {
- AlertEntry alerting = mAlertEntries.get(key);
- if (alerting != null) {
- return alerting.mEarliestRemovaltime;
- }
- return 0;
- }
-
protected class AlertEntry implements Comparable<AlertEntry> {
@Nullable public NotificationEntry mEntry;
public long mPostTime;
@@ -285,11 +276,6 @@ public abstract class AlertingNotificationManager {
updateEntry(true /* updatePostTime */);
}
- @VisibleForTesting
- long getEarliestRemovaltime() {
- return mEarliestRemovaltime;
- }
-
/**
* Updates an entry's removal time.
* @param updatePostTime whether or not to refresh the post time
@@ -305,23 +291,26 @@ public abstract class AlertingNotificationManager {
}
removeAutoRemovalCallbacks();
- final long finishTime = calculateFinishTime();
- final long timeRemaining = isSticky()
- ? finishTime - mClock.currentTimeMillis()
- : Math.max(finishTime - now, mMinimumDisplayTime);
-
- mHandler.postDelayed(mRemoveAlertRunnable, timeRemaining);
+ if (!isSticky()) {
+ final long finishTime = calculateFinishTime();
+ final long timeLeft = Math.max(finishTime - now, mMinimumDisplayTime);
+ mHandler.postDelayed(mRemoveAlertRunnable, timeLeft);
+ }
}
/**
* Whether or not the notification is "sticky" i.e. should stay on screen regardless
- * of the timer and should be removed externally.
+ * of the timer (forever) and should be removed externally.
* @return true if the notification is sticky
*/
public boolean isSticky() {
// This implementation is overridden by HeadsUpManager HeadsUpEntry #isSticky
- // but we keep this here for use by unit tests.
- return mEntry.isStickyAndNotDemoted();
+ return false;
+ }
+
+ public boolean isStickyForSomeTime() {
+ // This implementation is overridden by HeadsUpManager HeadsUpEntry #isStickyForSomeTime
+ return false;
}
/**
@@ -360,8 +349,9 @@ public abstract class AlertingNotificationManager {
public void removeAsSoonAsPossible() {
if (mRemoveAlertRunnable != null) {
removeAutoRemovalCallbacks();
- mHandler.postDelayed(mRemoveAlertRunnable,
- mEarliestRemovaltime - mClock.currentTimeMillis());
+
+ final long timeLeft = mEarliestRemovaltime - mClock.currentTimeMillis();
+ mHandler.postDelayed(mRemoveAlertRunnable, timeLeft);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BatteryStatusChip.kt b/packages/SystemUI/src/com/android/systemui/statusbar/BatteryStatusChip.kt
new file mode 100644
index 000000000000..37140ec2aa32
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BatteryStatusChip.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2023 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
+
+import android.annotation.IntRange
+import android.annotation.SuppressLint
+import android.content.Context
+import android.content.res.Configuration
+import android.util.AttributeSet
+import android.view.View
+import android.widget.FrameLayout
+import android.widget.LinearLayout
+import com.android.settingslib.Utils
+import com.android.systemui.R
+import com.android.systemui.battery.BatteryMeterView
+import com.android.systemui.statusbar.events.BackgroundAnimatableView
+
+class BatteryStatusChip @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
+ FrameLayout(context, attrs), BackgroundAnimatableView {
+
+ private val roundedContainer: LinearLayout
+ private val batteryMeterView: BatteryMeterView
+ override val contentView: View
+ get() = batteryMeterView
+
+ init {
+ inflate(context, R.layout.battery_status_chip, this)
+ roundedContainer = findViewById(R.id.rounded_container)
+ batteryMeterView = findViewById(R.id.battery_meter_view)
+ updateResources()
+ }
+
+ /**
+ * When animating as a chip in the status bar, we want to animate the width for the rounded
+ * container. We have to subtract our own top and left offset because the bounds come to us as
+ * absolute on-screen bounds.
+ */
+ override fun setBoundsForAnimation(l: Int, t: Int, r: Int, b: Int) {
+ roundedContainer.setLeftTopRightBottom(l - left, t - top, r - left, b - top)
+ }
+
+ fun setBatteryLevel(@IntRange(from = 0, to = 100) batteryLevel: Int) {
+ batteryMeterView.setForceShowPercent(true)
+ batteryMeterView.onBatteryLevelChanged(batteryLevel, true)
+ }
+
+ override fun onConfigurationChanged(newConfig: Configuration) {
+ super.onConfigurationChanged(newConfig)
+ updateResources()
+ }
+
+ @SuppressLint("UseCompatLoadingForDrawables")
+ private fun updateResources() {
+ val primaryColor =
+ Utils.getColorAttrDefaultColor(context, com.android.internal.R.attr.colorPrimary)
+ val textColorSecondary =
+ Utils.getColorAttrDefaultColor(mContext, android.R.attr.textColorSecondary)
+ batteryMeterView.updateColors(primaryColor, textColorSecondary, primaryColor)
+ roundedContainer.background = mContext.getDrawable(R.drawable.statusbar_chip_bg)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 2cf1f53b4499..c435799748ee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -168,6 +168,7 @@ public class CommandQueue extends IStatusBar.Stub implements
private static final int MSG_GO_TO_FULLSCREEN_FROM_SPLIT = 70 << MSG_SHIFT;
private static final int MSG_ENTER_STAGE_SPLIT_FROM_RUNNING_APP = 71 << MSG_SHIFT;
private static final int MSG_SHOW_MEDIA_OUTPUT_SWITCHER = 72 << MSG_SHIFT;
+ private static final int MSG_TOGGLE_TASKBAR = 73 << MSG_SHIFT;
public static final int FLAG_EXCLUDE_NONE = 0;
public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -229,6 +230,7 @@ public class CommandQueue extends IStatusBar.Stub implements
@BackDispositionMode int backDisposition, boolean showImeSwitcher) { }
default void showRecentApps(boolean triggeredFromAltTab) { }
default void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) { }
+ default void toggleTaskbar() { }
default void toggleRecentApps() { }
default void toggleSplitScreen() { }
default void preloadRecentApps() { }
@@ -715,6 +717,13 @@ public class CommandQueue extends IStatusBar.Stub implements
}
}
+ public void toggleTaskbar() {
+ synchronized (mLock) {
+ mHandler.removeMessages(MSG_TOGGLE_TASKBAR);
+ mHandler.obtainMessage(MSG_TOGGLE_TASKBAR, 0, 0, null).sendToTarget();
+ }
+ }
+
public void toggleRecentApps() {
synchronized (mLock) {
mHandler.removeMessages(MSG_TOGGLE_RECENT_APPS);
@@ -1416,6 +1425,11 @@ public class CommandQueue extends IStatusBar.Stub implements
mCallbacks.get(i).hideRecentApps(msg.arg1 != 0, msg.arg2 != 0);
}
break;
+ case MSG_TOGGLE_TASKBAR:
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).toggleTaskbar();
+ }
+ break;
case MSG_TOGGLE_RECENT_APPS:
for (int i = 0; i < mCallbacks.size(); i++) {
mCallbacks.get(i).toggleRecentApps();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
index f20f929637cd..43fbc7cbae03 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
@@ -356,7 +356,7 @@ public final class KeyboardShortcuts {
* Keyboard with its default map.
*/
private void retrieveKeyCharacterMap(int deviceId) {
- final InputManager inputManager = InputManager.getInstance();
+ final InputManager inputManager = mContext.getSystemService(InputManager.class);
mBackupKeyCharacterMap = inputManager.getInputDevice(-1).getKeyCharacterMap();
if (deviceId != -1) {
final InputDevice inputDevice = inputManager.getInputDevice(deviceId);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutsReceiver.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutsReceiver.java
index e9fac28395ea..1cfb400280fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutsReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutsReceiver.java
@@ -39,7 +39,7 @@ public class KeyboardShortcutsReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
- if (mIsShortcutListSearchEnabled && Utilities.isTablet(context)) {
+ if (mIsShortcutListSearchEnabled && Utilities.isLargeScreen(context)) {
if (Intent.ACTION_SHOW_KEYBOARD_SHORTCUTS.equals(intent.getAction())) {
KeyboardShortcutListSearch.show(context, -1 /* deviceId unknown */);
} else if (Intent.ACTION_DISMISS_KEYBOARD_SHORTCUTS.equals(intent.getAction())) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt
index 62c225ba0b4e..df8c6abfff97 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt
@@ -148,7 +148,8 @@ constructor(
qsDragFraction: $qsTransitionFraction
qsSquishFraction: $qsSquishTransitionFraction
isTransitioningToFullShade: $isTransitioningToFullShade
- """.trimIndent()
+ """
+ .trimIndent()
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
index f0d064b42d9c..9a9503c8cd9c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
@@ -572,8 +572,7 @@ class LockscreenShadeTransitionController @Inject constructor(
entry.setGroupExpansionChanging(true)
userId = entry.sbn.userId
}
- var fullShadeNeedsBouncer = (!lockScreenUserManager.userAllowsPrivateNotificationsInPublic(
- lockScreenUserManager.getCurrentUserId()) ||
+ var fullShadeNeedsBouncer = (
!lockScreenUserManager.shouldShowLockscreenNotifications() ||
falsingCollector.shouldEnforceBouncer())
if (keyguardBypassController.bypassEnabled) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index f4cd985adbdb..51c5183ffee9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -213,7 +213,8 @@ public class NotificationLockscreenUserManagerImpl implements
DeviceProvisionedController deviceProvisionedController,
KeyguardStateController keyguardStateController,
SecureSettings secureSettings,
- DumpManager dumpManager) {
+ DumpManager dumpManager,
+ LockPatternUtils lockPatternUtils) {
mContext = context;
mMainHandler = mainHandler;
mDevicePolicyManager = devicePolicyManager;
@@ -225,7 +226,7 @@ public class NotificationLockscreenUserManagerImpl implements
mClickNotifier = clickNotifier;
mOverviewProxyServiceLazy = overviewProxyServiceLazy;
statusBarStateController.addCallback(this);
- mLockPatternUtils = new LockPatternUtils(context);
+ mLockPatternUtils = lockPatternUtils;
mKeyguardManager = keyguardManager;
mBroadcastDispatcher = broadcastDispatcher;
mDeviceProvisionedController = deviceProvisionedController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProvider.kt
index 42b874fd7156..7297ae689224 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProvider.kt
@@ -74,7 +74,7 @@ constructor(
/**
* @return a context with the MCC/MNC [Configuration] values corresponding to this
- * subscriptionId
+ * subscriptionId
*/
fun getMobileContextForSub(subId: Int, context: Context): Context {
if (demoModeController.isInDemoMode) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt
index bd5b8f0b17a5..bfc4e9c47db5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt
@@ -16,7 +16,7 @@
package com.android.systemui.statusbar.events
-import android.animation.Animator
+import androidx.core.animation.Animator
import android.annotation.UiThread
import android.graphics.Point
import android.graphics.Rect
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusBarEventsModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusBarEventsModule.kt
new file mode 100644
index 000000000000..3d6d48917dd3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusBarEventsModule.kt
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2023 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.events
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.statusbar.window.StatusBarWindowController
+import com.android.systemui.util.concurrency.DelayableExecutor
+import com.android.systemui.util.time.SystemClock
+import dagger.Module
+import dagger.Provides
+import kotlinx.coroutines.CoroutineScope
+
+@Module
+interface StatusBarEventsModule {
+
+ companion object {
+
+ @Provides
+ @SysUISingleton
+ fun provideSystemStatusAnimationScheduler(
+ featureFlags: FeatureFlags,
+ coordinator: SystemEventCoordinator,
+ chipAnimationController: SystemEventChipAnimationController,
+ statusBarWindowController: StatusBarWindowController,
+ dumpManager: DumpManager,
+ systemClock: SystemClock,
+ @Application coroutineScope: CoroutineScope,
+ @Main executor: DelayableExecutor
+ ): SystemStatusAnimationScheduler {
+ return if (featureFlags.isEnabled(Flags.PLUG_IN_STATUS_BAR_CHIP)) {
+ SystemStatusAnimationSchedulerImpl(
+ coordinator,
+ chipAnimationController,
+ statusBarWindowController,
+ dumpManager,
+ systemClock,
+ coroutineScope
+ )
+ } else {
+ SystemStatusAnimationSchedulerLegacyImpl(
+ coordinator,
+ chipAnimationController,
+ statusBarWindowController,
+ dumpManager,
+ systemClock,
+ executor
+ )
+ }
+ }
+ }
+}
+
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt
index 4e1404d0637b..43f78c3166e4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt
@@ -16,24 +16,21 @@
package com.android.systemui.statusbar.events
+import android.annotation.IntRange
import android.annotation.SuppressLint
import android.content.Context
-import android.graphics.Color
-import android.graphics.drawable.ColorDrawable
-import android.view.LayoutInflater
import android.view.View
import android.widget.ImageView
-import com.android.settingslib.graph.ThemedBatteryDrawable
-import com.android.systemui.R
import com.android.systemui.privacy.OngoingPrivacyChip
import com.android.systemui.privacy.PrivacyItem
+import com.android.systemui.statusbar.BatteryStatusChip
typealias ViewCreator = (context: Context) -> BackgroundAnimatableView
interface StatusEvent {
val priority: Int
// Whether or not to force the status bar open and show a dot
- val forceVisible: Boolean
+ var forceVisible: Boolean
// Whether or not to show an animation for this event
val showAnimation: Boolean
val viewCreator: ViewCreator
@@ -73,17 +70,16 @@ class BGImageView(
}
}
-class BatteryEvent : StatusEvent {
+class BatteryEvent(@IntRange(from = 0, to = 100) val batteryLevel: Int) : StatusEvent {
override val priority = 50
- override val forceVisible = false
+ override var forceVisible = false
override val showAnimation = true
override var contentDescription: String? = ""
- override val viewCreator: (context: Context) -> BGImageView = { context ->
- val iv = BGImageView(context)
- iv.setImageDrawable(ThemedBatteryDrawable(context, Color.WHITE))
- iv.setBackgroundDrawable(ColorDrawable(Color.GREEN))
- iv
+ override val viewCreator: ViewCreator = { context ->
+ BatteryStatusChip(context).apply {
+ setBatteryLevel(batteryLevel)
+ }
}
override fun toString(): String {
@@ -94,13 +90,12 @@ class BatteryEvent : StatusEvent {
class PrivacyEvent(override val showAnimation: Boolean = true) : StatusEvent {
override var contentDescription: String? = null
override val priority = 100
- override val forceVisible = true
+ override var forceVisible = true
var privacyItems: List<PrivacyItem> = listOf()
private var privacyChip: OngoingPrivacyChip? = null
override val viewCreator: ViewCreator = { context ->
- val v = LayoutInflater.from(context)
- .inflate(R.layout.ongoing_privacy_chip, null) as OngoingPrivacyChip
+ val v = OngoingPrivacyChip(context)
v.privacyList = privacyItems
v.contentDescription = contentDescription
privacyChip = v
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt
index 8405aea218f0..776956a20140 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt
@@ -16,10 +16,6 @@
package com.android.systemui.statusbar.events
-import android.animation.Animator
-import android.animation.AnimatorListenerAdapter
-import android.animation.AnimatorSet
-import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Rect
import android.view.ContextThemeWrapper
@@ -30,7 +26,13 @@ import android.view.View.MeasureSpec.AT_MOST
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.widget.FrameLayout
+import androidx.core.animation.Animator
+import androidx.core.animation.AnimatorListenerAdapter
+import androidx.core.animation.AnimatorSet
+import androidx.core.animation.ValueAnimator
import com.android.systemui.R
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
import com.android.systemui.statusbar.window.StatusBarWindowController
import com.android.systemui.util.animation.AnimationUtil.Companion.frames
@@ -43,7 +45,8 @@ import kotlin.math.roundToInt
class SystemEventChipAnimationController @Inject constructor(
private val context: Context,
private val statusBarWindowController: StatusBarWindowController,
- private val contentInsetsProvider: StatusBarContentInsetsProvider
+ private val contentInsetsProvider: StatusBarContentInsetsProvider,
+ private val featureFlags: FeatureFlags
) : SystemStatusAnimationCallback {
private lateinit var animationWindowView: FrameLayout
@@ -53,12 +56,14 @@ class SystemEventChipAnimationController @Inject constructor(
// Left for LTR, Right for RTL
private var animationDirection = LEFT
- private var chipRight = 0
- private var chipLeft = 0
- private var chipWidth = 0
+ private var chipBounds = Rect()
+ private val chipWidth get() = chipBounds.width()
+ private val chipRight get() = chipBounds.right
+ private val chipLeft get() = chipBounds.left
private var chipMinWidth = context.resources.getDimensionPixelSize(
R.dimen.ongoing_appops_chip_min_animation_width)
- private var dotSize = context.resources.getDimensionPixelSize(
+
+ private val dotSize = context.resources.getDimensionPixelSize(
R.dimen.ongoing_appops_dot_diameter)
// Use during animation so that multiple animators can update the drawing rect
private var animRect = Rect()
@@ -90,21 +95,26 @@ class SystemEventChipAnimationController @Inject constructor(
it.view.measure(
View.MeasureSpec.makeMeasureSpec(
(animationWindowView.parent as View).width, AT_MOST),
- View.MeasureSpec.makeMeasureSpec(animationWindowView.height, AT_MOST))
- chipWidth = it.chipWidth
- }
-
- // decide which direction we're animating from, and then set some screen coordinates
- val contentRect = contentInsetsProvider.getStatusBarContentAreaForCurrentRotation()
- when (animationDirection) {
- LEFT -> {
- chipRight = contentRect.right
- chipLeft = contentRect.right - chipWidth
- }
- else /* RIGHT */ -> {
- chipLeft = contentRect.left
- chipRight = contentRect.left + chipWidth
+ View.MeasureSpec.makeMeasureSpec(
+ (animationWindowView.parent as View).height, AT_MOST))
+
+ // decide which direction we're animating from, and then set some screen coordinates
+ val contentRect = contentInsetsProvider.getStatusBarContentAreaForCurrentRotation()
+ val chipTop = ((animationWindowView.parent as View).height - it.view.measuredHeight) / 2
+ val chipBottom = chipTop + it.view.measuredHeight
+ val chipRight: Int
+ val chipLeft: Int
+ when (animationDirection) {
+ LEFT -> {
+ chipRight = contentRect.right
+ chipLeft = contentRect.right - it.chipWidth
+ }
+ else /* RIGHT */ -> {
+ chipLeft = contentRect.left
+ chipRight = contentRect.left + it.chipWidth
+ }
}
+ chipBounds = Rect(chipLeft, chipTop, chipRight, chipBottom)
}
}
@@ -117,16 +127,21 @@ class SystemEventChipAnimationController @Inject constructor(
interpolator = null
addUpdateListener { currentAnimatedView?.view?.alpha = animatedValue as Float }
}
+ currentAnimatedView?.contentView?.alpha = 0f
+ val contentAlphaIn = ValueAnimator.ofFloat(0f, 1f).apply {
+ startDelay = 10.frames
+ duration = 10.frames
+ interpolator = null
+ addUpdateListener { currentAnimatedView?.contentView?.alpha = animatedValue as Float }
+ }
val moveIn = ValueAnimator.ofInt(chipMinWidth, chipWidth).apply {
startDelay = 7.frames
duration = 23.frames
interpolator = STATUS_BAR_X_MOVE_IN
- addUpdateListener {
- updateAnimatedViewBoundsWidth(animatedValue as Int)
- }
+ addUpdateListener { updateAnimatedViewBoundsWidth(animatedValue as Int) }
}
val animSet = AnimatorSet()
- animSet.playTogether(alphaIn, moveIn)
+ animSet.playTogether(alphaIn, contentAlphaIn, moveIn)
return animSet
}
@@ -139,7 +154,7 @@ class SystemEventChipAnimationController @Inject constructor(
}
finish.addListener(object : AnimatorListenerAdapter() {
- override fun onAnimationEnd(animation: Animator?) {
+ override fun onAnimationEnd(animation: Animator) {
animationWindowView.removeView(currentAnimatedView!!.view)
}
})
@@ -152,7 +167,7 @@ class SystemEventChipAnimationController @Inject constructor(
duration = 9.frames
interpolator = STATUS_CHIP_WIDTH_TO_DOT_KEYFRAME_1
addUpdateListener {
- updateAnimatedViewBoundsWidth(it.animatedValue as Int)
+ updateAnimatedViewBoundsWidth(animatedValue as Int)
}
}
@@ -161,7 +176,7 @@ class SystemEventChipAnimationController @Inject constructor(
duration = 20.frames
interpolator = STATUS_CHIP_WIDTH_TO_DOT_KEYFRAME_2
addUpdateListener {
- updateAnimatedViewBoundsWidth(it.animatedValue as Int)
+ updateAnimatedViewBoundsWidth(animatedValue as Int)
}
}
@@ -174,7 +189,7 @@ class SystemEventChipAnimationController @Inject constructor(
duration = 6.frames
interpolator = STATUS_CHIP_HEIGHT_TO_DOT_KEYFRAME_1
addUpdateListener {
- updateAnimatedViewBoundsHeight(it.animatedValue as Int, chipVerticalCenter)
+ updateAnimatedViewBoundsHeight(animatedValue as Int, chipVerticalCenter)
}
}
@@ -183,7 +198,7 @@ class SystemEventChipAnimationController @Inject constructor(
duration = 15.frames
interpolator = STATUS_CHIP_HEIGHT_TO_DOT_KEYFRAME_2
addUpdateListener {
- updateAnimatedViewBoundsHeight(it.animatedValue as Int, chipVerticalCenter)
+ updateAnimatedViewBoundsHeight(animatedValue as Int, chipVerticalCenter)
}
}
@@ -210,15 +225,32 @@ class SystemEventChipAnimationController @Inject constructor(
}
private fun createMoveOutAnimationDefault(): Animator {
+ val alphaOut = ValueAnimator.ofFloat(1f, 0f).apply {
+ startDelay = 6.frames
+ duration = 6.frames
+ interpolator = null
+ addUpdateListener { currentAnimatedView?.view?.alpha = animatedValue as Float }
+ }
+
+ val contentAlphaOut = ValueAnimator.ofFloat(1f, 0f).apply {
+ duration = 5.frames
+ interpolator = null
+ addUpdateListener { currentAnimatedView?.contentView?.alpha = animatedValue as Float }
+ }
+
val moveOut = ValueAnimator.ofInt(chipWidth, chipMinWidth).apply {
duration = 23.frames
+ interpolator = STATUS_BAR_X_MOVE_OUT
addUpdateListener {
currentAnimatedView?.apply {
- updateAnimatedViewBoundsWidth(it.animatedValue as Int)
+ updateAnimatedViewBoundsWidth(animatedValue as Int)
}
}
}
- return moveOut
+
+ val animSet = AnimatorSet()
+ animSet.playTogether(alphaOut, contentAlphaOut, moveOut)
+ return animSet
}
private fun init() {
@@ -239,11 +271,15 @@ class SystemEventChipAnimationController @Inject constructor(
it.marginEnd = marginEnd
}
- private fun initializeAnimRect() = animRect.set(
- chipLeft,
- currentAnimatedView!!.view.top,
- chipRight,
- currentAnimatedView!!.view.bottom)
+ private fun initializeAnimRect() = if (featureFlags.isEnabled(Flags.PLUG_IN_STATUS_BAR_CHIP)) {
+ animRect.set(chipBounds)
+ } else {
+ animRect.set(
+ chipLeft,
+ currentAnimatedView!!.view.top,
+ chipRight,
+ currentAnimatedView!!.view.bottom)
+ }
/**
* To be called during an animation, sets the width and updates the current animated chip view
@@ -296,6 +332,8 @@ class SystemEventChipAnimationController @Inject constructor(
interface BackgroundAnimatableView {
val view: View // Since this can't extend View, add a view prop
get() = this as View
+ val contentView: View? // This will be alpha faded during appear and disappear animation
+ get() = null
val chipWidth: Int
get() = view.measuredWidth
fun setBoundsForAnimation(l: Int, t: Int, r: Int, b: Int)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt
index fde5d39db7e3..26fd2307c59d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt
@@ -16,11 +16,14 @@
package com.android.systemui.statusbar.events
+import android.annotation.IntRange
import android.content.Context
import android.provider.DeviceConfig
import android.provider.DeviceConfig.NAMESPACE_PRIVACY
import com.android.systemui.R
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
import com.android.systemui.privacy.PrivacyChipBuilder
import com.android.systemui.privacy.PrivacyItem
import com.android.systemui.privacy.PrivacyItemController
@@ -37,21 +40,18 @@ class SystemEventCoordinator @Inject constructor(
private val systemClock: SystemClock,
private val batteryController: BatteryController,
private val privacyController: PrivacyItemController,
- private val context: Context
+ private val context: Context,
+ private val featureFlags: FeatureFlags
) {
private lateinit var scheduler: SystemStatusAnimationScheduler
fun startObserving() {
- /* currently unused
batteryController.addCallback(batteryStateListener)
- */
privacyController.addCallback(privacyStateListener)
}
fun stopObserving() {
- /* currently unused
batteryController.removeCallback(batteryStateListener)
- */
privacyController.removeCallback(privacyStateListener)
}
@@ -59,12 +59,14 @@ class SystemEventCoordinator @Inject constructor(
this.scheduler = s
}
- fun notifyPluggedIn() {
- scheduler.onStatusEvent(BatteryEvent())
+ fun notifyPluggedIn(@IntRange(from = 0, to = 100) batteryLevel: Int) {
+ if (featureFlags.isEnabled(Flags.PLUG_IN_STATUS_BAR_CHIP)) {
+ scheduler.onStatusEvent(BatteryEvent(batteryLevel))
+ }
}
fun notifyPrivacyItemsEmpty() {
- scheduler.setShouldShowPersistentPrivacyIndicator(false)
+ scheduler.removePersistentDot()
}
fun notifyPrivacyItemsChanged(showAnimation: Boolean = true) {
@@ -79,25 +81,25 @@ class SystemEventCoordinator @Inject constructor(
}
private val batteryStateListener = object : BatteryController.BatteryStateChangeCallback {
- var plugged = false
- var stateKnown = false
+ private var plugged = false
+ private var stateKnown = false
override fun onBatteryLevelChanged(level: Int, pluggedIn: Boolean, charging: Boolean) {
if (!stateKnown) {
stateKnown = true
plugged = pluggedIn
- notifyListeners()
+ notifyListeners(level)
return
}
if (plugged != pluggedIn) {
plugged = pluggedIn
- notifyListeners()
+ notifyListeners(level)
}
}
- private fun notifyListeners() {
+ private fun notifyListeners(@IntRange(from = 0, to = 100) batteryLevel: Int) {
// We only care about the plugged in status
- if (plugged) notifyPluggedIn()
+ if (plugged) notifyPluggedIn(batteryLevel)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
index 197cf5608cf5..2a18f1f51ace 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2023 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.
@@ -16,302 +16,21 @@
package com.android.systemui.statusbar.events
-import android.animation.Animator
-import android.animation.AnimatorListenerAdapter
-import android.animation.AnimatorSet
import android.annotation.IntDef
-import android.os.Process
-import android.provider.DeviceConfig
-import android.util.Log
-import android.view.animation.PathInterpolator
+import androidx.core.animation.Animator
+import androidx.core.animation.AnimatorSet
+import androidx.core.animation.PathInterpolator
import com.android.systemui.Dumpable
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.dump.DumpManager
import com.android.systemui.statusbar.policy.CallbackController
-import com.android.systemui.statusbar.window.StatusBarWindowController
-import com.android.systemui.util.Assert
-import com.android.systemui.util.concurrency.DelayableExecutor
-import com.android.systemui.util.time.SystemClock
-import java.io.PrintWriter
-import javax.inject.Inject
-/**
- * Dead-simple scheduler for system status events. Obeys the following principles (all values TBD):
- * - Avoiding log spam by only allowing 12 events per minute (1event/5s)
- * - Waits 100ms to schedule any event for debouncing/prioritization
- * - Simple prioritization: Privacy > Battery > connectivity (encoded in [StatusEvent])
- * - Only schedules a single event, and throws away lowest priority events
- *
- * There are 4 basic stages of animation at play here:
- * 1. System chrome animation OUT
- * 2. Chip animation IN
- * 3. Chip animation OUT; potentially into a dot
- * 4. System chrome animation IN
- *
- * Thus we can keep all animations synchronized with two separate ValueAnimators, one for system
- * chrome and the other for the chip. These can animate from 0,1 and listeners can parameterize
- * their respective views based on the progress of the animator. Interpolation differences TBD
- */
-@SysUISingleton
-open class SystemStatusAnimationScheduler @Inject constructor(
- private val coordinator: SystemEventCoordinator,
- private val chipAnimationController: SystemEventChipAnimationController,
- private val statusBarWindowController: StatusBarWindowController,
- private val dumpManager: DumpManager,
- private val systemClock: SystemClock,
- @Main private val executor: DelayableExecutor
-) : CallbackController<SystemStatusAnimationCallback>, Dumpable {
-
- companion object {
- private const val PROPERTY_ENABLE_IMMERSIVE_INDICATOR = "enable_immersive_indicator"
- }
- public fun isImmersiveIndicatorEnabled(): Boolean {
- return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
- PROPERTY_ENABLE_IMMERSIVE_INDICATOR, true)
- }
-
- @SystemAnimationState var animationState: Int = IDLE
- private set
-
- /** True if the persistent privacy dot should be active */
- var hasPersistentDot = false
- protected set
-
- private var scheduledEvent: StatusEvent? = null
- private var cancelExecutionRunnable: Runnable? = null
- private val listeners = mutableSetOf<SystemStatusAnimationCallback>()
-
- fun getListeners(): MutableSet<SystemStatusAnimationCallback> {
- return listeners
- }
-
- init {
- coordinator.attachScheduler(this)
- dumpManager.registerDumpable(TAG, this)
- }
-
- open fun onStatusEvent(event: StatusEvent) {
- // Ignore any updates until the system is up and running
- if (isTooEarly() || !isImmersiveIndicatorEnabled()) {
- return
- }
-
- // Don't deal with threading for now (no need let's be honest)
- Assert.isMainThread()
- if ((event.priority > scheduledEvent?.priority ?: -1) &&
- animationState != ANIMATING_OUT &&
- (animationState != SHOWING_PERSISTENT_DOT && event.forceVisible)) {
- // events can only be scheduled if a higher priority or no other event is in progress
- if (DEBUG) {
- Log.d(TAG, "scheduling event $event")
- }
-
- scheduleEvent(event)
- } else if (scheduledEvent?.shouldUpdateFromEvent(event) == true) {
- if (DEBUG) {
- Log.d(TAG, "updating current event from: $event. animationState=$animationState")
- }
- scheduledEvent?.updateFromEvent(event)
- if (event.forceVisible) {
- hasPersistentDot = true
- // If we missed the chance to show the persistent dot, do it now
- if (animationState == IDLE) {
- notifyTransitionToPersistentDot()
- }
- }
- } else {
- if (DEBUG) {
- Log.d(TAG, "ignoring event $event")
- }
- }
- }
-
- private fun clearDotIfVisible() {
- notifyHidePersistentDot()
- }
-
- fun setShouldShowPersistentPrivacyIndicator(should: Boolean) {
- if (hasPersistentDot == should || !isImmersiveIndicatorEnabled()) {
- return
- }
-
- hasPersistentDot = should
-
- if (!hasPersistentDot) {
- clearDotIfVisible()
- }
- }
-
- public fun isTooEarly(): Boolean {
- return systemClock.uptimeMillis() - Process.getStartUptimeMillis() < MIN_UPTIME
- }
-
- /**
- * Clear the scheduled event (if any) and schedule a new one
- */
- private fun scheduleEvent(event: StatusEvent) {
- scheduledEvent = event
-
- if (event.forceVisible) {
- hasPersistentDot = true
- }
-
- // If animations are turned off, we'll transition directly to the dot
- if (!event.showAnimation && event.forceVisible) {
- notifyTransitionToPersistentDot()
- scheduledEvent = null
- return
- }
-
- chipAnimationController.prepareChipAnimation(scheduledEvent!!.viewCreator)
- animationState = ANIMATION_QUEUED
- executor.executeDelayed({
- runChipAnimation()
- }, DEBOUNCE_DELAY)
- }
-
- /**
- * 1. Define a total budget for the chip animation (1500ms)
- * 2. Send out callbacks to listeners so that they can generate animations locally
- * 3. Update the scheduler state so that clients know where we are
- * 4. Maybe: provide scaffolding such as: dot location, margins, etc
- * 5. Maybe: define a maximum animation length and enforce it. Probably only doable if we
- * collect all of the animators and run them together.
- */
- private fun runChipAnimation() {
- statusBarWindowController.setForceStatusBarVisible(true)
- animationState = ANIMATING_IN
-
- val animSet = collectStartAnimations()
- if (animSet.totalDuration > 500) {
- throw IllegalStateException("System animation total length exceeds budget. " +
- "Expected: 500, actual: ${animSet.totalDuration}")
- }
- animSet.addListener(object : AnimatorListenerAdapter() {
- override fun onAnimationEnd(animation: Animator?) {
- animationState = RUNNING_CHIP_ANIM
- }
- })
- animSet.start()
-
- executor.executeDelayed({
- val animSet2 = collectFinishAnimations()
- animationState = ANIMATING_OUT
- animSet2.addListener(object : AnimatorListenerAdapter() {
- override fun onAnimationEnd(animation: Animator?) {
- animationState = if (hasPersistentDot) {
- SHOWING_PERSISTENT_DOT
- } else {
- IDLE
- }
-
- statusBarWindowController.setForceStatusBarVisible(false)
- }
- })
- animSet2.start()
- scheduledEvent = null
- }, DISPLAY_LENGTH)
- }
-
- private fun collectStartAnimations(): AnimatorSet {
- val animators = mutableListOf<Animator>()
- listeners.forEach { listener ->
- listener.onSystemEventAnimationBegin()?.let { anim ->
- animators.add(anim)
- }
- }
- animators.add(chipAnimationController.onSystemEventAnimationBegin())
- val animSet = AnimatorSet().also {
- it.playTogether(animators)
- }
-
- return animSet
- }
-
- private fun collectFinishAnimations(): AnimatorSet {
- val animators = mutableListOf<Animator>()
- listeners.forEach { listener ->
- listener.onSystemEventAnimationFinish(hasPersistentDot)?.let { anim ->
- animators.add(anim)
- }
- }
- animators.add(chipAnimationController.onSystemEventAnimationFinish(hasPersistentDot))
- if (hasPersistentDot) {
- val dotAnim = notifyTransitionToPersistentDot()
- if (dotAnim != null) {
- animators.add(dotAnim)
- }
- }
- val animSet = AnimatorSet().also {
- it.playTogether(animators)
- }
-
- return animSet
- }
-
- private fun notifyTransitionToPersistentDot(): Animator? {
- val anims: List<Animator> = listeners.mapNotNull {
- it.onSystemStatusAnimationTransitionToPersistentDot(scheduledEvent?.contentDescription)
- }
- if (anims.isNotEmpty()) {
- val aSet = AnimatorSet()
- aSet.playTogether(anims)
- return aSet
- }
-
- return null
- }
-
- private fun notifyHidePersistentDot(): Animator? {
- val anims: List<Animator> = listeners.mapNotNull {
- it.onHidePersistentDot()
- }
-
- if (animationState == SHOWING_PERSISTENT_DOT) {
- animationState = IDLE
- }
-
- if (anims.isNotEmpty()) {
- val aSet = AnimatorSet()
- aSet.playTogether(anims)
- return aSet
- }
+interface SystemStatusAnimationScheduler :
+ CallbackController<SystemStatusAnimationCallback>, Dumpable {
- return null
- }
+ @SystemAnimationState fun getAnimationState(): Int
- override fun addCallback(listener: SystemStatusAnimationCallback) {
- Assert.isMainThread()
-
- if (listeners.isEmpty()) {
- coordinator.startObserving()
- }
- listeners.add(listener)
- }
+ fun onStatusEvent(event: StatusEvent)
- override fun removeCallback(listener: SystemStatusAnimationCallback) {
- Assert.isMainThread()
-
- listeners.remove(listener)
- if (listeners.isEmpty()) {
- coordinator.stopObserving()
- }
- }
-
- override fun dump(pw: PrintWriter, args: Array<out String>) {
- pw.println("Scheduled event: $scheduledEvent")
- pw.println("Has persistent privacy dot: $hasPersistentDot")
- pw.println("Animation state: $animationState")
- pw.println("Listeners:")
- if (listeners.isEmpty()) {
- pw.println("(none)")
- } else {
- listeners.forEach {
- pw.println(" $it")
- }
- }
- }
+ fun removePersistentDot()
}
/**
@@ -337,6 +56,7 @@ interface SystemStatusAnimationCallback {
@JvmDefault fun onHidePersistentDot(): Animator? { return null }
}
+
/**
* Animation state IntDef
*/
@@ -354,7 +74,7 @@ interface SystemStatusAnimationCallback {
annotation class SystemAnimationState
/** No animation is in progress */
-const val IDLE = 0
+@SystemAnimationState const val IDLE = 0
/** An animation is queued, and awaiting the debounce period */
const val ANIMATION_QUEUED = 1
/** System is animating out, and chip is animating in */
@@ -379,20 +99,16 @@ val STATUS_CHIP_HEIGHT_TO_DOT_KEYFRAME_1 = PathInterpolator(0.4f, 0f, 0.17f, 1f)
val STATUS_CHIP_HEIGHT_TO_DOT_KEYFRAME_2 = PathInterpolator(0.3f, 0f, 0f, 1f)
val STATUS_CHIP_MOVE_TO_DOT = PathInterpolator(0f, 0f, 0.05f, 1f)
-private const val TAG = "SystemStatusAnimationScheduler"
-private const val DEBOUNCE_DELAY = 100L
+internal const val DEBOUNCE_DELAY = 100L
/**
* The total time spent on the chip animation is 1500ms, broken up into 3 sections:
- * - 500ms to animate the chip in (including animating system icons away)
- * - 500ms holding the chip on screen
- * - 500ms to animate the chip away (and system icons back)
- *
- * So DISPLAY_LENGTH should be the sum of the first 2 phases, while the final 500ms accounts for
- * the actual animation
+ * - 500ms to animate the chip in (including animating system icons away)
+ * - 500ms holding the chip on screen
+ * - 500ms to animate the chip away (and system icons back)
*/
-private const val DISPLAY_LENGTH = 1000L
-
-private const val MIN_UPTIME: Long = 5 * 1000
+internal const val APPEAR_ANIMATION_DURATION = 500L
+internal const val DISPLAY_LENGTH = 3000L
+internal const val DISAPPEAR_ANIMATION_DURATION = 500L
-private const val DEBUG = false
+internal const val MIN_UPTIME: Long = 5 * 1000 \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImpl.kt
new file mode 100644
index 000000000000..f7a4feafee25
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImpl.kt
@@ -0,0 +1,425 @@
+/*
+ * Copyright (C) 2023 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.events
+
+import android.os.Process
+import android.provider.DeviceConfig
+import android.util.Log
+import androidx.core.animation.Animator
+import androidx.core.animation.AnimatorListenerAdapter
+import androidx.core.animation.AnimatorSet
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.statusbar.window.StatusBarWindowController
+import com.android.systemui.util.Assert
+import com.android.systemui.util.time.SystemClock
+import java.io.PrintWriter
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.FlowPreview
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.debounce
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withTimeout
+
+/**
+ * Scheduler for system status events. Obeys the following principles:
+ * ```
+ * - Waits 100 ms to schedule any event for debouncing/prioritization
+ * - Simple prioritization: Privacy > Battery > Connectivity (encoded in [StatusEvent])
+ * - Only schedules a single event, and throws away lowest priority events
+ * ```
+ *
+ * There are 4 basic stages of animation at play here:
+ * ```
+ * 1. System chrome animation OUT
+ * 2. Chip animation IN
+ * 3. Chip animation OUT; potentially into a dot
+ * 4. System chrome animation IN
+ * ```
+ *
+ * Thus we can keep all animations synchronized with two separate ValueAnimators, one for system
+ * chrome and the other for the chip. These can animate from 0,1 and listeners can parameterize
+ * their respective views based on the progress of the animator.
+ */
+@OptIn(FlowPreview::class)
+open class SystemStatusAnimationSchedulerImpl
+@Inject
+constructor(
+ private val coordinator: SystemEventCoordinator,
+ private val chipAnimationController: SystemEventChipAnimationController,
+ private val statusBarWindowController: StatusBarWindowController,
+ dumpManager: DumpManager,
+ private val systemClock: SystemClock,
+ @Application private val coroutineScope: CoroutineScope
+) : SystemStatusAnimationScheduler {
+
+ companion object {
+ private const val PROPERTY_ENABLE_IMMERSIVE_INDICATOR = "enable_immersive_indicator"
+ }
+
+ /** Contains the StatusEvent that is going to be displayed next. */
+ private var scheduledEvent = MutableStateFlow<StatusEvent?>(null)
+
+ /**
+ * The currently displayed status event. (This is null in all states except ANIMATING_IN and
+ * CHIP_ANIMATION_RUNNING)
+ */
+ private var currentlyDisplayedEvent: StatusEvent? = null
+
+ /** StateFlow holding the current [SystemAnimationState] at any time. */
+ private var animationState = MutableStateFlow(IDLE)
+
+ /** True if the persistent privacy dot should be active */
+ var hasPersistentDot = false
+ protected set
+
+ /** Set of currently registered listeners */
+ protected val listeners = mutableSetOf<SystemStatusAnimationCallback>()
+
+ /** The job that is controlling the animators of the currently displayed status event. */
+ private var currentlyRunningAnimationJob: Job? = null
+
+ /** The job that is controlling the animators when an event is cancelled. */
+ private var eventCancellationJob: Job? = null
+
+ init {
+ coordinator.attachScheduler(this)
+ dumpManager.registerCriticalDumpable(TAG, this)
+
+ coroutineScope.launch {
+ // Wait for animationState to become ANIMATION_QUEUED and scheduledEvent to be non null.
+ // Once this combination is stable for at least DEBOUNCE_DELAY, then start a chip enter
+ // animation
+ animationState
+ .combine(scheduledEvent) { animationState, scheduledEvent ->
+ Pair(animationState, scheduledEvent)
+ }
+ .debounce(DEBOUNCE_DELAY)
+ .collect { (animationState, event) ->
+ if (animationState == ANIMATION_QUEUED && event != null) {
+ startAnimationLifecycle(event)
+ scheduledEvent.value = null
+ }
+ }
+ }
+ }
+
+ @SystemAnimationState override fun getAnimationState(): Int = animationState.value
+
+ override fun onStatusEvent(event: StatusEvent) {
+ Assert.isMainThread()
+
+ // Ignore any updates until the system is up and running
+ if (isTooEarly() || !isImmersiveIndicatorEnabled()) {
+ return
+ }
+
+ if (
+ (event.priority > (scheduledEvent.value?.priority ?: -1)) &&
+ (event.priority > (currentlyDisplayedEvent?.priority ?: -1)) &&
+ !hasPersistentDot
+ ) {
+ // a event can only be scheduled if no other event is in progress or it has a higher
+ // priority. If a persistent dot is currently displayed, don't schedule the event.
+ if (DEBUG) {
+ Log.d(TAG, "scheduling event $event")
+ }
+
+ scheduleEvent(event)
+ } else if (currentlyDisplayedEvent?.shouldUpdateFromEvent(event) == true) {
+ if (DEBUG) {
+ Log.d(
+ TAG,
+ "updating current event from: $event. animationState=${animationState.value}"
+ )
+ }
+ currentlyDisplayedEvent?.updateFromEvent(event)
+ } else if (scheduledEvent.value?.shouldUpdateFromEvent(event) == true) {
+ if (DEBUG) {
+ Log.d(
+ TAG,
+ "updating scheduled event from: $event. animationState=${animationState.value}"
+ )
+ }
+ scheduledEvent.value?.updateFromEvent(event)
+ } else {
+ if (DEBUG) {
+ Log.d(TAG, "ignoring event $event")
+ }
+ }
+ }
+
+ override fun removePersistentDot() {
+ Assert.isMainThread()
+
+ // If there is an event scheduled currently, set its forceVisible flag to false, such that
+ // it will never transform into a persistent dot
+ scheduledEvent.value?.forceVisible = false
+
+ // Nothing else to do if hasPersistentDot is already false
+ if (!hasPersistentDot) return
+ // Set hasPersistentDot to false. If the animationState is anything before ANIMATING_OUT,
+ // the disappear animation will not animate into a dot but remove the chip entirely
+ hasPersistentDot = false
+ // if we are currently showing a persistent dot, hide it
+ if (animationState.value == SHOWING_PERSISTENT_DOT) notifyHidePersistentDot()
+ // if we are currently animating into a dot, wait for the animation to finish and then hide
+ // the dot
+ if (animationState.value == ANIMATING_OUT) {
+ coroutineScope.launch {
+ withTimeout(DISAPPEAR_ANIMATION_DURATION) {
+ animationState.first { it == SHOWING_PERSISTENT_DOT || it == ANIMATION_QUEUED }
+ notifyHidePersistentDot()
+ }
+ }
+ }
+ }
+
+ protected fun isTooEarly(): Boolean {
+ return systemClock.uptimeMillis() - Process.getStartUptimeMillis() < MIN_UPTIME
+ }
+
+ protected fun isImmersiveIndicatorEnabled(): Boolean {
+ return DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_PRIVACY,
+ PROPERTY_ENABLE_IMMERSIVE_INDICATOR,
+ true
+ )
+ }
+
+ /** Clear the scheduled event (if any) and schedule a new one */
+ private fun scheduleEvent(event: StatusEvent) {
+ scheduledEvent.value = event
+ if (currentlyDisplayedEvent != null && eventCancellationJob?.isActive != true) {
+ // cancel the currently displayed event. As soon as the event is animated out, the
+ // scheduled event will be displayed.
+ cancelCurrentlyDisplayedEvent()
+ return
+ }
+ if (animationState.value == IDLE) {
+ // If we are in IDLE state, set it to ANIMATION_QUEUED now
+ animationState.value = ANIMATION_QUEUED
+ }
+ }
+
+ /**
+ * Cancels the currently displayed event by animating it out. This function should only be
+ * called if the animationState is ANIMATING_IN or RUNNING_CHIP_ANIM, or in other words whenever
+ * currentlyRunningEvent is not null
+ */
+ private fun cancelCurrentlyDisplayedEvent() {
+ eventCancellationJob =
+ coroutineScope.launch {
+ withTimeout(APPEAR_ANIMATION_DURATION) {
+ // wait for animationState to become RUNNING_CHIP_ANIM, then cancel the running
+ // animation job and run the disappear animation immediately
+ animationState.first { it == RUNNING_CHIP_ANIM }
+ currentlyRunningAnimationJob?.cancel()
+ runChipDisappearAnimation()
+ }
+ }
+ }
+
+ /**
+ * Takes the currently scheduled Event and (using the coroutineScope) animates it in and out
+ * again after displaying it for DISPLAY_LENGTH ms. This function should only be called if there
+ * is an event scheduled (and currentlyDisplayedEvent is null)
+ */
+ private fun startAnimationLifecycle(event: StatusEvent) {
+ Assert.isMainThread()
+ hasPersistentDot = event.forceVisible
+
+ if (!event.showAnimation && event.forceVisible) {
+ // If animations are turned off, we'll transition directly to the dot
+ animationState.value = SHOWING_PERSISTENT_DOT
+ notifyTransitionToPersistentDot()
+ return
+ }
+
+ currentlyDisplayedEvent = event
+
+ chipAnimationController.prepareChipAnimation(event.viewCreator)
+ currentlyRunningAnimationJob =
+ coroutineScope.launch {
+ runChipAppearAnimation()
+ delay(APPEAR_ANIMATION_DURATION + DISPLAY_LENGTH)
+ runChipDisappearAnimation()
+ }
+ }
+
+ /**
+ * 1. Define a total budget for the chip animation (1500ms)
+ * 2. Send out callbacks to listeners so that they can generate animations locally
+ * 3. Update the scheduler state so that clients know where we are
+ * 4. Maybe: provide scaffolding such as: dot location, margins, etc
+ * 5. Maybe: define a maximum animation length and enforce it. Probably only doable if we
+ * collect all of the animators and run them together.
+ */
+ private fun runChipAppearAnimation() {
+ Assert.isMainThread()
+ if (hasPersistentDot) {
+ statusBarWindowController.setForceStatusBarVisible(true)
+ }
+ animationState.value = ANIMATING_IN
+
+ val animSet = collectStartAnimations()
+ if (animSet.totalDuration > 500) {
+ throw IllegalStateException(
+ "System animation total length exceeds budget. " +
+ "Expected: 500, actual: ${animSet.totalDuration}"
+ )
+ }
+ animSet.addListener(
+ object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator) {
+ animationState.value = RUNNING_CHIP_ANIM
+ }
+ }
+ )
+ animSet.start()
+ }
+
+ private fun runChipDisappearAnimation() {
+ Assert.isMainThread()
+ val animSet2 = collectFinishAnimations()
+ animationState.value = ANIMATING_OUT
+ animSet2.addListener(
+ object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator) {
+ animationState.value =
+ when {
+ hasPersistentDot -> SHOWING_PERSISTENT_DOT
+ scheduledEvent.value != null -> ANIMATION_QUEUED
+ else -> IDLE
+ }
+ statusBarWindowController.setForceStatusBarVisible(false)
+ }
+ }
+ )
+ animSet2.start()
+
+ // currentlyDisplayedEvent is set to null before the animation has ended such that new
+ // events can be scheduled during the disappear animation. We don't want to miss e.g. a new
+ // privacy event being scheduled during the disappear animation, otherwise we could end up
+ // with e.g. an active microphone but no privacy dot being displayed.
+ currentlyDisplayedEvent = null
+ }
+
+ private fun collectStartAnimations(): AnimatorSet {
+ val animators = mutableListOf<Animator>()
+ listeners.forEach { listener ->
+ listener.onSystemEventAnimationBegin()?.let { anim -> animators.add(anim) }
+ }
+ animators.add(chipAnimationController.onSystemEventAnimationBegin())
+
+ return AnimatorSet().also { it.playTogether(animators) }
+ }
+
+ private fun collectFinishAnimations(): AnimatorSet {
+ val animators = mutableListOf<Animator>()
+ listeners.forEach { listener ->
+ listener.onSystemEventAnimationFinish(hasPersistentDot)?.let { anim ->
+ animators.add(anim)
+ }
+ }
+ animators.add(chipAnimationController.onSystemEventAnimationFinish(hasPersistentDot))
+ if (hasPersistentDot) {
+ val dotAnim = notifyTransitionToPersistentDot()
+ if (dotAnim != null) {
+ animators.add(dotAnim)
+ }
+ }
+
+ return AnimatorSet().also { it.playTogether(animators) }
+ }
+
+ private fun notifyTransitionToPersistentDot(): Animator? {
+ val anims: List<Animator> =
+ listeners.mapNotNull {
+ it.onSystemStatusAnimationTransitionToPersistentDot(
+ currentlyDisplayedEvent?.contentDescription
+ )
+ }
+ if (anims.isNotEmpty()) {
+ val aSet = AnimatorSet()
+ aSet.playTogether(anims)
+ return aSet
+ }
+
+ return null
+ }
+
+ private fun notifyHidePersistentDot(): Animator? {
+ Assert.isMainThread()
+ val anims: List<Animator> = listeners.mapNotNull { it.onHidePersistentDot() }
+
+ if (animationState.value == SHOWING_PERSISTENT_DOT) {
+ if (scheduledEvent.value != null) {
+ animationState.value = ANIMATION_QUEUED
+ } else {
+ animationState.value = IDLE
+ }
+ }
+
+ if (anims.isNotEmpty()) {
+ val aSet = AnimatorSet()
+ aSet.playTogether(anims)
+ return aSet
+ }
+
+ return null
+ }
+
+ override fun addCallback(listener: SystemStatusAnimationCallback) {
+ Assert.isMainThread()
+
+ if (listeners.isEmpty()) {
+ coordinator.startObserving()
+ }
+ listeners.add(listener)
+ }
+
+ override fun removeCallback(listener: SystemStatusAnimationCallback) {
+ Assert.isMainThread()
+
+ listeners.remove(listener)
+ if (listeners.isEmpty()) {
+ coordinator.stopObserving()
+ }
+ }
+
+ override fun dump(pw: PrintWriter, args: Array<out String>) {
+ pw.println("Scheduled event: ${scheduledEvent.value}")
+ pw.println("Currently displayed event: $currentlyDisplayedEvent")
+ pw.println("Has persistent privacy dot: $hasPersistentDot")
+ pw.println("Animation state: ${animationState.value}")
+ pw.println("Listeners:")
+ if (listeners.isEmpty()) {
+ pw.println("(none)")
+ } else {
+ listeners.forEach { pw.println(" $it") }
+ }
+ }
+}
+
+private const val DEBUG = false
+private const val TAG = "SystemStatusAnimationSchedulerImpl"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLegacyImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLegacyImpl.kt
new file mode 100644
index 000000000000..5fa83ef5d454
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLegacyImpl.kt
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2021 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.events
+
+import android.os.Process
+import android.provider.DeviceConfig
+import android.util.Log
+import androidx.core.animation.Animator
+import androidx.core.animation.AnimatorListenerAdapter
+import androidx.core.animation.AnimatorSet
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.statusbar.window.StatusBarWindowController
+import com.android.systemui.util.Assert
+import com.android.systemui.util.concurrency.DelayableExecutor
+import com.android.systemui.util.time.SystemClock
+import java.io.PrintWriter
+import javax.inject.Inject
+
+/**
+ * Dead-simple scheduler for system status events. Obeys the following principles (all values TBD):
+ * ```
+ * - Avoiding log spam by only allowing 12 events per minute (1event/5s)
+ * - Waits 100ms to schedule any event for debouncing/prioritization
+ * - Simple prioritization: Privacy > Battery > connectivity (encoded in [StatusEvent])
+ * - Only schedules a single event, and throws away lowest priority events
+ * ```
+ *
+ * There are 4 basic stages of animation at play here:
+ * ```
+ * 1. System chrome animation OUT
+ * 2. Chip animation IN
+ * 3. Chip animation OUT; potentially into a dot
+ * 4. System chrome animation IN
+ * ```
+ *
+ * Thus we can keep all animations synchronized with two separate ValueAnimators, one for system
+ * chrome and the other for the chip. These can animate from 0,1 and listeners can parameterize
+ * their respective views based on the progress of the animator. Interpolation differences TBD
+ */
+open class SystemStatusAnimationSchedulerLegacyImpl
+@Inject
+constructor(
+ private val coordinator: SystemEventCoordinator,
+ private val chipAnimationController: SystemEventChipAnimationController,
+ private val statusBarWindowController: StatusBarWindowController,
+ private val dumpManager: DumpManager,
+ private val systemClock: SystemClock,
+ @Main private val executor: DelayableExecutor
+) : SystemStatusAnimationScheduler {
+
+ companion object {
+ private const val PROPERTY_ENABLE_IMMERSIVE_INDICATOR = "enable_immersive_indicator"
+ }
+
+ fun isImmersiveIndicatorEnabled(): Boolean {
+ return DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_PRIVACY,
+ PROPERTY_ENABLE_IMMERSIVE_INDICATOR,
+ true
+ )
+ }
+
+ @SystemAnimationState private var animationState: Int = IDLE
+
+ /** True if the persistent privacy dot should be active */
+ var hasPersistentDot = false
+ protected set
+
+ private var scheduledEvent: StatusEvent? = null
+
+ val listeners = mutableSetOf<SystemStatusAnimationCallback>()
+
+ init {
+ coordinator.attachScheduler(this)
+ dumpManager.registerDumpable(TAG, this)
+ }
+
+ @SystemAnimationState override fun getAnimationState() = animationState
+
+ override fun onStatusEvent(event: StatusEvent) {
+ // Ignore any updates until the system is up and running
+ if (isTooEarly() || !isImmersiveIndicatorEnabled()) {
+ return
+ }
+
+ // Don't deal with threading for now (no need let's be honest)
+ Assert.isMainThread()
+ if (
+ (event.priority > (scheduledEvent?.priority ?: -1)) &&
+ animationState != ANIMATING_OUT &&
+ animationState != SHOWING_PERSISTENT_DOT
+ ) {
+ // events can only be scheduled if a higher priority or no other event is in progress
+ if (DEBUG) {
+ Log.d(TAG, "scheduling event $event")
+ }
+
+ scheduleEvent(event)
+ } else if (scheduledEvent?.shouldUpdateFromEvent(event) == true) {
+ if (DEBUG) {
+ Log.d(TAG, "updating current event from: $event. animationState=$animationState")
+ }
+ scheduledEvent?.updateFromEvent(event)
+ if (event.forceVisible) {
+ hasPersistentDot = true
+ // If we missed the chance to show the persistent dot, do it now
+ if (animationState == IDLE) {
+ notifyTransitionToPersistentDot()
+ }
+ }
+ } else {
+ if (DEBUG) {
+ Log.d(TAG, "ignoring event $event")
+ }
+ }
+ }
+
+ override fun removePersistentDot() {
+ if (!hasPersistentDot || !isImmersiveIndicatorEnabled()) {
+ return
+ }
+
+ hasPersistentDot = false
+ notifyHidePersistentDot()
+ return
+ }
+
+ fun isTooEarly(): Boolean {
+ return systemClock.uptimeMillis() - Process.getStartUptimeMillis() < MIN_UPTIME
+ }
+
+ /** Clear the scheduled event (if any) and schedule a new one */
+ private fun scheduleEvent(event: StatusEvent) {
+ scheduledEvent = event
+
+ if (event.forceVisible) {
+ hasPersistentDot = true
+ }
+
+ // If animations are turned off, we'll transition directly to the dot
+ if (!event.showAnimation && event.forceVisible) {
+ notifyTransitionToPersistentDot()
+ scheduledEvent = null
+ return
+ }
+
+ chipAnimationController.prepareChipAnimation(scheduledEvent!!.viewCreator)
+ animationState = ANIMATION_QUEUED
+ executor.executeDelayed({ runChipAnimation() }, DEBOUNCE_DELAY)
+ }
+
+ /**
+ * 1. Define a total budget for the chip animation (1500ms)
+ * 2. Send out callbacks to listeners so that they can generate animations locally
+ * 3. Update the scheduler state so that clients know where we are
+ * 4. Maybe: provide scaffolding such as: dot location, margins, etc
+ * 5. Maybe: define a maximum animation length and enforce it. Probably only doable if we
+ * collect all of the animators and run them together.
+ */
+ private fun runChipAnimation() {
+ statusBarWindowController.setForceStatusBarVisible(true)
+ animationState = ANIMATING_IN
+
+ val animSet = collectStartAnimations()
+ if (animSet.totalDuration > 500) {
+ throw IllegalStateException(
+ "System animation total length exceeds budget. " +
+ "Expected: 500, actual: ${animSet.totalDuration}"
+ )
+ }
+ animSet.addListener(
+ object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator) {
+ animationState = RUNNING_CHIP_ANIM
+ }
+ }
+ )
+ animSet.start()
+
+ executor.executeDelayed(
+ {
+ val animSet2 = collectFinishAnimations()
+ animationState = ANIMATING_OUT
+ animSet2.addListener(
+ object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator) {
+ animationState =
+ if (hasPersistentDot) {
+ SHOWING_PERSISTENT_DOT
+ } else {
+ IDLE
+ }
+
+ statusBarWindowController.setForceStatusBarVisible(false)
+ }
+ }
+ )
+ animSet2.start()
+ scheduledEvent = null
+ },
+ DISPLAY_LENGTH
+ )
+ }
+
+ private fun collectStartAnimations(): AnimatorSet {
+ val animators = mutableListOf<Animator>()
+ listeners.forEach { listener ->
+ listener.onSystemEventAnimationBegin()?.let { anim -> animators.add(anim) }
+ }
+ animators.add(chipAnimationController.onSystemEventAnimationBegin())
+ val animSet = AnimatorSet().also { it.playTogether(animators) }
+
+ return animSet
+ }
+
+ private fun collectFinishAnimations(): AnimatorSet {
+ val animators = mutableListOf<Animator>()
+ listeners.forEach { listener ->
+ listener.onSystemEventAnimationFinish(hasPersistentDot)?.let { anim ->
+ animators.add(anim)
+ }
+ }
+ animators.add(chipAnimationController.onSystemEventAnimationFinish(hasPersistentDot))
+ if (hasPersistentDot) {
+ val dotAnim = notifyTransitionToPersistentDot()
+ if (dotAnim != null) {
+ animators.add(dotAnim)
+ }
+ }
+ val animSet = AnimatorSet().also { it.playTogether(animators) }
+
+ return animSet
+ }
+
+ private fun notifyTransitionToPersistentDot(): Animator? {
+ val anims: List<Animator> =
+ listeners.mapNotNull {
+ it.onSystemStatusAnimationTransitionToPersistentDot(
+ scheduledEvent?.contentDescription
+ )
+ }
+ if (anims.isNotEmpty()) {
+ val aSet = AnimatorSet()
+ aSet.playTogether(anims)
+ return aSet
+ }
+
+ return null
+ }
+
+ private fun notifyHidePersistentDot(): Animator? {
+ val anims: List<Animator> = listeners.mapNotNull { it.onHidePersistentDot() }
+
+ if (animationState == SHOWING_PERSISTENT_DOT) {
+ animationState = IDLE
+ }
+
+ if (anims.isNotEmpty()) {
+ val aSet = AnimatorSet()
+ aSet.playTogether(anims)
+ return aSet
+ }
+
+ return null
+ }
+
+ override fun addCallback(listener: SystemStatusAnimationCallback) {
+ Assert.isMainThread()
+
+ if (listeners.isEmpty()) {
+ coordinator.startObserving()
+ }
+ listeners.add(listener)
+ }
+
+ override fun removeCallback(listener: SystemStatusAnimationCallback) {
+ Assert.isMainThread()
+
+ listeners.remove(listener)
+ if (listeners.isEmpty()) {
+ coordinator.stopObserving()
+ }
+ }
+
+ override fun dump(pw: PrintWriter, args: Array<out String>) {
+ pw.println("Scheduled event: $scheduledEvent")
+ pw.println("Has persistent privacy dot: $hasPersistentDot")
+ pw.println("Animation state: $animationState")
+ pw.println("Listeners:")
+ if (listeners.isEmpty()) {
+ pw.println("(none)")
+ } else {
+ listeners.forEach { pw.println(" $it") }
+ }
+ }
+}
+
+private const val DEBUG = false
+private const val TAG = "SystemStatusAnimationSchedulerLegacyImpl"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
index f395bea16131..82c5ee64b046 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
@@ -334,9 +334,9 @@ constructor(
}
val ssView = plugin.getView(parent)
+ configPlugin?.let { ssView.registerConfigProvider(it) }
ssView.setUiSurface(BcSmartspaceDataPlugin.UI_SURFACE_LOCK_SCREEN_AOD)
ssView.registerDataProvider(plugin)
- configPlugin?.let { ssView.registerConfigProvider(it) }
ssView.setIntentStarter(object : BcSmartspaceDataPlugin.IntentStarter {
override fun startIntent(view: View, intent: Intent, showOnLockscreen: Boolean) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
index 0a5e9867a17f..11582d7e3cc8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
@@ -29,7 +29,6 @@ import android.app.AppGlobals;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
-import android.app.SynchronousUserSwitchObserver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -52,7 +51,9 @@ import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.systemui.CoreStartable;
import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dagger.qualifiers.UiBackground;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.NotificationChannels;
@@ -73,6 +74,8 @@ public class InstantAppNotifier
private final Context mContext;
private final Handler mHandler = new Handler();
+ private final UserTracker mUserTracker;
+ private final Executor mMainExecutor;
private final Executor mUiBgExecutor;
private final ArraySet<Pair<String, Integer>> mCurrentNotifs = new ArraySet<>();
private final CommandQueue mCommandQueue;
@@ -82,10 +85,14 @@ public class InstantAppNotifier
public InstantAppNotifier(
Context context,
CommandQueue commandQueue,
+ UserTracker userTracker,
+ @Main Executor mainExecutor,
@UiBackground Executor uiBgExecutor,
KeyguardStateController keyguardStateController) {
mContext = context;
mCommandQueue = commandQueue;
+ mUserTracker = userTracker;
+ mMainExecutor = mainExecutor;
mUiBgExecutor = uiBgExecutor;
mKeyguardStateController = keyguardStateController;
}
@@ -93,11 +100,7 @@ public class InstantAppNotifier
@Override
public void start() {
// listen for user / profile change.
- try {
- ActivityManager.getService().registerUserSwitchObserver(mUserSwitchListener, TAG);
- } catch (RemoteException e) {
- // Ignore
- }
+ mUserTracker.addCallback(mUserSwitchListener, mMainExecutor);
mCommandQueue.addCallback(this);
mKeyguardStateController.addCallback(this);
@@ -129,13 +132,10 @@ public class InstantAppNotifier
updateForegroundInstantApps();
}
- private final SynchronousUserSwitchObserver mUserSwitchListener =
- new SynchronousUserSwitchObserver() {
- @Override
- public void onUserSwitching(int newUserId) throws RemoteException {}
-
+ private final UserTracker.Callback mUserSwitchListener =
+ new UserTracker.Callback() {
@Override
- public void onUserSwitchComplete(int newUserId) throws RemoteException {
+ public void onUserChanged(int newUser, Context userContext) {
mHandler.post(
() -> {
updateForegroundInstantApps();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
index fc89be2c6670..00d8c421c721 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
@@ -28,10 +28,6 @@ class NotifPipelineFlags @Inject constructor(
val featureFlags: FeatureFlags,
val sysPropFlags: FlagResolver,
) {
- init {
- featureFlags.addListener(Flags.DISABLE_FSI) { event -> event.requestNoRestart() }
- }
-
fun isDevLoggingEnabled(): Boolean =
featureFlags.isEnabled(Flags.NOTIFICATION_PIPELINE_DEVELOPER_LOGGING)
@@ -40,8 +36,6 @@ class NotifPipelineFlags @Inject constructor(
fun fsiOnDNDUpdate(): Boolean = featureFlags.isEnabled(Flags.FSI_ON_DND_UPDATE)
- fun disableFsi(): Boolean = featureFlags.isEnabled(Flags.DISABLE_FSI)
-
fun forceDemoteFsi(): Boolean =
sysPropFlags.isEnabled(NotificationFlags.FSI_FORCE_DEMOTE)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
index 7e53d5431353..8874f59d6c17 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
@@ -18,6 +18,7 @@ package com.android.systemui.statusbar.notification
import android.animation.ObjectAnimator
import android.util.FloatProperty
+import androidx.annotation.VisibleForTesting
import com.android.systemui.Dumpable
import com.android.systemui.animation.Interpolators
import com.android.systemui.dagger.SysUISingleton
@@ -302,29 +303,29 @@ class NotificationWakeUpCoordinator @Inject constructor(
// the doze amount to 0f (not dozing) so that the notifications are no longer hidden.
// See: UnlockedScreenOffAnimationController.onFinishedWakingUp()
setDozeAmount(0f, 0f, source = "Override: Shade->Shade (lock cancelled by unlock)")
+ this.state = newState
+ return
}
if (overrideDozeAmountIfAnimatingScreenOff(mLinearDozeAmount)) {
+ this.state = newState
return
}
if (overrideDozeAmountIfBypass()) {
+ this.state = newState
return
}
maybeClearDozeAmountOverrideHidingNotifs()
- if (bypassController.bypassEnabled &&
- newState == StatusBarState.KEYGUARD && state == StatusBarState.SHADE_LOCKED &&
- (!statusBarStateController.isDozing || shouldAnimateVisibility())) {
- // We're leaving shade locked. Let's animate the notifications away
- setNotificationsVisible(visible = true, increaseSpeed = false, animate = false)
- setNotificationsVisible(visible = false, increaseSpeed = false, animate = true)
- }
-
this.state = newState
}
+ @VisibleForTesting
+ val statusBarState: Int
+ get() = state
+
override fun onPanelExpansionChanged(event: ShadeExpansionChangeEvent) {
val collapsedEnough = event.fraction <= 0.9f
if (collapsedEnough != this.collapsedEnoughToHide) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt
index 44645315ca80..88d9ffcdcf3e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt
@@ -13,7 +13,7 @@
package com.android.systemui.statusbar.notification
-import com.android.systemui.log.dagger.NotificationLog
+import com.android.systemui.log.dagger.NotificationLockscreenLog
import com.android.systemui.plugins.log.LogBuffer
import com.android.systemui.plugins.log.LogLevel.DEBUG
import com.android.systemui.statusbar.StatusBarState
@@ -21,7 +21,12 @@ import javax.inject.Inject
class NotificationWakeUpCoordinatorLogger
@Inject
-constructor(@NotificationLog private val buffer: LogBuffer) {
+constructor(@NotificationLockscreenLog private val buffer: LogBuffer) {
+ private var lastSetDozeAmountLogWasFractional = false
+ private var lastSetDozeAmountLogState = -1
+ private var lastSetDozeAmountLogSource = "undefined"
+ private var lastOnDozeAmountChangedLogWasFractional = false
+
fun logSetDozeAmount(
linear: Float,
eased: Float,
@@ -29,6 +34,20 @@ constructor(@NotificationLog private val buffer: LogBuffer) {
state: Int,
changed: Boolean,
) {
+ // Avoid logging on every frame of the animation if important values are not changing
+ val isFractional = linear != 1f && linear != 0f
+ if (
+ lastSetDozeAmountLogWasFractional &&
+ isFractional &&
+ lastSetDozeAmountLogState == state &&
+ lastSetDozeAmountLogSource == source
+ ) {
+ return
+ }
+ lastSetDozeAmountLogWasFractional = isFractional
+ lastSetDozeAmountLogState = state
+ lastSetDozeAmountLogSource = source
+
buffer.log(
TAG,
DEBUG,
@@ -66,6 +85,10 @@ constructor(@NotificationLog private val buffer: LogBuffer) {
}
fun logOnDozeAmountChanged(linear: Float, eased: Float) {
+ // Avoid logging on every frame of the animation when values are fractional
+ val isFractional = linear != 1f && linear != 0f
+ if (lastOnDozeAmountChangedLogWasFractional && isFractional) return
+ lastOnDozeAmountChangedLogWasFractional = isFractional
buffer.log(
TAG,
DEBUG,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt
index a35617c88caf..6deef2e11828 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt
@@ -315,6 +315,7 @@ interface Roundable {
/**
* State object for a `Roundable` class.
+ *
* @param targetView Will handle the [AnimatableProperty]
* @param roundable Target of the radius animation
* @param maxRadius Max corner radius in pixels
@@ -436,7 +437,6 @@ interface SourceType {
* This is the most convenient way to define a new [SourceType].
*
* For example:
- *
* ```kotlin
* private val SECTION = SourceType.from("Section")
* ```
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index 4e9e88d57201..bc531da0ec40 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -619,14 +619,6 @@ public final class NotificationEntry extends ListEntry {
return row.isMediaRow();
}
- /**
- * We are a top level child if our parent is the list of notifications duh
- * @return {@code true} if we're a top level notification
- */
- public boolean isTopLevelChild() {
- return row != null && row.isTopLevelChild();
- }
-
public void resetUserExpansion() {
if (row != null) row.resetUserExpansion();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DismissibilityCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DismissibilityCoordinator.kt
index 1fccf82b21af..0a9dddc1c75e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DismissibilityCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DismissibilityCoordinator.kt
@@ -46,6 +46,7 @@ constructor(
/**
* Visits every entry and its children to mark the dismissible entries.
+ *
* @param markedKeys set to store the marked entry keys
* @param entries to visit
* @param isLocked the locked state of the device
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 67a8a63ad7da..6c84fefe2d38 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
@@ -34,6 +34,7 @@ import com.android.systemui.statusbar.notification.dagger.AlertingHeader;
import com.android.systemui.statusbar.notification.dagger.SilentHeader;
import com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -43,8 +44,8 @@ import javax.inject.Inject;
* Filters out NotificationEntries based on its Ranking and dozing state.
* Assigns alerting / silent section based on the importance of the notification entry.
* We check the NotificationEntry's Ranking for:
- * - whether the notification's app is suspended or hiding its notifications
- * - whether DND settings are hiding notifications from ambient display or the notification list
+ * - whether the notification's app is suspended or hiding its notifications
+ * - whether DND settings are hiding notifications from ambient display or the notification list
*/
@CoordinatorScope
public class RankingCoordinator implements Coordinator {
@@ -78,6 +79,8 @@ public class RankingCoordinator implements Coordinator {
public void attach(NotifPipeline pipeline) {
mStatusBarStateController.addCallback(mStatusBarStateCallback);
mSectionStyleProvider.setMinimizedSections(Collections.singleton(mMinimizedNotifSectioner));
+ mSectionStyleProvider.setSilentSections(
+ Arrays.asList(mSilentNotifSectioner, mMinimizedNotifSectioner));
pipeline.addPreGroupFilter(mSuspendedFilter);
pipeline.addPreGroupFilter(mDndVisualEffectsFilter);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SectionStyleProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SectionStyleProvider.kt
index 7b9483022fd8..5a3edf4ac8fd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SectionStyleProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SectionStyleProvider.kt
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.notification.collection.provider
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.notification.collection.ListEntry
import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner
import javax.inject.Inject
@@ -27,6 +28,7 @@ import javax.inject.Inject
*/
@SysUISingleton
class SectionStyleProvider @Inject constructor() {
+ private lateinit var silentSections: Set<NotifSectioner>
private lateinit var lowPrioritySections: Set<NotifSectioner>
/**
@@ -38,9 +40,42 @@ class SectionStyleProvider @Inject constructor() {
}
/**
- * Determine if the given section is minimized
+ * Determine if the given section is minimized.
*/
fun isMinimizedSection(section: NotifSection): Boolean {
return lowPrioritySections.contains(section.sectioner)
}
+
+ /**
+ * Determine if the given entry is minimized.
+ */
+ @JvmOverloads
+ fun isMinimized(entry: ListEntry, ifNotInSection: Boolean = true): Boolean {
+ val section = entry.section ?: return ifNotInSection
+ return isMinimizedSection(section)
+ }
+
+ /**
+ * Feed the provider the information it needs about which sections are silent, so that it can
+ * calculate which entries are in a "silent" section.
+ */
+ fun setSilentSections(sections: Collection<NotifSectioner>) {
+ silentSections = sections.toSet()
+ }
+
+ /**
+ * Determine if the given section is silent.
+ */
+ fun isSilentSection(section: NotifSection): Boolean {
+ return silentSections.contains(section.sectioner)
+ }
+
+ /**
+ * Determine if the given entry is silent.
+ */
+ @JvmOverloads
+ fun isSilent(entry: ListEntry, ifNotInSection: Boolean = true): Boolean {
+ val section = entry.section ?: return ifNotInSection
+ return isSilentSection(section)
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeRepo.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeRepo.kt
deleted file mode 100644
index b48322822c86..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeRepo.kt
+++ /dev/null
@@ -1,102 +0,0 @@
-package com.android.systemui.statusbar.notification.fsi
-
-import android.app.PendingIntent
-import android.content.Context
-import android.content.pm.PackageManager
-import android.graphics.drawable.Drawable
-import android.os.RemoteException
-import android.service.dreams.IDreamManager
-import com.android.systemui.CoreStartable
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.data.repository.KeyguardRepository
-import com.android.systemui.statusbar.notification.collection.NotificationEntry
-import com.android.systemui.statusbar.notification.collection.provider.LaunchFullScreenIntentProvider
-import com.android.systemui.statusbar.notification.fsi.FsiDebug.Companion.log
-import com.android.systemui.statusbar.phone.CentralSurfaces
-import java.util.concurrent.Executor
-import javax.inject.Inject
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
-
-/**
- * Class that bridges the gap between clean app architecture and existing code. Provides new
- * implementation of StatusBarNotificationActivityStarter launchFullscreenIntent that pipes
- * one-directional data => FsiChromeViewModel => FsiChromeView.
- */
-@SysUISingleton
-class FsiChromeRepo
-@Inject
-constructor(
- private val context: Context,
- private val pm: PackageManager,
- private val keyguardRepo: KeyguardRepository,
- private val launchFullScreenIntentProvider: LaunchFullScreenIntentProvider,
- private val featureFlags: FeatureFlags,
- private val uiBgExecutor: Executor,
- private val dreamManager: IDreamManager,
- private val centralSurfaces: CentralSurfaces
-) : CoreStartable {
-
- companion object {
- private const val classTag = "FsiChromeRepo"
- }
-
- data class FSIInfo(
- val appName: String,
- val appIcon: Drawable,
- val fullscreenIntent: PendingIntent
- )
-
- private val _infoFlow = MutableStateFlow<FSIInfo?>(null)
- val infoFlow: StateFlow<FSIInfo?> = _infoFlow
-
- override fun start() {
- log("$classTag start listening for FSI notifications")
-
- // Listen for FSI launch events for the lifetime of SystemUI.
- launchFullScreenIntentProvider.registerListener { entry -> launchFullscreenIntent(entry) }
- }
-
- fun dismiss() {
- _infoFlow.value = null
- }
-
- fun onFullscreen() {
- // TODO(b/243421660) implement transition from container to fullscreen
- }
-
- fun stopScreenSaver() {
- uiBgExecutor.execute {
- try {
- dreamManager.awaken()
- } catch (e: RemoteException) {
- e.printStackTrace()
- }
- }
- }
-
- fun launchFullscreenIntent(entry: NotificationEntry) {
- if (!featureFlags.isEnabled(Flags.FSI_CHROME)) {
- return
- }
- if (!keyguardRepo.isKeyguardShowing()) {
- return
- }
- stopScreenSaver()
-
- var appName = pm.getApplicationLabel(context.applicationInfo) as String
- val appIcon = pm.getApplicationIcon(context.packageName)
- val fullscreenIntent = entry.sbn.notification.fullScreenIntent
-
- log("FsiChromeRepo launchFullscreenIntent appName=$appName appIcon $appIcon")
- _infoFlow.value = FSIInfo(appName, appIcon, fullscreenIntent)
-
- // If screen is off or we're showing AOD, show lockscreen.
- centralSurfaces.wakeUpForFullScreenIntent()
-
- // Don't show HUN since we're already showing FSI.
- entry.notifyFullScreenIntentLaunched()
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeView.kt
deleted file mode 100644
index 6e5fcf40440c..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeView.kt
+++ /dev/null
@@ -1,83 +0,0 @@
-package com.android.systemui.statusbar.notification.fsi
-
-import android.content.Context
-import android.graphics.Color
-import android.graphics.Color.DKGRAY
-import android.graphics.Outline
-import android.util.AttributeSet
-import android.view.View
-import android.view.ViewOutlineProvider
-import android.widget.Button
-import android.widget.ImageView
-import android.widget.LinearLayout
-import android.widget.TextView
-import com.android.systemui.R
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.statusbar.notification.fsi.FsiDebug.Companion.log
-
-@SysUISingleton
-class FsiChromeView
-@JvmOverloads
-constructor(
- context: Context?,
- attrs: AttributeSet? = null,
- defStyleAttr: Int = 0,
- defStyleRes: Int = 0
-) : LinearLayout(context, attrs, defStyleAttr, defStyleRes) {
-
- companion object {
- private const val classTag = "FsiChromeView"
- }
-
- lateinit var chromeContainer: LinearLayout
- lateinit var appIconImageView: ImageView
- lateinit var appNameTextView: TextView
- lateinit var dismissButton: Button
- lateinit var fullscreenButton: Button
-
- private val cornerRadius: Float =
- resources.getDimensionPixelSize(R.dimen.notification_corner_radius).toFloat()
- private val vertPadding: Int =
- resources.getDimensionPixelSize(R.dimen.fsi_chrome_vertical_padding)
- private val sidePadding: Int =
- resources.getDimensionPixelSize(R.dimen.notification_side_paddings)
-
- init {
- log("$classTag init")
- }
-
- override fun onFinishInflate() {
- log("$classTag onFinishInflate")
- super.onFinishInflate()
-
- setBackgroundColor(Color.TRANSPARENT)
- setPadding(
- sidePadding,
- vertPadding,
- sidePadding,
- vertPadding
- ) // Make smaller than fullscreen.
-
- chromeContainer = findViewById(R.id.fsi_chrome)
- chromeContainer.setBackgroundColor(DKGRAY)
-
- appIconImageView = findViewById(R.id.fsi_app_icon)
- appNameTextView = findViewById(R.id.fsi_app_name)
- dismissButton = findViewById(R.id.fsi_dismiss_button)
- fullscreenButton = findViewById(R.id.fsi_fullscreen_button)
-
- outlineProvider =
- object : ViewOutlineProvider() {
- override fun getOutline(view: View, outline: Outline) {
- outline.setRoundRect(
- /* left */ sidePadding,
- /* top */ vertPadding,
- /* right */ view.width - sidePadding,
- /* bottom */ view.height - vertPadding,
- cornerRadius
- )
- }
- }
- clipToOutline = true
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewBinder.kt
deleted file mode 100644
index 1a3927ba9b06..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewBinder.kt
+++ /dev/null
@@ -1,99 +0,0 @@
-package com.android.systemui.statusbar.notification.fsi
-
-import android.content.Context
-import android.view.LayoutInflater
-import android.view.WindowManager
-import com.android.systemui.CoreStartable
-import com.android.systemui.R
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.statusbar.notification.fsi.FsiDebug.Companion.log
-import com.android.systemui.statusbar.phone.CentralSurfaces
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.launch
-import java.util.concurrent.Executor
-import javax.inject.Inject
-
-@SysUISingleton
-class FsiChromeViewBinder
-@Inject
-constructor(
- val context: Context,
- val windowManager: WindowManager,
- val viewModelFactory: FsiChromeViewModelFactory,
- val layoutInflater: LayoutInflater,
- val centralSurfaces: CentralSurfaces,
- @Main val mainExecutor: Executor,
- @Application val scope: CoroutineScope,
-) : CoreStartable {
-
- companion object {
- private const val classTag = "FsiChromeViewBinder"
- }
-
- private val fsiChromeView =
- layoutInflater.inflate(R.layout.fsi_chrome_view, null /* root */, false /* attachToRoot */)
- as FsiChromeView
-
- var addedToWindowManager = false
- var cornerRadius: Int = context.resources.getDimensionPixelSize(
- R.dimen.notification_corner_radius)
-
- override fun start() {
- val methodTag = "start"
- log("$classTag $methodTag ")
-
- scope.launch {
- log("$classTag $methodTag launch ")
- viewModelFactory.viewModelFlow.collect { vm -> updateForViewModel(vm) }
- }
- }
-
- private fun updateForViewModel(vm: FsiChromeViewModel?) {
- val methodTag = "updateForViewModel"
-
- if (vm == null) {
- log("$classTag $methodTag viewModel is null, removing from window manager")
-
- if (addedToWindowManager) {
- windowManager.removeView(fsiChromeView)
- addedToWindowManager = false
- }
- return
- }
-
- bindViewModel(vm, windowManager)
-
- if (addedToWindowManager) {
- log("$classTag $methodTag already addedToWindowManager")
- } else {
- windowManager.addView(fsiChromeView, FsiTaskViewConfig.getWmLayoutParams("PackageName"))
- addedToWindowManager = true
- }
- }
-
- private fun bindViewModel(
- vm: FsiChromeViewModel,
- windowManager: WindowManager,
- ) {
- log("$classTag bindViewModel")
-
- fsiChromeView.appIconImageView.setImageDrawable(vm.appIcon)
- fsiChromeView.appNameTextView.text = vm.appName
-
- fsiChromeView.dismissButton.setOnClickListener { vm.onDismiss() }
- fsiChromeView.fullscreenButton.setOnClickListener { vm.onFullscreen() }
-
- vm.taskView.cornerRadius = cornerRadius.toFloat()
- vm.taskView.startActivity(
- vm.fsi,
- FsiTaskViewConfig.getFillInIntent(),
- FsiTaskViewConfig.getActivityOptions(context, windowManager),
- FsiTaskViewConfig.getLaunchBounds(windowManager)
- )
-
- log("$classTag bindViewModel started taskview activity")
- fsiChromeView.addView(vm.taskView)
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewModelFactory.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewModelFactory.kt
deleted file mode 100644
index 1ca698b6bd58..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewModelFactory.kt
+++ /dev/null
@@ -1,87 +0,0 @@
-package com.android.systemui.statusbar.notification.fsi
-
-import android.annotation.UiContext
-import android.app.PendingIntent
-import android.content.Context
-import android.graphics.drawable.Drawable
-import com.android.systemui.CoreStartable
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.statusbar.notification.fsi.FsiDebug.Companion.log
-import com.android.wm.shell.TaskView
-import com.android.wm.shell.TaskViewFactory
-import java.util.Optional
-import java.util.concurrent.Executor
-import javax.inject.Inject
-import kotlin.coroutines.resume
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.mapLatest
-import kotlinx.coroutines.suspendCancellableCoroutine
-
-/**
- * Handle view-related data for fullscreen intent container on lockscreen. Wraps FsiChromeRepo,
- * transforms events/state into view-relevant representation for FsiChromeView. Alive for lifetime
- * of SystemUI.
- */
-@SysUISingleton
-class FsiChromeViewModelFactory
-@Inject
-constructor(
- val repo: FsiChromeRepo,
- val taskViewFactory: Optional<TaskViewFactory>,
- @UiContext val context: Context,
- @Main val mainExecutor: Executor,
-) : CoreStartable {
-
- companion object {
- private const val classTag = "FsiChromeViewModelFactory"
- }
-
- val viewModelFlow: Flow<FsiChromeViewModel?> =
- repo.infoFlow.mapLatest { fsiInfo ->
- fsiInfo?.let {
- log("$classTag viewModelFlow got new fsiInfo")
-
- // mapLatest emits null when FSIInfo is null
- FsiChromeViewModel(
- fsiInfo.appName,
- fsiInfo.appIcon,
- createTaskView(),
- fsiInfo.fullscreenIntent,
- repo
- )
- }
- }
-
- override fun start() {
- log("$classTag start")
- }
-
- private suspend fun createTaskView(): TaskView = suspendCancellableCoroutine { k ->
- log("$classTag createTaskView")
-
- taskViewFactory.get().create(context, mainExecutor) { taskView -> k.resume(taskView) }
- }
-}
-
-// Alive for lifetime of FSI.
-data class FsiChromeViewModel(
- val appName: String,
- val appIcon: Drawable,
- val taskView: TaskView,
- val fsi: PendingIntent,
- val repo: FsiChromeRepo
-) {
- companion object {
- private const val classTag = "FsiChromeViewModel"
- }
-
- fun onDismiss() {
- log("$classTag onDismiss")
- repo.dismiss()
- }
- fun onFullscreen() {
- log("$classTag onFullscreen")
- repo.onFullscreen()
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiDebug.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiDebug.kt
deleted file mode 100644
index d9e3f8fbf146..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiDebug.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.android.systemui.statusbar.notification.fsi
-
-class FsiDebug {
-
- companion object {
- private const val debugTag = "FsiDebug"
- private const val debug = true
-
- fun log(s: Any) {
- if (!debug) {
- return
- }
- android.util.Log.d(debugTag, "$s")
- }
- }
-} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiTaskViewConfig.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiTaskViewConfig.kt
deleted file mode 100644
index 034ab56d5a65..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiTaskViewConfig.kt
+++ /dev/null
@@ -1,75 +0,0 @@
-package com.android.systemui.statusbar.notification.fsi
-
-import android.app.ActivityOptions
-import android.content.Context
-import android.content.Intent
-import android.graphics.PixelFormat
-import android.graphics.Rect
-import android.os.Binder
-import android.view.ViewGroup
-import android.view.WindowManager
-
-/**
- * Config for adding the FsiChromeView window to WindowManager and starting the FSI activity.
- */
-class FsiTaskViewConfig {
-
- companion object {
-
- private const val classTag = "FsiTaskViewConfig"
-
- fun getWmLayoutParams(packageName: String): WindowManager.LayoutParams {
- val params: WindowManager.LayoutParams?
- params =
- WindowManager.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.MATCH_PARENT,
- WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
- WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE or
- WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED or
- WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER,
- PixelFormat.TRANSLUCENT
- )
- params.setTrustedOverlay()
- params.fitInsetsTypes = 0
- params.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
- params.token = Binder()
- params.packageName = packageName
- params.layoutInDisplayCutoutMode =
- WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
- params.privateFlags =
- params.privateFlags or WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS
- return params
- }
-
- fun getFillInIntent(): Intent {
- val fillInIntent = Intent()
- fillInIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT)
- fillInIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
- // FLAG_ACTIVITY_NEW_TASK is auto-applied because
- // we're starting the FSI activity from a non-Activity context
- return fillInIntent
- }
-
- fun getLaunchBounds(windowManager: WindowManager): Rect {
- // TODO(b/243421660) check this works for non-resizeable activity
- return Rect()
- }
-
- fun getActivityOptions(context: Context, windowManager: WindowManager): ActivityOptions {
- // Custom options so there is no activity transition animation
- val options =
- ActivityOptions.makeCustomAnimation(context, 0 /* enterResId */, 0 /* exitResId */)
-
- options.taskAlwaysOnTop = true
-
- options.pendingIntentLaunchFlags =
- Intent.FLAG_ACTIVITY_NEW_DOCUMENT or
- Intent.FLAG_ACTIVITY_MULTIPLE_TASK or
- Intent.FLAG_ACTIVITY_NEW_TASK
-
- options.launchBounds = getLaunchBounds(windowManager)
- return options
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java
index ae19febadfaa..9001470ad406 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java
@@ -35,10 +35,6 @@ public interface NotificationInterruptStateProvider {
*/
NO_FSI_SHOW_STICKY_HUN(false),
/**
- * Full screen intents are disabled.
- */
- NO_FSI_DISABLED(false),
- /**
* No full screen intent included, so there is nothing to show.
*/
NO_FULL_SCREEN_INTENT(false),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java
index 0163dbef2760..9f45b9d67189 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java
@@ -244,10 +244,6 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter
@Override
public FullScreenIntentDecision getFullScreenIntentDecision(NotificationEntry entry) {
- if (mFlags.disableFsi()) {
- return FullScreenIntentDecision.NO_FSI_DISABLED;
- }
-
if (entry.getSbn().getNotification().fullScreenIntent == null) {
if (entry.isStickyAndNotDemoted()) {
return FullScreenIntentDecision.NO_FSI_SHOW_STICKY_HUN;
@@ -343,9 +339,6 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter
case NO_FSI_SHOW_STICKY_HUN:
mLogger.logNoFullscreen(entry, "Permission denied, show sticky HUN");
return;
- case NO_FSI_DISABLED:
- mLogger.logNoFullscreen(entry, "Disabled");
- return;
case NO_FULL_SCREEN_INTENT:
return;
case NO_FSI_SUPPRESSED_BY_DND:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt
index f0b221dd4726..0de3246e01fa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt
@@ -344,7 +344,7 @@ class ChannelEditorDialogController @Inject constructor(
or WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED)
}
-class ChannelEditorDialog(context: Context) : Dialog(context) {
+class ChannelEditorDialog(context: Context, theme: Int) : Dialog(context, theme) {
fun updateDoneButtonText(hasChanges: Boolean) {
findViewById<TextView>(R.id.done_button)?.setText(
if (hasChanges)
@@ -361,7 +361,7 @@ class ChannelEditorDialog(context: Context) : Dialog(context) {
}
fun build(): ChannelEditorDialog {
- return ChannelEditorDialog(context)
+ return ChannelEditorDialog(context, R.style.Theme_SystemUI_Dialog)
}
}
}
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 7c6efe47eafc..2affa77eee04 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
@@ -110,7 +110,6 @@ import com.android.systemui.statusbar.notification.stack.AmbientState;
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.SwipeableView;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -3587,10 +3586,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
return mEntry.getSbn().getNotification().isMediaNotification();
}
- public boolean isTopLevelChild() {
- return getParent() instanceof NotificationStackScrollLayout;
- }
-
public boolean isGroupNotFullyVisible() {
return getClipTopAmount() > 0 || getTranslationY() < 0;
}
@@ -3734,7 +3729,9 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
pw.println("Roundness: " + getRoundableState().debugString());
- if (mIsSummaryWithChildren) {
+ int transientViewCount = mChildrenContainer == null
+ ? 0 : mChildrenContainer.getTransientViewCount();
+ if (mIsSummaryWithChildren || transientViewCount > 0) {
pw.println();
pw.print("ChildrenContainer");
pw.print(" visibility: " + mChildrenContainer.getVisibility());
@@ -3742,8 +3739,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
pw.print(", translationY: " + mChildrenContainer.getTranslationY());
pw.println();
List<ExpandableNotificationRow> notificationChildren = getAttachedChildren();
- pw.println("Children: " + notificationChildren.size());
- pw.print("{");
+ pw.print("Children: " + notificationChildren.size() + " {");
pw.increaseIndent();
for (ExpandableNotificationRow child : notificationChildren) {
pw.println();
@@ -3751,6 +3747,15 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
pw.decreaseIndent();
pw.println("}");
+ pw.print("Transient Views: " + transientViewCount + " {");
+ pw.increaseIndent();
+ for (int i = 0; i < transientViewCount; i++) {
+ pw.println();
+ ExpandableView child = (ExpandableView) mChildrenContainer.getTransientView(i);
+ child.dump(pw, args);
+ }
+ pw.decreaseIndent();
+ pw.println("}");
} else if (mPrivateLayout != null) {
mPrivateLayout.dumpSmartReplies(pw);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
index f1694aceac6c..2dda6fd802e8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
@@ -317,7 +317,7 @@ public class ExpandableNotificationRowController implements NotifViewController
}
mView.removeChildNotification(childView);
if (!isTransfer) {
- mListContainer.notifyGroupChildRemoved(childView, mView);
+ mListContainer.notifyGroupChildRemoved(childView, mView.getChildrenContainer());
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index d2087ba6ca1c..e09b94bb661d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -2792,7 +2792,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
}
child.setOnHeightChangedListener(null);
updateScrollStateForRemovedChild(child);
- boolean animationGenerated = generateRemoveAnimation(child);
+ boolean animationGenerated = container != null && generateRemoveAnimation(child);
if (animationGenerated) {
if (!mSwipedOutViews.contains(child) || !isFullySwipedOut(child)) {
container.addTransientView(child, 0);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index 2868116fe697..92c5b632f813 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -211,7 +211,11 @@ public class NotificationStackScrollLayoutController {
public void onViewAttachedToWindow(View v) {
mConfigurationController.addCallback(mConfigurationListener);
mZenModeController.addCallback(mZenModeControllerCallback);
- mBarState = mStatusBarStateController.getState();
+ final int newBarState = mStatusBarStateController.getState();
+ if (newBarState != mBarState) {
+ mStateListener.onStateChanged(newBarState);
+ mStateListener.onStatePostChange();
+ }
mStatusBarStateController.addCallback(
mStateListener, SysuiStatusBarStateController.RANK_STACK_SCROLLER);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
index aaf9300e7cc8..c6f56d482d43 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
@@ -251,13 +251,13 @@ class NotificationSwipeHelper extends SwipeHelper implements NotificationSwipeAc
|| (isFastNonDismissGesture && isAbleToShowMenu);
int menuSnapTarget = menuRow.getMenuSnapTarget();
boolean isNonFalseMenuRevealingGesture =
- !isFalseGesture() && isMenuRevealingGestureAwayFromMenu;
+ isMenuRevealingGestureAwayFromMenu && !isFalseGesture();
if ((isNonDismissGestureTowardsMenu || isNonFalseMenuRevealingGesture)
&& menuSnapTarget != 0) {
// Menu has not been snapped to previously and this is menu revealing gesture
snapOpen(animView, menuSnapTarget, velocity);
menuRow.onSnapOpen();
- } else if (isDismissGesture(ev) && !gestureTowardsMenu) {
+ } else if (isDismissGesture && !gestureTowardsMenu) {
dismiss(animView, velocity);
menuRow.onDismiss();
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt
index 548d1a135948..8b6d6a4f3170 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt
@@ -25,9 +25,10 @@ constructor(
/**
* This method looks for views that can be rounded (and implement [Roundable]) during a
* notification swipe.
+ *
* @return The [Roundable] targets above/below the [viewSwiped] (if available). The
- * [RoundableTargets.before] and [RoundableTargets.after] parameters can be `null` if there is
- * no above/below notification or the notification is not part of the same section.
+ * [RoundableTargets.before] and [RoundableTargets.after] parameters can be `null` if there is
+ * no above/below notification or the notification is not part of the same section.
*/
fun findRoundableTargets(
viewSwiped: ExpandableNotificationRow,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
index 576df7ac7add..f6d53b3bc9b3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
@@ -31,7 +31,7 @@ import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.qs.AutoAddTracker;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.ReduceBrightColorsController;
import com.android.systemui.qs.SettingObserver;
import com.android.systemui.qs.external.CustomTile;
@@ -75,7 +75,7 @@ public class AutoTileManager implements UserAwareController {
private final String mSafetySpec;
protected final Context mContext;
- protected final QSTileHost mHost;
+ protected final QSHost mHost;
protected final Handler mHandler;
protected final SecureSettings mSecureSettings;
protected final AutoAddTracker mAutoTracker;
@@ -92,7 +92,7 @@ public class AutoTileManager implements UserAwareController {
private final ArrayList<AutoAddSetting> mAutoAddSettingList = new ArrayList<>();
public AutoTileManager(Context context, AutoAddTracker.Builder autoAddTrackerBuilder,
- QSTileHost host,
+ QSHost host,
@Background Handler handler,
SecureSettings secureSettings,
HotspotController hotspotController,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index 9f3836105a95..7855cdfeb4c3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -374,6 +374,17 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
}
@Override
+ public void onBiometricDetected(int userId, BiometricSourceType biometricSourceType,
+ boolean isStrongBiometric) {
+ Trace.beginSection("BiometricUnlockController#onBiometricDetected");
+ if (mUpdateMonitor.isGoingToSleep()) {
+ Trace.endSection();
+ return;
+ }
+ startWakeAndUnlock(MODE_SHOW_BOUNCER);
+ }
+
+ @Override
public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType,
boolean isStrongBiometric) {
Trace.beginSection("BiometricUnlockController#onBiometricAuthenticated");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
index 8dcfec71b68e..9e62817fcc67 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
@@ -375,8 +375,6 @@ public interface CentralSurfaces extends Dumpable, ActivityStarter, LifecycleOwn
void fadeKeyguardAfterLaunchTransition(Runnable beforeFading,
Runnable endRunnable, Runnable cancelRunnable);
- void animateKeyguardUnoccluding();
-
void startLaunchTransitionTimeout();
boolean hideKeyguardImpl(boolean forceStateChange);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
index 6f4afe43fe50..b8c7a1d77810 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
@@ -50,6 +50,7 @@ import com.android.systemui.camera.CameraIntents;
import com.android.systemui.dagger.qualifiers.DisplayId;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.QSPanelController;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shade.CameraLauncher;
@@ -103,6 +104,7 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba
private final SystemBarAttributesListener mSystemBarAttributesListener;
private final Lazy<CameraLauncher> mCameraLauncherLazy;
private final QuickSettingsController mQsController;
+ private final QSHost mQSHost;
private static final VibrationAttributes HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES =
VibrationAttributes.createForUsage(VibrationAttributes.USAGE_HARDWARE_FEEDBACK);
@@ -135,7 +137,8 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba
@DisplayId int displayId,
SystemBarAttributesListener systemBarAttributesListener,
Lazy<CameraLauncher> cameraLauncherLazy,
- UserTracker userTracker) {
+ UserTracker userTracker,
+ QSHost qsHost) {
mCentralSurfaces = centralSurfaces;
mQsController = quickSettingsController;
mContext = context;
@@ -161,6 +164,7 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba
mDisplayId = displayId;
mCameraLauncherLazy = cameraLauncherLazy;
mUserTracker = userTracker;
+ mQSHost = qsHost;
mVibrateOnOpening = resources.getBoolean(R.bool.config_vibrateOnIconAnimation);
mCameraLaunchGestureVibrationEffect = getCameraGestureVibrationEffect(
@@ -181,22 +185,17 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba
@Override
public void addQsTile(ComponentName tile) {
- QSPanelController qsPanelController = mCentralSurfaces.getQSPanelController();
- if (qsPanelController != null && qsPanelController.getHost() != null) {
- qsPanelController.getHost().addTile(tile);
- }
+ mQSHost.addTile(tile);
}
@Override
public void remQsTile(ComponentName tile) {
- QSPanelController qsPanelController = mCentralSurfaces.getQSPanelController();
- if (qsPanelController != null && qsPanelController.getHost() != null) {
- qsPanelController.getHost().removeTileByUser(tile);
- }
+ mQSHost.removeTileByUser(tile);
}
@Override
public void clickTile(ComponentName tile) {
+ // Can't inject this because it changes with the QS fragment
QSPanelController qsPanelController = mCentralSurfaces.getQSPanelController();
if (qsPanelController != null) {
qsPanelController.clickTile(tile);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index 17fb05547e00..d6dc67143892 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -104,6 +104,8 @@ import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityManager;
import android.widget.DateTimeView;
+import android.window.BackEvent;
+import android.window.OnBackAnimationCallback;
import android.window.OnBackInvokedCallback;
import android.window.OnBackInvokedDispatcher;
@@ -164,6 +166,7 @@ import com.android.systemui.keyguard.ui.binder.LightRevealScrimViewBinder;
import com.android.systemui.keyguard.ui.viewmodel.LightRevealScrimViewModel;
import com.android.systemui.navigationbar.NavigationBarController;
import com.android.systemui.navigationbar.NavigationBarView;
+import com.android.systemui.notetask.NoteTaskController;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.OverlayPlugin;
@@ -507,6 +510,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
protected final NotificationInterruptStateProvider mNotificationInterruptStateProvider;
private final BrightnessSliderController.Factory mBrightnessSliderFactory;
private final FeatureFlags mFeatureFlags;
+ private final boolean mAnimateBack;
private final FragmentService mFragmentService;
private final ScreenOffAnimationController mScreenOffAnimationController;
private final WallpaperController mWallpaperController;
@@ -642,7 +646,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
private NotificationActivityStarter mNotificationActivityStarter;
private final Lazy<NotificationShadeDepthController> mNotificationShadeDepthControllerLazy;
private final Optional<Bubbles> mBubblesOptional;
- private final Bubbles.BubbleExpandListener mBubbleExpandListener;
+ private final Lazy<NoteTaskController> mNoteTaskControllerLazy;
private final Optional<StartingSurface> mStartingSurfaceOptional;
private final ActivityIntentHelper mActivityIntentHelper;
@@ -653,6 +657,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
private final InteractionJankMonitor mJankMonitor;
+ /** Existing callback that handles back gesture invoked for the Shade. */
private final OnBackInvokedCallback mOnBackInvokedCallback = () -> {
if (DEBUG) {
Log.d(TAG, "mOnBackInvokedCallback() called");
@@ -660,6 +665,33 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
onBackPressed();
};
+ private boolean shouldBackBeHandled() {
+ return (mState != StatusBarState.KEYGUARD && mState != StatusBarState.SHADE_LOCKED
+ && !isBouncerShowingOverDream());
+ }
+
+ /**
+ * New callback that handles back gesture invoked, cancel, progress
+ * and provides feedback via Shade animation.
+ * (enabled via the WM_SHADE_ANIMATE_BACK_GESTURE flag)
+ */
+ private final OnBackAnimationCallback mOnBackAnimationCallback = new OnBackAnimationCallback() {
+ @Override
+ public void onBackInvoked() {
+ onBackPressed();
+ }
+
+ @Override
+ public void onBackProgressed(BackEvent event) {
+ if (shouldBackBeHandled()) {
+ if (mNotificationPanelViewController.canPanelBeCollapsed()) {
+ float fraction = event.getProgress();
+ mNotificationPanelViewController.onBackProgressed(fraction);
+ }
+ }
+ }
+ };
+
/**
* Public constructor for CentralSurfaces.
*
@@ -705,6 +737,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
WakefulnessLifecycle wakefulnessLifecycle,
SysuiStatusBarStateController statusBarStateController,
Optional<Bubbles> bubblesOptional,
+ Lazy<NoteTaskController> noteTaskControllerLazy,
DeviceProvisionedController deviceProvisionedController,
NavigationBarController navigationBarController,
AccessibilityFloatingMenuController accessibilityFloatingMenuController,
@@ -795,6 +828,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
mWakefulnessLifecycle = wakefulnessLifecycle;
mStatusBarStateController = statusBarStateController;
mBubblesOptional = bubblesOptional;
+ mNoteTaskControllerLazy = noteTaskControllerLazy;
mDeviceProvisionedController = deviceProvisionedController;
mNavigationBarController = navigationBarController;
mAccessibilityFloatingMenuController = accessibilityFloatingMenuController;
@@ -852,9 +886,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
mShadeExpansionStateManager.addExpansionListener(this::onPanelExpansionChanged);
mShadeExpansionStateManager.addFullExpansionListener(this::onShadeExpansionFullyChanged);
- mBubbleExpandListener = (isExpanding, key) ->
- mContext.getMainExecutor().execute(this::updateScrimController);
-
mActivityIntentHelper = new ActivityIntentHelper(mContext);
mActivityLaunchAnimator = activityLaunchAnimator;
@@ -882,6 +913,17 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
if (mFeatureFlags.isEnabled(Flags.WM_ENABLE_PREDICTIVE_BACK_SYSUI)) {
mContext.getApplicationInfo().setEnableOnBackInvokedCallback(true);
}
+ // Based on teamfood flag, enable predictive back animation for the Shade.
+ mAnimateBack = mFeatureFlags.isEnabled(Flags.WM_SHADE_ANIMATE_BACK_GESTURE);
+ }
+
+ private void initBubbles(Bubbles bubbles) {
+ final Bubbles.BubbleExpandListener listener = (isExpanding, key) ->
+ mContext.getMainExecutor().execute(() -> {
+ updateScrimController();
+ mNoteTaskControllerLazy.get().onBubbleExpandChanged(isExpanding, key);
+ });
+ bubbles.setExpandListener(listener);
}
@Override
@@ -889,9 +931,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
mScreenLifecycle.addObserver(mScreenObserver);
mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
mUiModeManager = mContext.getSystemService(UiModeManager.class);
- if (mBubblesOptional.isPresent()) {
- mBubblesOptional.get().setExpandListener(mBubbleExpandListener);
- }
+ mBubblesOptional.ifPresent(this::initBubbles);
// Do not restart System UI when the bugreport flag changes.
mFeatureFlags.addListener(Flags.LEAVE_SHADE_OPEN_FOR_BUGREPORT, event -> {
@@ -2214,10 +2254,10 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
pw.println("Current Status Bar state:");
pw.println(" mExpandedVisible=" + mShadeController.isExpandedVisible());
pw.println(" mDisplayMetrics=" + mDisplayMetrics);
- pw.println(" mStackScroller: " + CentralSurfaces.viewInfo(mStackScroller));
- pw.println(" mStackScroller: " + CentralSurfaces.viewInfo(mStackScroller)
- + " scroll " + mStackScroller.getScrollX()
+ pw.print(" mStackScroller: " + CentralSurfaces.viewInfo(mStackScroller));
+ pw.print(" scroll " + mStackScroller.getScrollX()
+ "," + mStackScroller.getScrollY());
+ pw.println(" translationX " + mStackScroller.getTranslationX());
}
pw.print(" mInteractingWindows="); pw.println(mInteractingWindows);
@@ -2554,7 +2594,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
String action = intent.getAction();
String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY);
if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
- if (mIsShortcutListSearchEnabled && Utilities.isTablet(mContext)) {
+ if (mIsShortcutListSearchEnabled && Utilities.isLargeScreen(mContext)) {
KeyboardShortcutListSearch.dismiss();
} else {
KeyboardShortcuts.dismiss();
@@ -2699,7 +2739,8 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
if (viewRootImpl != null) {
viewRootImpl.getOnBackInvokedDispatcher()
.registerOnBackInvokedCallback(OnBackInvokedDispatcher.PRIORITY_DEFAULT,
- mOnBackInvokedCallback);
+ mAnimateBack ? mOnBackAnimationCallback
+ : mOnBackInvokedCallback);
mIsBackCallbackRegistered = true;
if (DEBUG) Log.d(TAG, "is now VISIBLE to user AND callback registered");
}
@@ -2714,7 +2755,9 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
ViewRootImpl viewRootImpl = getViewRootImpl();
if (viewRootImpl != null) {
viewRootImpl.getOnBackInvokedDispatcher()
- .unregisterOnBackInvokedCallback(mOnBackInvokedCallback);
+ .unregisterOnBackInvokedCallback(
+ mAnimateBack ? mOnBackAnimationCallback
+ : mOnBackInvokedCallback);
mIsBackCallbackRegistered = false;
if (DEBUG) Log.d(TAG, "is NOT VISIBLE to user, AND callback unregistered");
}
@@ -2991,16 +3034,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
}
/**
- * Plays the animation when an activity that was occluding Keyguard goes away.
- */
- @Override
- public void animateKeyguardUnoccluding() {
- mNotificationPanelViewController.setExpandedFraction(0f);
- mCommandQueueCallbacks.animateExpandNotificationsPanel();
- mScrimController.setUnocclusionAnimationRunning(true);
- }
-
- /**
* Starts the timeout when we try to start the affordances on Keyguard. We usually rely that
* Keyguard goes away via fadeKeyguardAfterLaunchTransition, however, that might not happen
* because the launched app crashed or something else went wrong.
@@ -3256,9 +3289,10 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
if (mNotificationPanelViewController.closeUserSwitcherIfOpen()) {
return true;
}
- if (mState != StatusBarState.KEYGUARD && mState != StatusBarState.SHADE_LOCKED
- && !isBouncerShowingOverDream()) {
+ if (shouldBackBeHandled()) {
if (mNotificationPanelViewController.canPanelBeCollapsed()) {
+ // this is the Shade dismiss animation, so make sure QQS closes when it ends.
+ mNotificationPanelViewController.onBackPressed();
mShadeController.animateCollapseShade();
}
return true;
@@ -3765,6 +3799,9 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
} else {
mScrimController.transitionTo(ScrimState.AUTH_SCRIMMED);
}
+ // This will cancel the keyguardFadingAway animation if it is running. We need to do
+ // this as otherwise it can remain pending and leave keyguard in a weird state.
+ mUnlockScrimCallback.onCancelled();
} else if (mBouncerShowing && !unlocking) {
// Bouncer needs the front scrim when it's on top of an activity,
// tapping on a notification, editing QS or being dismissed by
@@ -3905,7 +3942,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
}
protected void toggleKeyboardShortcuts(int deviceId) {
- if (mIsShortcutListSearchEnabled && Utilities.isTablet(mContext)) {
+ if (mIsShortcutListSearchEnabled && Utilities.isLargeScreen(mContext)) {
KeyboardShortcutListSearch.toggle(mContext, deviceId);
} else {
KeyboardShortcuts.toggle(mContext, deviceId);
@@ -3913,7 +3950,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
}
protected void dismissKeyboardShortcuts() {
- if (mIsShortcutListSearchEnabled && Utilities.isTablet(mContext)) {
+ if (mIsShortcutListSearchEnabled && Utilities.isLargeScreen(mContext)) {
KeyboardShortcutListSearch.dismiss();
} else {
KeyboardShortcuts.dismiss();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
index cba0897408dd..753032c2ee01 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
@@ -21,9 +21,6 @@ import static android.app.StatusBarManager.DISABLE_SYSTEM_INFO;
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.ContentObserver;
@@ -36,13 +33,16 @@ import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
+import androidx.core.animation.Animator;
+import androidx.core.animation.AnimatorListenerAdapter;
+import androidx.core.animation.ValueAnimator;
import com.android.keyguard.CarrierTextController;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.logging.KeyguardLogger;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
+import com.android.systemui.animation.InterpolatorsAndroidX;
import com.android.systemui.battery.BatteryMeterViewController;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.log.LogLevel;
@@ -166,7 +166,8 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat
private final ValueAnimator.AnimatorUpdateListener mAnimatorUpdateListener =
animation -> {
- mKeyguardStatusBarAnimateAlpha = (float) animation.getAnimatedValue();
+ mKeyguardStatusBarAnimateAlpha =
+ (float) ((ValueAnimator) animation).getAnimatedValue();
updateViewState();
};
@@ -434,7 +435,7 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat
ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
anim.addUpdateListener(mAnimatorUpdateListener);
anim.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
- anim.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+ anim.setInterpolator(InterpolatorsAndroidX.LINEAR_OUT_SLOW_IN);
anim.start();
}
@@ -445,7 +446,7 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat
anim.addUpdateListener(mAnimatorUpdateListener);
anim.setStartDelay(startDelay);
anim.setDuration(duration);
- anim.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+ anim.setInterpolator(InterpolatorsAndroidX.LINEAR_OUT_SLOW_IN);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index 85590fc0b64f..eb19c0d2ad71 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -1,6 +1,5 @@
package com.android.systemui.statusbar.phone;
-import android.app.NotificationManager;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
@@ -39,6 +38,7 @@ import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator
import com.android.systemui.statusbar.notification.PropertyAnimator;
import com.android.systemui.statusbar.notification.collection.ListEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider;
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
import com.android.systemui.statusbar.window.StatusBarWindowController;
import com.android.wm.shell.bubbles.Bubbles;
@@ -73,6 +73,7 @@ public class NotificationIconAreaController implements
private final NotificationWakeUpCoordinator mWakeUpCoordinator;
private final KeyguardBypassController mBypassController;
private final DozeParameters mDozeParameters;
+ private final SectionStyleProvider mSectionStyleProvider;
private final Optional<Bubbles> mBubblesOptional;
private final StatusBarWindowController mStatusBarWindowController;
private final ScreenOffAnimationController mScreenOffAnimationController;
@@ -117,6 +118,7 @@ public class NotificationIconAreaController implements
NotificationMediaManager notificationMediaManager,
NotificationListener notificationListener,
DozeParameters dozeParameters,
+ SectionStyleProvider sectionStyleProvider,
Optional<Bubbles> bubblesOptional,
DemoModeController demoModeController,
DarkIconDispatcher darkIconDispatcher,
@@ -128,6 +130,7 @@ public class NotificationIconAreaController implements
mStatusBarStateController.addCallback(this);
mMediaManager = notificationMediaManager;
mDozeParameters = dozeParameters;
+ mSectionStyleProvider = sectionStyleProvider;
mWakeUpCoordinator = wakeUpCoordinator;
wakeUpCoordinator.addListener(this);
mBypassController = keyguardBypassController;
@@ -260,19 +263,13 @@ public class NotificationIconAreaController implements
protected boolean shouldShowNotificationIcon(NotificationEntry entry,
boolean showAmbient, boolean showLowPriority, boolean hideDismissed,
boolean hideRepliedMessages, boolean hideCurrentMedia, boolean hidePulsing) {
- if (entry.getRanking().isAmbient() && !showAmbient) {
+ if (!showAmbient && mSectionStyleProvider.isMinimized(entry)) {
return false;
}
if (hideCurrentMedia && entry.getKey().equals(mMediaManager.getMediaNotificationKey())) {
return false;
}
- if (!showLowPriority && entry.getImportance() < NotificationManager.IMPORTANCE_DEFAULT) {
- return false;
- }
- if (!entry.isTopLevelChild()) {
- return false;
- }
- if (entry.getRow().getVisibility() == View.GONE) {
+ if (!showLowPriority && mSectionStyleProvider.isSilent(entry)) {
return false;
}
if (entry.isRowDismissed() && hideDismissed) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 6c532a5c5fab..e6b76ad0e00c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -22,8 +22,6 @@ import android.annotation.Nullable;
import android.app.ActivityTaskManager;
import android.app.AlarmManager;
import android.app.AlarmManager.AlarmClockInfo;
-import android.app.IActivityManager;
-import android.app.SynchronousUserSwitchObserver;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -134,7 +132,6 @@ public class PhoneStatusBarPolicy
private final NextAlarmController mNextAlarmController;
private final AlarmManager mAlarmManager;
private final UserInfoController mUserInfoController;
- private final IActivityManager mIActivityManager;
private final UserManager mUserManager;
private final UserTracker mUserTracker;
private final DevicePolicyManager mDevicePolicyManager;
@@ -149,6 +146,7 @@ public class PhoneStatusBarPolicy
private final KeyguardStateController mKeyguardStateController;
private final LocationController mLocationController;
private final PrivacyItemController mPrivacyItemController;
+ private final Executor mMainExecutor;
private final Executor mUiBgExecutor;
private final SensorPrivacyController mSensorPrivacyController;
private final RecordingController mRecordingController;
@@ -168,16 +166,17 @@ public class PhoneStatusBarPolicy
@Inject
public PhoneStatusBarPolicy(StatusBarIconController iconController,
CommandQueue commandQueue, BroadcastDispatcher broadcastDispatcher,
- @UiBackground Executor uiBgExecutor, @Main Looper looper, @Main Resources resources,
- CastController castController, HotspotController hotspotController,
- BluetoothController bluetoothController, NextAlarmController nextAlarmController,
- UserInfoController userInfoController, RotationLockController rotationLockController,
- DataSaverController dataSaverController, ZenModeController zenModeController,
+ @Main Executor mainExecutor, @UiBackground Executor uiBgExecutor, @Main Looper looper,
+ @Main Resources resources, CastController castController,
+ HotspotController hotspotController, BluetoothController bluetoothController,
+ NextAlarmController nextAlarmController, UserInfoController userInfoController,
+ RotationLockController rotationLockController, DataSaverController dataSaverController,
+ ZenModeController zenModeController,
DeviceProvisionedController deviceProvisionedController,
KeyguardStateController keyguardStateController,
LocationController locationController,
- SensorPrivacyController sensorPrivacyController, IActivityManager iActivityManager,
- AlarmManager alarmManager, UserManager userManager, UserTracker userTracker,
+ SensorPrivacyController sensorPrivacyController, AlarmManager alarmManager,
+ UserManager userManager, UserTracker userTracker,
DevicePolicyManager devicePolicyManager, RecordingController recordingController,
@Nullable TelecomManager telecomManager, @DisplayId int displayId,
@Main SharedPreferences sharedPreferences, DateFormatUtil dateFormatUtil,
@@ -195,7 +194,6 @@ public class PhoneStatusBarPolicy
mNextAlarmController = nextAlarmController;
mAlarmManager = alarmManager;
mUserInfoController = userInfoController;
- mIActivityManager = iActivityManager;
mUserManager = userManager;
mUserTracker = userTracker;
mDevicePolicyManager = devicePolicyManager;
@@ -208,6 +206,7 @@ public class PhoneStatusBarPolicy
mPrivacyItemController = privacyItemController;
mSensorPrivacyController = sensorPrivacyController;
mRecordingController = recordingController;
+ mMainExecutor = mainExecutor;
mUiBgExecutor = uiBgExecutor;
mTelecomManager = telecomManager;
mRingerModeTracker = ringerModeTracker;
@@ -256,11 +255,7 @@ public class PhoneStatusBarPolicy
mRingerModeTracker.getRingerModeInternal().observeForever(observer);
// listen for user / profile change.
- try {
- mIActivityManager.registerUserSwitchObserver(mUserSwitchListener, TAG);
- } catch (RemoteException e) {
- // Ignore
- }
+ mUserTracker.addCallback(mUserSwitchListener, mMainExecutor);
// TTY status
updateTTY();
@@ -555,15 +550,15 @@ public class PhoneStatusBarPolicy
});
}
- private final SynchronousUserSwitchObserver mUserSwitchListener =
- new SynchronousUserSwitchObserver() {
+ private final UserTracker.Callback mUserSwitchListener =
+ new UserTracker.Callback() {
@Override
- public void onUserSwitching(int newUserId) throws RemoteException {
+ public void onUserChanging(int newUser, Context userContext) {
mHandler.post(() -> mUserInfoController.reloadUserInfo());
}
@Override
- public void onUserSwitchComplete(int newUserId) throws RemoteException {
+ public void onUserChanged(int newUser, Context userContext) {
mHandler.post(() -> {
updateAlarm();
updateManagedProfile();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 80093a3da325..fb8bf523f625 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -138,26 +138,12 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
private boolean mTransitioningToFullShade;
/**
- * Is there currently an unocclusion animation running. Used to avoid bright flickers
- * of the notification scrim.
- */
- private boolean mUnOcclusionAnimationRunning;
-
- /**
* The percentage of the bouncer which is hidden. If 1, the bouncer is completely hidden. If
* 0, the bouncer is visible.
*/
@FloatRange(from = 0, to = 1)
private float mBouncerHiddenFraction = KeyguardBouncerConstants.EXPANSION_HIDDEN;
- /**
- * Set whether an unocclusion animation is currently running on the notification panel. Used
- * to avoid bright flickers of the notification scrim.
- */
- public void setUnocclusionAnimationRunning(boolean unocclusionAnimationRunning) {
- mUnOcclusionAnimationRunning = unocclusionAnimationRunning;
- }
-
@IntDef(prefix = {"VISIBILITY_"}, value = {
TRANSPARENT,
SEMI_TRANSPARENT,
@@ -359,9 +345,16 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
}
}
- /**
- * Sets corner radius of scrims.
- */
+ // TODO(b/270984686) recompute scrim height accurately, based on shade contents.
+ /** Set corner radius of the bottom edge of the Notification scrim. */
+ public void setNotificationBottomRadius(float radius) {
+ if (mNotificationsScrim == null) {
+ return;
+ }
+ mNotificationsScrim.setBottomEdgeRadius(radius);
+ }
+
+ /** Sets corner radius of scrims. */
public void setScrimCornerRadius(int radius) {
if (mScrimBehind == null || mNotificationsScrim == null) {
return;
@@ -525,6 +518,12 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
scheduleUpdate();
}
+ /** This is used by the predictive back gesture animation to scale the Shade. */
+ public void applyBackScaling(float scale) {
+ mNotificationsScrim.setScaleX(scale);
+ mNotificationsScrim.setScaleY(scale);
+ }
+
public void onTrackingStarted() {
mDarkenWhileDragging = !mKeyguardStateController.canDismissLockScreen();
if (!mKeyguardUnlockAnimationController.isPlayingCannedUnlockAnimation()) {
@@ -532,10 +531,6 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
}
}
- public void onExpandingFinished() {
- setUnocclusionAnimationRunning(false);
- }
-
@VisibleForTesting
protected void onHideWallpaperTimeout() {
if (mState != ScrimState.AOD && mState != ScrimState.PULSING) {
@@ -875,13 +870,6 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
if (mKeyguardOccluded || hideNotificationScrim) {
mNotificationsAlpha = 0;
}
- if (mUnOcclusionAnimationRunning && mState == ScrimState.KEYGUARD) {
- // We're unoccluding the keyguard and don't want to have a bright flash.
- mNotificationsAlpha = ScrimState.KEYGUARD.getNotifAlpha();
- mNotificationsTint = ScrimState.KEYGUARD.getNotifTint();
- mBehindAlpha = ScrimState.KEYGUARD.getBehindAlpha();
- mBehindTint = ScrimState.KEYGUARD.getBehindTint();
- }
}
if (mState != ScrimState.UNLOCKED) {
mAnimatingPanelExpansionOnUnlock = false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 183790d123fd..66f5b6508494 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -66,6 +66,7 @@ import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInt
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.navigationbar.NavigationBarView;
import com.android.systemui.navigationbar.NavigationModeController;
+import com.android.systemui.navigationbar.TaskbarDelegate;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shade.NotificationPanelViewController;
import com.android.systemui.shade.ShadeController;
@@ -280,7 +281,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
private float mQsExpansion;
final Set<KeyguardViewManagerCallback> mCallbacks = new HashSet<>();
private boolean mIsModernAlternateBouncerEnabled;
- private boolean mIsUnoccludeTransitionFlagEnabled;
private boolean mIsBackAnimationEnabled;
private OnDismissAction mAfterKeyguardGoneAction;
@@ -300,6 +300,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
@Nullable private KeyguardBypassController mBypassController;
@Nullable private OccludingAppBiometricUI mOccludingAppBiometricUI;
+ @Nullable private TaskbarDelegate mTaskbarDelegate;
private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
new KeyguardUpdateMonitorCallback() {
@Override
@@ -359,7 +360,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
.map(SysUIUnfoldComponent::getFoldAodAnimationController).orElse(null);
mIsModernAlternateBouncerEnabled = featureFlags.isEnabled(Flags.MODERN_ALTERNATE_BOUNCER);
mAlternateBouncerInteractor = alternateBouncerInteractor;
- mIsUnoccludeTransitionFlagEnabled = featureFlags.isEnabled(Flags.UNOCCLUSION_TRANSITION);
mIsBackAnimationEnabled =
featureFlags.isEnabled(Flags.WM_ENABLE_PREDICTIVE_BACK_BOUNCER_ANIM);
}
@@ -564,6 +564,10 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
updateStates();
}
+ public void setTaskbarDelegate(TaskbarDelegate taskbarDelegate) {
+ mTaskbarDelegate = taskbarDelegate;
+ }
+
/**
* Show the keyguard. Will handle creating and attaching to the view manager
* lazily.
@@ -874,11 +878,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
// by a FLAG_DISMISS_KEYGUARD_ACTIVITY.
reset(isOccluding /* hideBouncerWhenShowing*/);
}
- if (!mIsUnoccludeTransitionFlagEnabled) {
- if (animate && !isOccluded && isShowing && !primaryBouncerIsShowing()) {
- mCentralSurfaces.animateKeyguardUnoccluding();
- }
- }
}
@Override
@@ -1193,7 +1192,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
* Updates the visibility of the nav bar window (which will cause insets changes).
*/
protected void updateNavigationBarVisibility(boolean navBarVisible) {
- if (mCentralSurfaces.getNavigationBarView() != null) {
+ if (mCentralSurfaces.getNavigationBarView() != null
+ || (mTaskbarDelegate != null && mTaskbarDelegate.isInitialized())) {
if (navBarVisible) {
long delay = getNavBarShowDelay();
if (delay == 0) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index 3471a4656637..726b2344309f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -561,10 +561,6 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
mLogger.logFullScreenIntentSuppressedByVR(entry);
return;
}
- if (mFeatureFlags.isEnabled(Flags.FSI_CHROME)) {
- // FsiChromeRepo runs its own implementation of launchFullScreenIntent
- return;
- }
// Stop screensaver if the notification has a fullscreen intent.
// (like an incoming phone call)
mUiBgExecutor.execute(() -> {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesComponent.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesComponent.java
index aec196fc90f0..8e59a8b62a05 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesComponent.java
@@ -22,11 +22,11 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
import com.android.keyguard.LockIconViewController;
import com.android.systemui.biometrics.AuthRippleController;
-import com.android.systemui.shade.LargeScreenShadeHeaderController;
import com.android.systemui.shade.NotificationPanelViewController;
import com.android.systemui.shade.NotificationShadeWindowView;
import com.android.systemui.shade.NotificationShadeWindowViewController;
import com.android.systemui.shade.QuickSettingsController;
+import com.android.systemui.shade.ShadeHeaderController;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationShelfController;
import com.android.systemui.statusbar.core.StatusBarInitializer;
@@ -138,9 +138,9 @@ public interface CentralSurfacesComponent {
CentralSurfacesCommandQueueCallbacks getCentralSurfacesCommandQueueCallbacks();
/**
- * Creates a {@link LargeScreenShadeHeaderController}.
+ * Creates a {@link ShadeHeaderController}.
*/
- LargeScreenShadeHeaderController getLargeScreenShadeHeaderController();
+ ShadeHeaderController getLargeScreenShadeHeaderController();
/**
* Creates a new {@link CollapsedStatusBarFragment} each time it's called. See
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java
index c1c6c88da822..0929233feb88 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java
@@ -20,9 +20,10 @@ import android.annotation.Nullable;
import android.content.ContentResolver;
import android.os.Handler;
import android.view.LayoutInflater;
-import android.view.View;
import android.view.ViewStub;
+import androidx.constraintlayout.motion.widget.MotionLayout;
+
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.LockIconView;
import com.android.systemui.R;
@@ -32,7 +33,6 @@ import com.android.systemui.biometrics.AuthRippleView;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.privacy.OngoingPrivacyChip;
import com.android.systemui.settings.UserTracker;
@@ -85,9 +85,7 @@ import dagger.multibindings.IntoSet;
@Module(subcomponents = StatusBarFragmentComponent.class)
public abstract class StatusBarViewModule {
- public static final String LARGE_SCREEN_SHADE_HEADER = "large_screen_shade_header";
- private static final String SPLIT_SHADE_BATTERY_VIEW = "split_shade_battery_view";
- public static final String LARGE_SCREEN_BATTERY_CONTROLLER = "split_shade_battery_controller";
+ public static final String SHADE_HEADER = "large_screen_shade_header";
public static final String STATUS_BAR_FRAGMENT = "status_bar_fragment";
/** */
@@ -171,17 +169,15 @@ public abstract class StatusBarViewModule {
/** */
@Provides
- @Named(LARGE_SCREEN_SHADE_HEADER)
+ @Named(SHADE_HEADER)
@CentralSurfacesComponent.CentralSurfacesScope
- public static View getLargeScreenShadeHeaderBarView(
+ public static MotionLayout getLargeScreenShadeHeaderBarView(
NotificationShadeWindowView notificationShadeWindowView,
FeatureFlags featureFlags) {
ViewStub stub = notificationShadeWindowView.findViewById(R.id.qs_header_stub);
- int layoutId = featureFlags.isEnabled(Flags.COMBINED_QS_HEADERS)
- ? R.layout.combined_qs_header
- : R.layout.large_screen_shade_header;
+ int layoutId = R.layout.combined_qs_header;
stub.setLayoutResource(layoutId);
- View v = stub.inflate();
+ MotionLayout v = (MotionLayout) stub.inflate();
return v;
}
@@ -197,7 +193,7 @@ public abstract class StatusBarViewModule {
@Provides
@CentralSurfacesComponent.CentralSurfacesScope
public static OngoingPrivacyChip getSplitShadeOngoingPrivacyChip(
- @Named(LARGE_SCREEN_SHADE_HEADER) View header) {
+ @Named(SHADE_HEADER) MotionLayout header) {
return header.findViewById(R.id.privacy_chip);
}
@@ -205,23 +201,23 @@ public abstract class StatusBarViewModule {
@Provides
@CentralSurfacesComponent.CentralSurfacesScope
static StatusIconContainer providesStatusIconContainer(
- @Named(LARGE_SCREEN_SHADE_HEADER) View header) {
+ @Named(SHADE_HEADER) MotionLayout header) {
return header.findViewById(R.id.statusIcons);
}
/** */
@Provides
@CentralSurfacesComponent.CentralSurfacesScope
- @Named(SPLIT_SHADE_BATTERY_VIEW)
- static BatteryMeterView getBatteryMeterView(@Named(LARGE_SCREEN_SHADE_HEADER) View view) {
+ @Named(SHADE_HEADER)
+ static BatteryMeterView getBatteryMeterView(@Named(SHADE_HEADER) MotionLayout view) {
return view.findViewById(R.id.batteryRemainingIcon);
}
@Provides
@CentralSurfacesComponent.CentralSurfacesScope
- @Named(LARGE_SCREEN_BATTERY_CONTROLLER)
+ @Named(SHADE_HEADER)
static BatteryMeterViewController getBatteryMeterViewController(
- @Named(SPLIT_SHADE_BATTERY_VIEW) BatteryMeterView batteryMeterView,
+ @Named(SHADE_HEADER) BatteryMeterView batteryMeterView,
UserTracker userTracker,
ConfigurationController configurationController,
TunerService tunerService,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
index 65becf77b347..ed978c39eb3d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
@@ -23,7 +23,6 @@ import static android.app.StatusBarManager.DISABLE_SYSTEM_INFO;
import static com.android.systemui.statusbar.events.SystemStatusAnimationSchedulerKt.IDLE;
import static com.android.systemui.statusbar.events.SystemStatusAnimationSchedulerKt.SHOWING_PERSISTENT_DOT;
-import android.animation.Animator;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.app.Fragment;
@@ -43,6 +42,7 @@ import android.view.ViewStub;
import android.widget.LinearLayout;
import androidx.annotation.VisibleForTesting;
+import androidx.core.animation.Animator;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.Dumpable;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt
index fe69f7507503..c04ea36b3d8d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt
@@ -16,9 +16,9 @@
package com.android.systemui.statusbar.phone.fragment
-import android.animation.Animator
-import android.animation.AnimatorSet
-import android.animation.ValueAnimator
+import androidx.core.animation.Animator
+import androidx.core.animation.AnimatorSet
+import androidx.core.animation.ValueAnimator
import android.content.res.Resources
import android.view.View
import com.android.systemui.R
@@ -46,15 +46,19 @@ class StatusBarSystemEventAnimator(
R.dimen.ongoing_appops_chip_animation_out_status_bar_translation_x)
override fun onSystemEventAnimationBegin(): Animator {
- val moveOut = ValueAnimator.ofFloat(0f, 1f).setDuration(23.frames)
- moveOut.interpolator = STATUS_BAR_X_MOVE_OUT
- moveOut.addUpdateListener { animation: ValueAnimator ->
- animatedView.translationX = -(translationXIn * animation.animatedValue as Float)
+ val moveOut = ValueAnimator.ofFloat(0f, 1f).apply {
+ duration = 23.frames
+ interpolator = STATUS_BAR_X_MOVE_OUT
+ addUpdateListener {
+ animatedView.translationX = -(translationXIn * animatedValue as Float)
+ }
}
- val alphaOut = ValueAnimator.ofFloat(1f, 0f).setDuration(8.frames)
- alphaOut.interpolator = null
- alphaOut.addUpdateListener { animation: ValueAnimator ->
- animatedView.alpha = animation.animatedValue as Float
+ val alphaOut = ValueAnimator.ofFloat(1f, 0f).apply {
+ duration = 8.frames
+ interpolator = null
+ addUpdateListener {
+ animatedView.alpha = animatedValue as Float
+ }
}
val animSet = AnimatorSet()
@@ -64,17 +68,21 @@ class StatusBarSystemEventAnimator(
override fun onSystemEventAnimationFinish(hasPersistentDot: Boolean): Animator {
animatedView.translationX = translationXOut.toFloat()
- val moveIn = ValueAnimator.ofFloat(1f, 0f).setDuration(28.frames)
- moveIn.startDelay = 2.frames
- moveIn.interpolator = STATUS_BAR_X_MOVE_IN
- moveIn.addUpdateListener { animation: ValueAnimator ->
- animatedView.translationX = translationXOut * animation.animatedValue as Float
+ val moveIn = ValueAnimator.ofFloat(1f, 0f).apply {
+ duration = 23.frames
+ startDelay = 7.frames
+ interpolator = STATUS_BAR_X_MOVE_IN
+ addUpdateListener {
+ animatedView.translationX = translationXOut * animatedValue as Float
+ }
}
- val alphaIn = ValueAnimator.ofFloat(0f, 1f).setDuration(10.frames)
- alphaIn.startDelay = 4.frames
- alphaIn.interpolator = null
- alphaIn.addUpdateListener { animation: ValueAnimator ->
- animatedView.alpha = animation.animatedValue as Float
+ val alphaIn = ValueAnimator.ofFloat(0f, 1f).apply {
+ duration = 5.frames
+ startDelay = 11.frames
+ interpolator = null
+ addUpdateListener {
+ animatedView.alpha = animatedValue as Float
+ }
}
val animatorSet = AnimatorSet()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfig.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfig.kt
index 8c82fbac90b8..f4e3eab8593d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfig.kt
@@ -45,7 +45,7 @@ import kotlinx.coroutines.flow.asStateFlow
* 1. Define a new `private val` wrapping the key using [BooleanCarrierConfig]
* 2. Define a public `val` exposing the wrapped flow using [BooleanCarrierConfig.config]
* 3. Add the new [BooleanCarrierConfig] to the list of tracked configs, so they are properly
- * updated when a new carrier config comes down
+ * updated when a new carrier config comes down
*/
class SystemUiCarrierConfig
internal constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
index b3d5b1e7e450..53a208cd171e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
@@ -353,8 +353,8 @@ constructor(
* True if the checked subId is in the list of current subs or the active mobile data subId
*
* @param checkedSubs the list to validate [subId] against. To invalidate the cache, pass in the
- * new subscription list. Otherwise use [subscriptions.value] to validate a subId against the
- * current known subscriptions
+ * new subscription list. Otherwise use [subscriptions.value] to validate a subId against the
+ * current known subscriptions
*/
private fun checkSub(subId: Int, checkedSubs: List<SubscriptionModel>): Boolean {
if (activeMobileDataSubscriptionId.value == subId) return true
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
index 7b0f95271d63..4caf2b09a3f2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
@@ -92,7 +92,8 @@ interface MobileIconInteractor {
* 1. The default network name, if one is configured
* 2. A derived name based off of the intent [ACTION_SERVICE_PROVIDERS_UPDATED]
* 3. Or, in the case where the repository sends us the default network name, we check for an
- * override in [connectionInfo.operatorAlphaShort], a value that is derived from [ServiceState]
+ * override in [connectionInfo.operatorAlphaShort], a value that is derived from
+ * [ServiceState]
*/
val networkName: StateFlow<NetworkNameModel>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileViewModel.kt
index 24cd9304f8dd..8e103f7bee2f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileViewModel.kt
@@ -25,7 +25,7 @@ import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
* allows the mobile icon to change some view parameters at different locations
*
* @param commonImpl for convenience, this class wraps a base interface that can provides all of the
- * common implementations between locations. See [MobileIconViewModel]
+ * common implementations between locations. See [MobileIconViewModel]
*/
abstract class LocationBasedMobileViewModel(
val commonImpl: MobileIconViewModelCommon,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcher.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcher.kt
index e0e0ed795e4a..b1296179d7f7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcher.kt
@@ -41,7 +41,6 @@ import kotlinx.coroutines.flow.stateIn
* or the [WifiRepositoryImpl]'s prod implementation, based on the current demo mode value. In this
* way, downstream clients can all consist of real implementations and not care about which
* repository is responsible for the data. Graphically:
- *
* ```
* RealRepository
* │
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index 3263c4e83a7c..1a4a311ee0de 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -410,11 +410,14 @@ public abstract class HeadsUpManager extends AlertingNotificationManager {
@Override
public boolean isSticky() {
- final boolean isSticky = (mEntry.isRowPinned() && expanded)
+ return (mEntry.isRowPinned() && expanded)
|| remoteInputActive
- || hasFullScreenIntent(mEntry)
- || mEntry.isStickyAndNotDemoted();
- return isSticky;
+ || hasFullScreenIntent(mEntry);
+ }
+
+ @Override
+ public boolean isStickyForSomeTime() {
+ return mEntry.isStickyAndNotDemoted();
}
@Override
@@ -476,10 +479,10 @@ public abstract class HeadsUpManager extends AlertingNotificationManager {
*/
@Override
protected long calculateFinishTime() {
- if (isSticky()) {
- return mEntry.mCreationElapsedRealTime + mStickyDisplayTime;
- }
- return mPostTime + getRecommendedHeadsUpTimeoutMs(mAutoDismissNotificationDecay);
+ final long duration = getRecommendedHeadsUpTimeoutMs(
+ isStickyForSomeTime() ? mStickyDisplayTime : mAutoDismissNotificationDecay);
+
+ return mPostTime + duration;
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.kt
index bdb656b9d2d5..1e223b1920ed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.kt
@@ -146,7 +146,7 @@ constructor(
*
* @param guestUserId id of the guest user to remove
* @param targetUserId id of the user to switch to after guest is removed. If
- * `UserHandle.USER_NULL`, then switch immediately to the newly created guest user.
+ * `UserHandle.USER_NULL`, then switch immediately to the newly created guest user.
*/
fun removeGuestUser(guestUserId: Int, targetUserId: Int) {
userInteractor.removeGuestUser(
@@ -160,9 +160,9 @@ constructor(
*
* @param guestUserId user id of the guest user to exit
* @param targetUserId user id of the guest user to exit, set to UserHandle#USER_NULL when
- * target user id is not known
+ * target user id is not known
* @param forceRemoveGuestOnExit true: remove guest before switching user, false: remove guest
- * only if its ephemeral, else keep guest
+ * only if its ephemeral, else keep guest
*/
fun exitGuestUser(guestUserId: Int, targetUserId: Int, forceRemoveGuestOnExit: Boolean) {
userInteractor.exitGuestUser(guestUserId, targetUserId, forceRemoveGuestOnExit)
diff --git a/packages/SystemUI/src/com/android/systemui/stylus/OWNERS b/packages/SystemUI/src/com/android/systemui/stylus/OWNERS
index 7ccb316dbca5..0ec996be72de 100644
--- a/packages/SystemUI/src/com/android/systemui/stylus/OWNERS
+++ b/packages/SystemUI/src/com/android/systemui/stylus/OWNERS
@@ -5,4 +5,6 @@ juliacr@google.com
madym@google.com
mgalhardo@google.com
petrcermak@google.com
+stevenckng@google.com
+tkachenkoi@google.com
vanjan@google.com \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/stylus/StylusManager.kt b/packages/SystemUI/src/com/android/systemui/stylus/StylusManager.kt
index 462504e82199..9952cfd4e85b 100644
--- a/packages/SystemUI/src/com/android/systemui/stylus/StylusManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/stylus/StylusManager.kt
@@ -22,6 +22,7 @@ import android.content.Context
import android.hardware.BatteryState
import android.hardware.input.InputManager
import android.hardware.input.InputSettings
+import android.os.Build
import android.os.Handler
import android.util.ArrayMap
import android.util.Log
@@ -61,8 +62,6 @@ constructor(
BluetoothAdapter.OnMetadataChangedListener {
private val stylusCallbacks: CopyOnWriteArrayList<StylusCallback> = CopyOnWriteArrayList()
- private val stylusBatteryCallbacks: CopyOnWriteArrayList<StylusBatteryCallback> =
- CopyOnWriteArrayList()
// This map should only be accessed on the handler
private val inputDeviceAddressMap: MutableMap<Int, String?> = ArrayMap()
@@ -82,6 +81,8 @@ constructor(
fun startListener() {
handler.post {
if (hasStarted) return@post
+ logDebug { "Listener has started." }
+
hasStarted = true
isInUsiSession =
inputManager.hasInputDevice {
@@ -103,19 +104,15 @@ constructor(
stylusCallbacks.remove(callback)
}
- fun registerBatteryCallback(callback: StylusBatteryCallback) {
- stylusBatteryCallbacks.add(callback)
- }
-
- fun unregisterBatteryCallback(callback: StylusBatteryCallback) {
- stylusBatteryCallbacks.remove(callback)
- }
-
override fun onInputDeviceAdded(deviceId: Int) {
if (!hasStarted) return
val device: InputDevice = inputManager.getInputDevice(deviceId) ?: return
if (!device.supportsSource(InputDevice.SOURCE_STYLUS)) return
+ logDebug {
+ "Stylus InputDevice added: $deviceId ${device.name}, " +
+ "External: ${device.isExternal}"
+ }
if (!device.isExternal) {
registerBatteryListener(deviceId)
@@ -137,6 +134,7 @@ constructor(
val device: InputDevice = inputManager.getInputDevice(deviceId) ?: return
if (!device.supportsSource(InputDevice.SOURCE_STYLUS)) return
+ logDebug { "Stylus InputDevice changed: $deviceId ${device.name}" }
val currAddress: String? = device.bluetoothAddress
val prevAddress: String? = inputDeviceAddressMap[deviceId]
@@ -157,6 +155,8 @@ constructor(
if (!hasStarted) return
if (!inputDeviceAddressMap.contains(deviceId)) return
+ logDebug { "Stylus InputDevice removed: $deviceId" }
+
unregisterBatteryListener(deviceId)
val btAddress: String? = inputDeviceAddressMap[deviceId]
@@ -180,7 +180,12 @@ constructor(
val isCharging = String(value) == "true"
- executeStylusBatteryCallbacks { cb ->
+ logDebug {
+ "Charging state metadata changed for device $inputDeviceId " +
+ "${device.address}: $isCharging"
+ }
+
+ executeStylusCallbacks { cb ->
cb.onStylusBluetoothChargingStateChanged(inputDeviceId, device, isCharging)
}
}
@@ -194,13 +199,10 @@ constructor(
handler.post {
if (!hasStarted) return@post
- if (DEBUG) {
- Log.d(
- TAG,
- "onBatteryStateChanged for $deviceId. " +
- "batteryState present: ${batteryState.isPresent}, " +
- "capacity: ${batteryState.capacity}"
- )
+ logDebug {
+ "Battery state changed for $deviceId. " +
+ "batteryState present: ${batteryState.isPresent}, " +
+ "capacity: ${batteryState.capacity}"
}
val batteryStateValid = isBatteryStateValid(batteryState)
@@ -209,14 +211,14 @@ constructor(
onStylusUsed()
}
- executeStylusBatteryCallbacks { cb ->
+ executeStylusCallbacks { cb ->
cb.onStylusUsiBatteryStateChanged(deviceId, eventTimeMillis, batteryState)
}
}
}
private fun onStylusBluetoothConnected(deviceId: Int, btAddress: String) {
- trackAndLogBluetoothSession(deviceId, true)
+ trackAndLogBluetoothSession(deviceId, btAddress, true)
val device: BluetoothDevice = bluetoothAdapter?.getRemoteDevice(btAddress) ?: return
try {
bluetoothAdapter.addOnMetadataChangedListener(device, executor, this)
@@ -226,7 +228,7 @@ constructor(
}
private fun onStylusBluetoothDisconnected(deviceId: Int, btAddress: String) {
- trackAndLogBluetoothSession(deviceId, false)
+ trackAndLogBluetoothSession(deviceId, btAddress, false)
val device: BluetoothDevice = bluetoothAdapter?.getRemoteDevice(btAddress) ?: return
try {
bluetoothAdapter.removeOnMetadataChangedListener(device, this)
@@ -245,6 +247,7 @@ constructor(
if (!featureFlags.isEnabled(Flags.TRACK_STYLUS_EVER_USED)) return
if (InputSettings.isStylusEverUsed(context)) return
+ logDebug { "Stylus used for the first time." }
InputSettings.setStylusEverUsed(context, true)
executeStylusCallbacks { cb -> cb.onStylusFirstUsed() }
}
@@ -259,12 +262,7 @@ constructor(
// TODO(b/268618918) handle cases where an invalid battery callback from a previous stylus
// is sent after the actual valid callback
if (batteryStateValid && usiSessionId == null) {
- if (DEBUG) {
- Log.d(
- TAG,
- "USI battery newly present, entering new USI session. Device ID: $deviceId"
- )
- }
+ logDebug { "USI battery newly present, entering new USI session: $deviceId" }
usiSessionId = instanceIdSequence.newInstanceId()
uiEventLogger.logWithInstanceId(
StylusUiEvent.USI_STYLUS_BATTERY_PRESENCE_FIRST_DETECTED,
@@ -273,9 +271,7 @@ constructor(
usiSessionId
)
} else if (!batteryStateValid && usiSessionId != null) {
- if (DEBUG) {
- Log.d(TAG, "USI battery newly absent, exiting USI session Device ID: $deviceId")
- }
+ logDebug { "USI battery newly absent, exiting USI session: $deviceId" }
uiEventLogger.logWithInstanceId(
StylusUiEvent.USI_STYLUS_BATTERY_PRESENCE_REMOVED,
0,
@@ -286,8 +282,17 @@ constructor(
}
}
- private fun trackAndLogBluetoothSession(deviceId: Int, bluetoothConnected: Boolean) {
- if (bluetoothConnected) {
+ private fun trackAndLogBluetoothSession(
+ deviceId: Int,
+ btAddress: String,
+ btConnected: Boolean
+ ) {
+ logDebug {
+ "Bluetooth stylus ${if (btConnected) "connected" else "disconnected"}:" +
+ " $deviceId $btAddress"
+ }
+
+ if (btConnected) {
inputDeviceBtSessionIdMap[deviceId] = instanceIdSequence.newInstanceId()
uiEventLogger.logWithInstanceId(
StylusUiEvent.BLUETOOTH_STYLUS_CONNECTED,
@@ -314,10 +319,6 @@ constructor(
stylusCallbacks.forEach(run)
}
- private fun executeStylusBatteryCallbacks(run: (cb: StylusBatteryCallback) -> Unit) {
- stylusBatteryCallbacks.forEach(run)
- }
-
private fun registerBatteryListener(deviceId: Int) {
try {
inputManager.addInputDeviceBatteryListener(deviceId, executor, this)
@@ -363,13 +364,6 @@ constructor(
fun onStylusBluetoothConnected(deviceId: Int, btAddress: String) {}
fun onStylusBluetoothDisconnected(deviceId: Int, btAddress: String) {}
fun onStylusFirstUsed() {}
- }
-
- /**
- * Callback interface to receive stylus battery events from the StylusManager. All callbacks are
- * runs on the same background handler.
- */
- interface StylusBatteryCallback {
fun onStylusBluetoothChargingStateChanged(
inputDeviceId: Int,
btDevice: BluetoothDevice,
@@ -383,7 +377,12 @@ constructor(
}
companion object {
- private val TAG = StylusManager::class.simpleName.orEmpty()
- private val DEBUG = false
+ val TAG = StylusManager::class.simpleName.orEmpty()
+ }
+}
+
+private inline fun logDebug(message: () -> String) {
+ if (Build.IS_DEBUGGABLE) {
+ Log.d(StylusManager.TAG, message())
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerStartable.kt b/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerStartable.kt
index 27cafb10c07d..3667392b515e 100644
--- a/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerStartable.kt
@@ -37,7 +37,7 @@ constructor(
private val inputManager: InputManager,
private val stylusUsiPowerUi: StylusUsiPowerUI,
private val featureFlags: FeatureFlags,
-) : CoreStartable, StylusManager.StylusCallback, StylusManager.StylusBatteryCallback {
+) : CoreStartable, StylusManager.StylusCallback {
override fun onStylusAdded(deviceId: Int) {
// On some devices, the addition of a new internal stylus indicates the use of a
@@ -74,7 +74,6 @@ constructor(
stylusUsiPowerUi.init()
stylusManager.registerCallback(this)
- stylusManager.registerBatteryCallback(this)
stylusManager.startListener()
}
diff --git a/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt b/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt
index ec0a6e7a80d8..21b0efadb8d5 100644
--- a/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt
+++ b/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt
@@ -26,6 +26,7 @@ import android.content.Intent
import android.content.IntentFilter
import android.hardware.BatteryState
import android.hardware.input.InputManager
+import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.UserHandle
@@ -109,6 +110,10 @@ constructor(
inputDeviceId = deviceId
batteryCapacity = batteryState.capacity
+ logDebug {
+ "Updating notification battery state to $batteryCapacity " +
+ "for InputDevice $deviceId."
+ }
refresh()
}
}
@@ -125,12 +130,14 @@ constructor(
handler.post updateSuppressed@{
if (suppressed == suppress) return@updateSuppressed
+ logDebug { "Updating notification suppression to $suppress." }
suppressed = suppress
refresh()
}
}
private fun hideNotification() {
+ logDebug { "Cancelling USI low battery notification." }
instanceId = null
notificationManager.cancel(USI_NOTIFICATION_ID)
}
@@ -153,6 +160,7 @@ constructor(
.setAutoCancel(true)
.build()
+ logDebug { "Show or update USI low battery notification at $batteryCapacity." }
logUiEvent(StylusUiEvent.STYLUS_LOW_BATTERY_NOTIFICATION_SHOWN)
notificationManager.notify(USI_NOTIFICATION_ID, notification)
}
@@ -180,10 +188,12 @@ constructor(
override fun onReceive(context: Context, intent: Intent) {
when (intent.action) {
ACTION_DISMISSED_LOW_BATTERY -> {
+ logDebug { "USI low battery notification dismissed." }
logUiEvent(StylusUiEvent.STYLUS_LOW_BATTERY_NOTIFICATION_DISMISSED)
updateSuppression(true)
}
ACTION_CLICKED_LOW_BATTERY -> {
+ logDebug { "USI low battery notification clicked." }
logUiEvent(StylusUiEvent.STYLUS_LOW_BATTERY_NOTIFICATION_CLICKED)
updateSuppression(true)
if (inputDeviceId == null) return
@@ -233,6 +243,8 @@ constructor(
}
companion object {
+ val TAG = StylusUsiPowerUI::class.simpleName.orEmpty()
+
// Low battery threshold matches CrOS, see:
// https://source.chromium.org/chromium/chromium/src/+/main:ash/system/power/peripheral_battery_notifier.cc;l=41
private const val LOW_BATTERY_THRESHOLD = 0.16f
@@ -251,3 +263,9 @@ constructor(
@VisibleForTesting const val KEY_SETTINGS_FRAGMENT_ARGS = ":settings:show_fragment_args"
}
}
+
+private inline fun logDebug(message: () -> String) {
+ if (Build.IS_DEBUGGABLE) {
+ Log.d(StylusUsiPowerUI.TAG, message())
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/telephony/ui/activity/SwitchToManagedProfileForCallActivity.kt b/packages/SystemUI/src/com/android/systemui/telephony/ui/activity/SwitchToManagedProfileForCallActivity.kt
index e092f01d19f6..8e2b05cd9526 100644
--- a/packages/SystemUI/src/com/android/systemui/telephony/ui/activity/SwitchToManagedProfileForCallActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/telephony/ui/activity/SwitchToManagedProfileForCallActivity.kt
@@ -66,7 +66,7 @@ class SwitchToManagedProfileForCallActivity : AlertActivity(), DialogInterface.O
private fun switchToManagedProfile() {
try {
applicationContext.startActivityAsUser(
- Intent(Intent.ACTION_DIAL, phoneNumber),
+ Intent(Intent.ACTION_CALL, phoneNumber),
ActivityOptions.makeOpenCrossProfileAppsAnimation().toBundle(),
UserHandle.of(managedProfileUserId)
)
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TouchableRegionViewController.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TouchableRegionViewController.kt
index 60241a9684d9..cf0184f9e1ae 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TouchableRegionViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TouchableRegionViewController.kt
@@ -27,7 +27,7 @@ import com.android.systemui.util.ViewController
* pass through to the window below.
*
* @param touchableRegionSetter a function that, given the view and an out rect, fills the rect with
- * the touchable region of this view.
+ * the touchable region of this view.
*/
class TouchableRegionViewController(
view: View,
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarAnimator.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarAnimator.kt
index 01a81deabc95..16123882046c 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarAnimator.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarAnimator.kt
@@ -35,7 +35,7 @@ open class ChipbarAnimator @Inject constructor() {
* Animates [innerView] and its children into view.
*
* @return true if the animation was successfully started and false if the animation can't be
- * run for any reason.
+ * run for any reason.
*
* See [ViewHierarchyAnimator.animateAddition].
*/
@@ -55,7 +55,7 @@ open class ChipbarAnimator @Inject constructor() {
* Animates [innerView] and its children out of view.
*
* @return true if the animation was successfully started and false if the animation can't be
- * run for any reason.
+ * run for any reason.
*
* See [ViewHierarchyAnimator.animateRemoval].
*/
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt
index fe46318daa30..125cc761d400 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt
@@ -28,10 +28,10 @@ import com.android.systemui.temporarydisplay.ViewPriority
* A container for all the state needed to display a chipbar via [ChipbarCoordinator].
*
* @property startIcon the icon to display at the start of the chipbar (on the left in LTR locales;
- * on the right in RTL locales).
+ * on the right in RTL locales).
* @property text the text to display.
* @property endItem an optional end item to display at the end of the chipbar (on the right in LTR
- * locales; on the left in RTL locales).
+ * locales; on the left in RTL locales).
* @property vibrationEffect an optional vibration effect when the chipbar is displayed
* @property allowSwipeToDismiss true if users are allowed to swipe up to dismiss this chipbar.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
index b23d870fb82f..8cfe2eac3d33 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
@@ -42,7 +42,7 @@ import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.demomode.DemoModeController;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.SystemUIDialog;
@@ -68,7 +68,7 @@ public class TunerServiceImpl extends TunerService {
// Things that use the tunable infrastructure but are now real user settings and
// shouldn't be reset with tuner settings.
private static final String[] RESET_EXCEPTION_LIST = new String[] {
- QSTileHost.TILES_SETTING,
+ QSHost.TILES_SETTING,
Settings.Secure.DOZE_ALWAYS_ON,
Settings.Secure.MEDIA_CONTROLS_RESUME,
Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
index 5ea43994d404..0a78d896e1bd 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
@@ -54,6 +54,7 @@ import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
import com.android.systemui.statusbar.NotificationShadeWindowController;
+import com.android.systemui.statusbar.events.StatusBarEventsModule;
import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider;
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.phone.DozeServiceHost;
@@ -95,6 +96,7 @@ import dagger.multibindings.IntoSet;
PowerModule.class,
QSModule.class,
ReferenceScreenshotModule.class,
+ StatusBarEventsModule.class,
VolumeModule.class,
}
)
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/FoldStateLoggingProviderImpl.kt b/packages/SystemUI/src/com/android/systemui/unfold/FoldStateLoggingProviderImpl.kt
index 2683971f852c..981f429d1f8f 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/FoldStateLoggingProviderImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/FoldStateLoggingProviderImpl.kt
@@ -61,8 +61,6 @@ class FoldStateLoggingProviderImpl(
foldStateProvider.stop()
}
- override fun onHingeAngleUpdate(angle: Float) {}
-
override fun onFoldUpdate(@FoldUpdate update: Int) {
val now = clock.elapsedRealtime()
when (update) {
@@ -77,6 +75,10 @@ class FoldStateLoggingProviderImpl(
}
}
+ override fun onUnfoldedScreenAvailable() {
+ Log.d(TAG, "Unfolded screen available")
+ }
+
private fun dispatchState(@LoggedFoldedStates current: Int) {
val now = clock.elapsedRealtime()
val previous = lastState
diff --git a/packages/SystemUI/src/com/android/systemui/user/UserCreator.kt b/packages/SystemUI/src/com/android/systemui/user/UserCreator.kt
index 5f89d5d144e8..9304a462b6a8 100644
--- a/packages/SystemUI/src/com/android/systemui/user/UserCreator.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/UserCreator.kt
@@ -45,7 +45,7 @@ constructor(
*
* @param successCallback is called when the user creation is successful.
* @param errorCallback is called when userManager.createUser returns null. (Exceptions are not
- * handled by this class)
+ * handled by this class)
*/
fun createUser(
userName: String?,
diff --git a/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt b/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt
index 70523bb6b81d..a0b56aa6f5c3 100644
--- a/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt
@@ -17,11 +17,8 @@
package com.android.systemui.user.data.repository
-import android.app.IActivityManager
-import android.app.UserSwitchObserver
import android.content.Context
import android.content.pm.UserInfo
-import android.os.IRemoteCallback
import android.os.UserHandle
import android.os.UserManager
import android.provider.Settings
@@ -121,7 +118,6 @@ constructor(
@Background private val backgroundDispatcher: CoroutineDispatcher,
private val globalSettings: GlobalSettings,
private val tracker: UserTracker,
- private val activityManager: IActivityManager,
featureFlags: FeatureFlags,
) : UserRepository {
@@ -213,18 +209,18 @@ constructor(
private fun observeUserSwitching() {
conflatedCallbackFlow {
val callback =
- object : UserSwitchObserver() {
- override fun onUserSwitching(newUserId: Int, reply: IRemoteCallback) {
+ object : UserTracker.Callback {
+ override fun onUserChanging(newUser: Int, userContext: Context) {
trySendWithFailureLogging(true, TAG, "userSwitching started")
}
- override fun onUserSwitchComplete(newUserId: Int) {
+ override fun onUserChanged(newUserId: Int, userContext: Context) {
trySendWithFailureLogging(false, TAG, "userSwitching completed")
}
}
- activityManager.registerUserSwitchObserver(callback, TAG)
+ tracker.addCallback(callback, mainDispatcher.asExecutor())
trySendWithFailureLogging(false, TAG, "initial value defaulting to false")
- awaitClose { activityManager.unregisterUserSwitchObserver(callback) }
+ awaitClose { tracker.removeCallback(callback) }
}
.onEach { _isUserSwitchingInProgress.value = it }
// TODO (b/262838215), Make this stateIn and initialize directly in field declaration
diff --git a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/GuestUserInteractor.kt b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/GuestUserInteractor.kt
index 2f63f32557e9..f026f0f9de37 100644
--- a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/GuestUserInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/GuestUserInteractor.kt
@@ -313,7 +313,7 @@ constructor(
* to create a new one.
*
* @return The multi-user user ID of the newly created guest user, or [UserHandle.USER_NULL] if
- * the guest couldn't be created.
+ * the guest couldn't be created.
*/
@UserIdInt
private suspend fun createInBackground(): Int {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/EmergencyButtonControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/EmergencyButtonControllerTest.kt
new file mode 100644
index 000000000000..30fed0b0316f
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/keyguard/EmergencyButtonControllerTest.kt
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2023 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.keyguard
+
+import android.app.ActivityTaskManager
+import android.content.pm.PackageManager
+import android.os.PowerManager
+import android.telecom.TelecomManager
+import android.telephony.TelephonyManager
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
+import com.android.internal.logging.MetricsLogger
+import com.android.internal.widget.LockPatternUtils
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.shade.ShadeController
+import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.time.FakeSystemClock
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.Mockito.anyInt
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
+class EmergencyButtonControllerTest : SysuiTestCase() {
+ lateinit var underTest: EmergencyButtonController
+ @Mock lateinit var emergencyButton: EmergencyButton
+ @Mock lateinit var configurationController: ConfigurationController
+ @Mock lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
+ @Mock lateinit var telephonyManager: TelephonyManager
+ @Mock lateinit var powerManager: PowerManager
+ @Mock lateinit var activityTaskManager: ActivityTaskManager
+ @Mock lateinit var shadeController: ShadeController
+ @Mock lateinit var telecomManager: TelecomManager
+ @Mock lateinit var metricsLogger: MetricsLogger
+ @Mock lateinit var lockPatternUtils: LockPatternUtils
+ @Mock lateinit var packageManager: PackageManager
+ val fakeSystemClock = FakeSystemClock()
+ val mainExecutor = FakeExecutor(fakeSystemClock)
+ val backgroundExecutor = FakeExecutor(fakeSystemClock)
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ underTest =
+ EmergencyButtonController(
+ emergencyButton,
+ configurationController,
+ keyguardUpdateMonitor,
+ telephonyManager,
+ powerManager,
+ activityTaskManager,
+ shadeController,
+ telecomManager,
+ metricsLogger,
+ lockPatternUtils,
+ mainExecutor,
+ backgroundExecutor
+ )
+ context.setMockPackageManager(packageManager)
+ Mockito.`when`(emergencyButton.context).thenReturn(context)
+ }
+
+ @Test
+ fun testUpdateEmergencyButton() {
+ Mockito.`when`(telecomManager.isInCall).thenReturn(true)
+ Mockito.`when`(lockPatternUtils.isSecure(anyInt())).thenReturn(true)
+ Mockito.`when`(packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY))
+ .thenReturn(true)
+ underTest.updateEmergencyCallButton()
+ backgroundExecutor.runAllReady()
+ verify(emergencyButton, never())
+ .updateEmergencyCallButton(
+ /* isInCall= */ any(),
+ /* hasTelephonyRadio= */ any(),
+ /* simLocked= */ any(),
+ /* isSecure= */ any()
+ )
+ mainExecutor.runAllReady()
+ verify(emergencyButton)
+ .updateEmergencyCallButton(
+ /* isInCall= */ eq(true),
+ /* hasTelephonyRadio= */ eq(true),
+ /* simLocked= */ any(),
+ /* isSecure= */ eq(true)
+ )
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
index 082c8ccd9657..13b3b1afd30b 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
@@ -18,8 +18,10 @@ package com.android.keyguard
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
+import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
+import android.widget.ImageView
import androidx.test.filters.SmallTest
import com.android.internal.util.LatencyTracker
import com.android.internal.widget.LockPatternUtils
@@ -30,6 +32,7 @@ import com.android.systemui.util.concurrency.DelayableExecutor
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyString
import org.mockito.Mock
@@ -37,6 +40,7 @@ import org.mockito.Mockito
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when`
+import org.mockito.Mockito.mock
import org.mockito.MockitoAnnotations
@SmallTest
@@ -76,7 +80,9 @@ class KeyguardPasswordViewControllerTest : SysuiTestCase() {
Mockito.`when`(keyguardPasswordView.findViewById<EditText>(R.id.passwordEntry))
.thenReturn(passwordEntry)
`when`(keyguardPasswordView.resources).thenReturn(context.resources)
- keyguardPasswordViewController =
+ `when`(keyguardPasswordView.findViewById<ImageView>(R.id.switch_ime_button))
+ .thenReturn(mock(ImageView::class.java))
+ keyguardPasswordViewController =
KeyguardPasswordViewController(
keyguardPasswordView,
keyguardUpdateMonitor,
@@ -113,6 +119,18 @@ class KeyguardPasswordViewControllerTest : SysuiTestCase() {
}
@Test
+ fun onApplyWindowInsetsListener_onApplyWindowInsets() {
+ `when`(keyguardViewController.isBouncerShowing).thenReturn(false)
+ val argumentCaptor = ArgumentCaptor.forClass(View.OnApplyWindowInsetsListener::class.java)
+
+ keyguardPasswordViewController.onViewAttached()
+ verify(keyguardPasswordView).setOnApplyWindowInsetsListener(argumentCaptor.capture())
+ argumentCaptor.value.onApplyWindowInsets(keyguardPasswordView, null)
+
+ verify(keyguardPasswordView).hideKeyboard()
+ }
+
+ @Test
fun testHideKeyboardWhenOnPause() {
keyguardPasswordViewController.onPause()
keyguardPasswordView.post {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
index 1bbc19931c21..531006da8210 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
@@ -37,6 +37,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -160,6 +161,29 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
}
@Test
+ public void testOnApplyWindowInsets_disappearAnimation_paddingNotSet() {
+ int paddingBottom = getContext().getResources()
+ .getDimensionPixelSize(R.dimen.keyguard_security_view_bottom_margin);
+ int imeInsetAmount = paddingBottom + 1;
+ int systemBarInsetAmount = 0;
+ initMode(MODE_DEFAULT);
+
+ Insets imeInset = Insets.of(0, 0, 0, imeInsetAmount);
+ Insets systemBarInset = Insets.of(0, 0, 0, systemBarInsetAmount);
+
+ WindowInsets insets = new WindowInsets.Builder()
+ .setInsets(ime(), imeInset)
+ .setInsetsIgnoringVisibility(systemBars(), systemBarInset)
+ .build();
+
+ ensureViewFlipperIsMocked();
+ mKeyguardSecurityContainer.startDisappearAnimation(
+ KeyguardSecurityModel.SecurityMode.Password);
+ mKeyguardSecurityContainer.onApplyWindowInsets(insets);
+ assertThat(mKeyguardSecurityContainer.getPaddingBottom()).isNotEqualTo(imeInsetAmount);
+ }
+
+ @Test
public void testDefaultViewMode() {
initMode(MODE_ONE_HANDED);
initMode(MODE_DEFAULT);
@@ -376,6 +400,17 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
assertThat(mKeyguardSecurityContainer.getScaleY()).isEqualTo(1);
}
+ @Test
+ public void testDisappearAnimationPassword() {
+ ensureViewFlipperIsMocked();
+ KeyguardPasswordView keyguardPasswordView = mock(KeyguardPasswordView.class);
+ when(mSecurityViewFlipper.getSecurityView()).thenReturn(keyguardPasswordView);
+
+ mKeyguardSecurityContainer
+ .startDisappearAnimation(KeyguardSecurityModel.SecurityMode.Password);
+ verify(keyguardPasswordView).setDisappearAnimationListener(any());
+ }
+
private BackEvent createBackEvent(float touchX, float progress) {
return new BackEvent(0, 0, progress, BackEvent.EDGE_LEFT);
}
@@ -446,4 +481,12 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
mUserSwitcherController, () -> {
}, mFalsingA11yDelegate);
}
+
+ private void ensureViewFlipperIsMocked() {
+ mSecurityViewFlipper = mock(KeyguardSecurityViewFlipper.class);
+ KeyguardPasswordView keyguardPasswordView = mock(KeyguardPasswordView.class);
+ when(mSecurityViewFlipper.getSecurityView()).thenReturn(keyguardPasswordView);
+ mKeyguardSecurityContainer.mSecurityViewFlipper = mSecurityViewFlipper;
+ }
+
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
index dfad15d68375..71449145d668 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
@@ -26,7 +26,6 @@ import android.testing.AndroidTestingRunner;
import com.android.keyguard.logging.KeyguardLogger;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.ClockAnimations;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
@@ -61,8 +60,6 @@ public class KeyguardStatusViewControllerTest extends SysuiTestCase {
@Mock
DozeParameters mDozeParameters;
@Mock
- FeatureFlags mFeatureFlags;
- @Mock
ScreenOffAnimationController mScreenOffAnimationController;
@Captor
private ArgumentCaptor<KeyguardUpdateMonitorCallback> mKeyguardUpdateMonitorCallbackCaptor;
@@ -83,7 +80,6 @@ public class KeyguardStatusViewControllerTest extends SysuiTestCase {
mKeyguardUpdateMonitor,
mConfigurationController,
mDozeParameters,
- mFeatureFlags,
mScreenOffAnimationController,
mKeyguardLogger);
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index e5d0692aaac2..86ba30cee7a3 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -20,6 +20,8 @@ import static android.app.StatusBarManager.SESSION_KEYGUARD;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT;
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT_PERMANENT;
+import static android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN;
+import static android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_STARTED_WAKING_UP;
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_POWER_BUTTON;
import static android.telephony.SubscriptionManager.DATA_ROAMING_DISABLE;
import static android.telephony.SubscriptionManager.NAME_SOURCE_CARRIER_ID;
@@ -29,7 +31,6 @@ import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STR
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
import static com.android.keyguard.FaceAuthApiRequestReason.NOTIFICATION_PANEL_CLICKED;
import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_AVAILABLE;
-import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_STATE_CANCELLING;
import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_STATE_CANCELLING_RESTARTING;
import static com.android.keyguard.KeyguardUpdateMonitor.DEFAULT_CANCEL_SIGNAL_TIMEOUT;
import static com.android.keyguard.KeyguardUpdateMonitor.HAL_POWER_PRESS_TIMEOUT;
@@ -58,8 +59,6 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Activity;
-import android.app.ActivityManager;
-import android.app.IActivityManager;
import android.app.admin.DevicePolicyManager;
import android.app.trust.IStrongAuthTracker;
import android.app.trust.TrustManager;
@@ -81,6 +80,7 @@ import android.hardware.biometrics.BiometricSourceType;
import android.hardware.biometrics.ComponentInfoInternal;
import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
import android.hardware.biometrics.SensorProperties;
+import android.hardware.face.FaceAuthenticateOptions;
import android.hardware.face.FaceManager;
import android.hardware.face.FaceSensorProperties;
import android.hardware.face.FaceSensorPropertiesInternal;
@@ -96,7 +96,6 @@ import android.os.BatteryManager;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.Handler;
-import android.os.IRemoteCallback;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -155,6 +154,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -238,8 +238,6 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
@Mock
private KeyguardUpdateMonitorLogger mKeyguardUpdateMonitorLogger;
@Mock
- private IActivityManager mActivityService;
- @Mock
private SessionTracker mSessionTracker;
@Mock
private UiEventLogger mUiEventLogger;
@@ -281,8 +279,6 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
@Before
public void setup() throws RemoteException {
MockitoAnnotations.initMocks(this);
- when(mActivityService.getCurrentUser()).thenReturn(mCurrentUserInfo);
- when(mActivityService.getCurrentUserId()).thenReturn(mCurrentUserId);
when(mFaceManager.isHardwareDetected()).thenReturn(true);
when(mAuthController.isFaceAuthEnrolled(anyInt())).thenReturn(true);
when(mFaceManager.getSensorPropertiesInternal()).thenReturn(mFaceSensorProperties);
@@ -321,13 +317,11 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mMockitoSession = ExtendedMockito.mockitoSession()
.spyStatic(SubscriptionManager.class)
- .spyStatic(ActivityManager.class)
.startMocking();
ExtendedMockito.doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
.when(SubscriptionManager::getDefaultSubscriptionId);
KeyguardUpdateMonitor.setCurrentUser(mCurrentUserId);
when(mUserTracker.getUserId()).thenReturn(mCurrentUserId);
- ExtendedMockito.doReturn(mActivityService).when(ActivityManager::getService);
mContext.getOrCreateTestableResources().addOverride(
com.android.systemui.R.integer.config_face_auth_supported_posture,
@@ -615,9 +609,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
mTestableLooper.processAllMessages();
- verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
- anyInt());
- verify(mFingerprintManager, never()).detectFingerprint(any(), any(), anyInt());
+ verifyFingerprintAuthenticateCall();
+ verifyFingerprintDetectNeverCalled();
}
@Test
@@ -627,24 +620,51 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
mTestableLooper.processAllMessages();
- verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyInt(), anyInt());
- verify(mFingerprintManager, never()).detectFingerprint(any(), any(), anyInt());
+ verifyFingerprintAuthenticateNeverCalled();
+ verifyFingerprintDetectNeverCalled();
}
@Test
public void testOnlyDetectFingerprint_whenFingerprintUnlockNotAllowed() {
- // Clear invocations, since previous setup (e.g. registering BiometricManager callbacks)
- // will trigger updateBiometricListeningState();
- clearInvocations(mFingerprintManager);
- mKeyguardUpdateMonitor.resetBiometricListeningState();
+ givenDetectFingerprintWithClearingFingerprintManagerInvocations();
- when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
- mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
- mTestableLooper.processAllMessages();
+ verifyFingerprintAuthenticateNeverCalled();
+ verifyFingerprintDetectCall();
+ }
- verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), anyInt());
- verify(mFingerprintManager).detectFingerprint(any(), any(), anyInt());
+ @Test
+ public void whenDetectFingerprint_biometricDetectCallback() {
+ ArgumentCaptor<FingerprintManager.FingerprintDetectionCallback> fpDetectCallbackCaptor =
+ ArgumentCaptor.forClass(FingerprintManager.FingerprintDetectionCallback.class);
+
+ givenDetectFingerprintWithClearingFingerprintManagerInvocations();
+ verify(mFingerprintManager).detectFingerprint(
+ any(), fpDetectCallbackCaptor.capture(), any());
+ fpDetectCallbackCaptor.getValue().onFingerprintDetected(0, 0, true);
+
+ // THEN verify keyguardUpdateMonitorCallback receives a detect callback
+ // and NO authenticate callbacks
+ verify(mTestCallback).onBiometricDetected(
+ eq(0), eq(BiometricSourceType.FINGERPRINT), eq(true));
+ verify(mTestCallback, never()).onBiometricAuthenticated(
+ anyInt(), any(), anyBoolean());
+ }
+
+ @Test
+ public void whenDetectFace_biometricDetectCallback() {
+ ArgumentCaptor<FaceManager.FaceDetectionCallback> faceDetectCallbackCaptor =
+ ArgumentCaptor.forClass(FaceManager.FaceDetectionCallback.class);
+
+ givenDetectFace();
+ verify(mFaceManager).detectFace(any(), faceDetectCallbackCaptor.capture(), any());
+ faceDetectCallbackCaptor.getValue().onFaceDetected(0, 0, false);
+
+ // THEN verify keyguardUpdateMonitorCallback receives a detect callback
+ // and NO authenticate callbacks
+ verify(mTestCallback).onBiometricDetected(
+ eq(0), eq(BiometricSourceType.FACE), eq(false));
+ verify(mTestCallback, never()).onBiometricAuthenticated(
+ anyInt(), any(), anyBoolean());
}
@Test
@@ -675,7 +695,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
strongAuthNotRequired();
// WHEN fingerprint is locked out
- fingerprintErrorLockedOut();
+ fingerprintErrorTemporaryLockedOut();
// THEN unlocking with face is not allowed
Assert.assertFalse(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
@@ -698,7 +718,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
strongAuthNotRequired();
// WHEN fingerprint is locked out
- fingerprintErrorLockedOut();
+ fingerprintErrorTemporaryLockedOut();
// THEN unlocking with fingerprint is not allowed
Assert.assertFalse(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
@@ -722,7 +742,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
Assert.assertTrue(mKeyguardUpdateMonitor.getUserHasTrust(getCurrentUser()));
// WHEN fingerprint is locked out
- fingerprintErrorLockedOut();
+ fingerprintErrorTemporaryLockedOut();
// THEN user is NOT considered as "having trust" and bouncer cannot be skipped
Assert.assertFalse(mKeyguardUpdateMonitor.getUserHasTrust(getCurrentUser()));
@@ -732,9 +752,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
@Test
public void testTriesToAuthenticate_whenBouncer() {
setKeyguardBouncerVisibility(true);
-
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
- verify(mFaceManager, never()).hasEnrolledTemplates(anyInt());
+ verifyFaceAuthenticateCall();
}
@Test
@@ -742,8 +760,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.sendPrimaryBouncerChanged(
/* bouncerIsOrWillBeShowing */ true, /* bouncerFullyShown */ false);
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verifyFaceAuthenticateNeverCalled();
}
@Test
@@ -751,7 +768,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
keyguardIsVisible();
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
mTestableLooper.processAllMessages();
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+
+ verifyFaceAuthenticateCall();
verify(mUiEventLogger).logWithInstanceIdAndPosition(
eq(FaceAuthUiEvent.FACE_AUTH_UPDATED_STARTED_WAKING_UP),
eq(0),
@@ -767,8 +785,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
keyguardIsVisible();
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verifyFaceAuthenticateNeverCalled();
}
@Test
@@ -779,17 +796,12 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
mTestableLooper.processAllMessages();
keyguardIsVisible();
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+
+ verifyFaceAuthenticateNeverCalled();
}
@Test
public void nofaceDetect_whenStrongAuthRequiredAndBypassUdfpsSupportedAndFpRunning() {
- // GIVEN mocked keyguardUpdateMonitorCallback
- KeyguardUpdateMonitorCallback keyguardUpdateMonitorCallback =
- mock(KeyguardUpdateMonitorCallback.class);
- mKeyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback);
-
// GIVEN bypass is enabled, face detection is supported
lockscreenBypassIsAllowed();
supportsFaceDetection();
@@ -804,32 +816,21 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
// THEN face detect and authenticate are NOT triggered
- verify(mFaceManager, never()).detectFace(any(), any(), anyInt());
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verifyFaceDetectNeverCalled();
+ verifyFaceAuthenticateNeverCalled();
// THEN biometric help message sent to callback
- verify(keyguardUpdateMonitorCallback).onBiometricHelp(
+ verify(mTestCallback).onBiometricHelp(
eq(BIOMETRIC_HELP_FACE_NOT_AVAILABLE), anyString(), eq(BiometricSourceType.FACE));
}
@Test
public void faceDetect_whenStrongAuthRequiredAndBypass() {
- // GIVEN bypass is enabled, face detection is supported and strong auth is required
- lockscreenBypassIsAllowed();
- supportsFaceDetection();
- strongAuthRequiredEncrypted();
- keyguardIsVisible();
- // fingerprint is NOT running, UDFPS is NOT supported
-
- // WHEN the device wakes up
- mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
- mTestableLooper.processAllMessages();
+ givenDetectFace();
// FACE detect is triggered, not authenticate
- verify(mFaceManager).detectFace(any(), any(), anyInt());
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verifyFaceDetectCall();
+ verifyFaceAuthenticateNeverCalled();
// WHEN bouncer becomes visible
setKeyguardBouncerVisibility(true);
@@ -837,9 +838,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
// THEN face scanning is not run
mKeyguardUpdateMonitor.requestFaceAuth(FaceAuthApiRequestReason.UDFPS_POINTER_DOWN);
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
- verify(mFaceManager, never()).detectFace(any(), any(), anyInt());
+ verifyFaceAuthenticateNeverCalled();
+ verifyFaceDetectNeverCalled();
}
@Test
@@ -854,9 +854,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
// FACE detect and authenticate are NOT triggered
- verify(mFaceManager, never()).detectFace(any(), any(), anyInt());
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verifyFaceDetectNeverCalled();
+ verifyFaceAuthenticateNeverCalled();
}
@Test
@@ -894,7 +893,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.setKeyguardShowing(true, true);
mKeyguardUpdateMonitor.setAssistantVisible(true);
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verifyFaceAuthenticateCall();
}
@Test
@@ -902,12 +901,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.setKeyguardShowing(false, true);
mKeyguardUpdateMonitor.setAssistantVisible(true);
- verify(mFaceManager, never()).authenticate(any(),
- any(),
- any(),
- any(),
- anyInt(),
- anyBoolean());
+ verifyFaceAuthenticateNeverCalled();
}
@Test
@@ -918,15 +912,12 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
// THEN fingerprint shouldn't listen
assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(false)).isFalse();
- verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyInt(), anyInt());
-
+ verifyFingerprintAuthenticateNeverCalled();
// WHEN alternate bouncer is shown
mKeyguardUpdateMonitor.setAlternateBouncerShowing(true);
// THEN make sure FP listening begins
- verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
- anyInt());
+ verifyFingerprintAuthenticateCall();
}
@Test
@@ -938,7 +929,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
KeyguardUpdateMonitor.getCurrentUser(), 0 /* flags */,
new ArrayList<>());
keyguardIsVisible();
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verifyFaceAuthenticateCall();
}
@Test
@@ -946,7 +937,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.setKeyguardShowing(true, true);
mKeyguardUpdateMonitor.setAssistantVisible(true);
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verifyFaceAuthenticateCall();
mTestableLooper.processAllMessages();
clearInvocations(mFaceManager);
@@ -959,12 +950,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.handleKeyguardReset();
assertThat(mKeyguardUpdateMonitor.isFaceDetectionRunning()).isFalse();
- verify(mFaceManager, never()).authenticate(any(),
- any(),
- any(),
- any(),
- anyInt(),
- anyBoolean());
+ verifyFaceAuthenticateNeverCalled();
}
@Test
@@ -974,8 +960,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.onTrustChanged(true /* enabled */, true /* newlyUnlocked */,
KeyguardUpdateMonitor.getCurrentUser(), 0 /* flags */, new ArrayList<>());
keyguardIsVisible();
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verifyFaceAuthenticateNeverCalled();
}
@Test
@@ -987,9 +972,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
keyguardIsVisible();
mTestableLooper.processAllMessages();
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
- verify(mFaceManager, never()).detectFace(any(), any(), anyInt());
+ verifyFaceAuthenticateNeverCalled();
+ verifyFaceDetectNeverCalled();
}
@Test
@@ -998,16 +982,14 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
.onAuthenticationError(FingerprintManager.BIOMETRIC_ERROR_POWER_PRESSED, "");
// THEN doesn't authenticate immediately
- verify(mFingerprintManager, never()).authenticate(any(),
- any(), any(), any(), anyInt(), anyInt(), anyInt());
+ verifyFingerprintAuthenticateNeverCalled();
// WHEN all messages (with delays) are processed
mTestableLooper.moveTimeForward(HAL_POWER_PRESS_TIMEOUT);
mTestableLooper.processAllMessages();
// THEN fingerprint manager attempts to authenticate again
- verify(mFingerprintManager).authenticate(any(),
- any(), any(), any(), anyInt(), anyInt(), anyInt());
+ verifyFingerprintAuthenticateCall();
}
@Test
@@ -1019,8 +1001,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
setKeyguardBouncerVisibility(true);
mTestableLooper.processAllMessages();
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verifyFaceAuthenticateNeverCalled();
}
@Test
@@ -1093,11 +1074,6 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
@Test
public void testBiometricsCleared_whenUserSwitches() throws Exception {
- final IRemoteCallback reply = new IRemoteCallback.Stub() {
- @Override
- public void sendResult(Bundle data) {
- } // do nothing
- };
final BiometricAuthenticated dummyAuthentication =
new BiometricAuthenticated(true /* authenticated */, true /* strong */);
mKeyguardUpdateMonitor.mUserFaceAuthenticated.put(0 /* user */, dummyAuthentication);
@@ -1105,18 +1081,13 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
assertThat(mKeyguardUpdateMonitor.mUserFingerprintAuthenticated.size()).isEqualTo(1);
assertThat(mKeyguardUpdateMonitor.mUserFaceAuthenticated.size()).isEqualTo(1);
- mKeyguardUpdateMonitor.handleUserSwitching(10 /* user */, reply);
+ mKeyguardUpdateMonitor.handleUserSwitching(10 /* user */, new CountDownLatch(0));
assertThat(mKeyguardUpdateMonitor.mUserFingerprintAuthenticated.size()).isEqualTo(0);
assertThat(mKeyguardUpdateMonitor.mUserFaceAuthenticated.size()).isEqualTo(0);
}
@Test
public void testMultiUserJankMonitor_whenUserSwitches() throws Exception {
- final IRemoteCallback reply = new IRemoteCallback.Stub() {
- @Override
- public void sendResult(Bundle data) {
- } // do nothing
- };
mKeyguardUpdateMonitor.handleUserSwitchComplete(10 /* user */);
verify(mInteractionJankMonitor).end(InteractionJankMonitor.CUJ_USER_SWITCH);
verify(mLatencyTracker).onActionEnd(LatencyTracker.ACTION_USER_SWITCH);
@@ -1147,9 +1118,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
keyguardIsVisible();
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
- verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
- anyInt());
+ verifyFaceAuthenticateCall();
+ verifyFingerprintAuthenticateCall();
when(mFingerprintManager.getLockoutModeForUser(eq(FINGERPRINT_SENSOR_ID), eq(newUser)))
.thenReturn(fingerprintLockoutMode);
@@ -1180,8 +1150,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
// Fingerprint should be cancelled on lockout if going to lockout state, else
// restarted if it's not
assertThat(mKeyguardUpdateMonitor.mFingerprintRunningState)
- .isEqualTo(fpLocked
- ? BIOMETRIC_STATE_CANCELLING : BIOMETRIC_STATE_CANCELLING_RESTARTING);
+ .isEqualTo(BIOMETRIC_STATE_CANCELLING_RESTARTING);
}
@Test
@@ -1597,10 +1566,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
public void testFaceDoesNotAuth_afterPinAttempt() {
mTestableLooper.processAllMessages();
mKeyguardUpdateMonitor.setCredentialAttempted();
- verify(mFingerprintManager, never()).authenticate(any(), any(), any(),
- any(), anyInt());
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verifyFaceAuthenticateNeverCalled();
}
@Test
@@ -1643,7 +1609,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
// Fingerprint is locked out.
- fingerprintErrorLockedOut();
+ fingerprintErrorTemporaryLockedOut();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
}
@@ -1975,9 +1941,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
keyguardIsVisible();
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
- verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
- anyInt());
+ verifyFaceAuthenticateCall();
+ verifyFingerprintAuthenticateCall();
mKeyguardUpdateMonitor.onFaceAuthenticated(0, false);
// Make sure keyguard is going away after face auth attempt, and that it calls
@@ -2003,8 +1968,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.dispatchDreamingStopped();
mTestableLooper.processAllMessages();
- verify(mFaceManager, never()).authenticate(
- any(), any(), any(), any(), anyInt(), anyBoolean());
+ verifyFaceAuthenticateNeverCalled();
}
@Test
@@ -2017,15 +1981,14 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
// THEN face auth isn't triggered
- verify(mFaceManager, never()).authenticate(
- any(), any(), any(), any(), anyInt(), anyBoolean());
+ verifyFaceAuthenticateNeverCalled();
// WHEN device wakes up from the power button
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
mTestableLooper.processAllMessages();
// THEN face auth is triggered
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verifyFaceAuthenticateCall();
}
@Test
@@ -2195,7 +2158,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
keyguardIsVisible();
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verifyFaceAuthenticateCall();
verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
anyInt());
@@ -2228,7 +2191,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
keyguardIsVisible();
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verifyFaceAuthenticateCall();
final CancellationSignal faceCancel = spy(mKeyguardUpdateMonitor.mFaceCancelSignal);
mKeyguardUpdateMonitor.mFaceCancelSignal = faceCancel;
@@ -2247,6 +2210,32 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
}
@Test
+ public void testPostureChangeToUnsupported_stopsFaceListeningState() {
+ // GIVEN device is listening for face
+ mKeyguardUpdateMonitor.mConfigFaceAuthSupportedPosture = DEVICE_POSTURE_CLOSED;
+ deviceInPostureStateClosed();
+ mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
+ mTestableLooper.processAllMessages();
+ keyguardIsVisible();
+
+ verifyFaceAuthenticateCall();
+
+ final CancellationSignal faceCancel = spy(mKeyguardUpdateMonitor.mFaceCancelSignal);
+ mKeyguardUpdateMonitor.mFaceCancelSignal = faceCancel;
+ KeyguardUpdateMonitorCallback callback = mock(KeyguardUpdateMonitorCallback.class);
+ mKeyguardUpdateMonitor.registerCallback(callback);
+
+ // WHEN device is opened
+ deviceInPostureStateOpened();
+ mTestableLooper.processAllMessages();
+
+ // THEN face listening is stopped.
+ verify(faceCancel).cancel();
+ verify(callback).onBiometricRunningStateChanged(
+ eq(false), eq(BiometricSourceType.FACE));
+ }
+
+ @Test
public void testShouldListenForFace_withLockedDown_returnsFalse()
throws RemoteException {
keyguardNotGoingAway();
@@ -2499,6 +2488,103 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
eq(false));
}
+ @Test
+ public void detectFingerprint_onTemporaryLockoutReset_authenticateFingerprint() {
+ ArgumentCaptor<FingerprintManager.LockoutResetCallback> fpLockoutResetCallbackCaptor =
+ ArgumentCaptor.forClass(FingerprintManager.LockoutResetCallback.class);
+ verify(mFingerprintManager).addLockoutResetCallback(fpLockoutResetCallbackCaptor.capture());
+
+ // GIVEN device is locked out
+ fingerprintErrorTemporaryLockedOut();
+
+ // GIVEN FP detection is running
+ givenDetectFingerprintWithClearingFingerprintManagerInvocations();
+ verifyFingerprintDetectCall();
+ verifyFingerprintAuthenticateNeverCalled();
+
+ // WHEN temporary lockout resets
+ fpLockoutResetCallbackCaptor.getValue().onLockoutReset(0);
+ mTestableLooper.processAllMessages();
+
+ // THEN fingerprint detect state should cancel & then restart (for authenticate call)
+ assertThat(mKeyguardUpdateMonitor.mFingerprintRunningState)
+ .isEqualTo(BIOMETRIC_STATE_CANCELLING_RESTARTING);
+ }
+
+ @Test
+ public void faceAuthenticateOptions_bouncerAuthenticateReason() {
+ // GIVEN the bouncer is fully visible
+ bouncerFullyVisible();
+
+ // WHEN authenticate is called
+ ArgumentCaptor<FaceAuthenticateOptions> captor =
+ ArgumentCaptor.forClass(FaceAuthenticateOptions.class);
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), captor.capture());
+
+ // THEN the authenticate reason is attributed to the bouncer
+ assertThat(captor.getValue().getAuthenticateReason())
+ .isEqualTo(AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN);
+ }
+
+ @Test
+ public void faceAuthenticateOptions_wakingUpAuthenticateReason_powerButtonWakeReason() {
+ // GIVEN keyguard is visible
+ keyguardIsVisible();
+
+ // WHEN device wakes up from the power button
+ mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
+ mTestableLooper.processAllMessages();
+
+ // THEN face auth is triggered
+ ArgumentCaptor<FaceAuthenticateOptions> captor =
+ ArgumentCaptor.forClass(FaceAuthenticateOptions.class);
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), captor.capture());
+
+ // THEN the authenticate reason is attributed to the waking
+ assertThat(captor.getValue().getAuthenticateReason())
+ .isEqualTo(AUTHENTICATE_REASON_STARTED_WAKING_UP);
+
+ // THEN the wake reason is attributed to the power button
+ assertThat(captor.getValue().getWakeReason())
+ .isEqualTo(PowerManager.WAKE_REASON_POWER_BUTTON);
+ }
+
+ private void verifyFingerprintAuthenticateNeverCalled() {
+ verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), any());
+ verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
+ anyInt(), anyInt());
+ }
+
+ private void verifyFingerprintAuthenticateCall() {
+ verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
+ anyInt());
+ }
+
+ private void verifyFingerprintDetectNeverCalled() {
+ verify(mFingerprintManager, never()).detectFingerprint(any(), any(), any());
+ }
+
+ private void verifyFingerprintDetectCall() {
+ verify(mFingerprintManager).detectFingerprint(any(), any(), any());
+ }
+
+ private void verifyFaceAuthenticateNeverCalled() {
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), any());
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt());
+ }
+
+ private void verifyFaceAuthenticateCall() {
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), any());
+ }
+
+ private void verifyFaceDetectNeverCalled() {
+ verify(mFaceManager, never()).detectFace(any(), any(), any());
+ }
+
+ private void verifyFaceDetectCall() {
+ verify(mFaceManager).detectFace(any(), any(), any());
+ }
+
private void userDeviceLockDown() {
when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
when(mStrongAuthTracker.getStrongAuthForUser(mCurrentUserId))
@@ -2568,7 +2654,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.setSwitchingUser(true);
}
- private void fingerprintErrorLockedOut() {
+ private void fingerprintErrorTemporaryLockedOut() {
mKeyguardUpdateMonitor.mFingerprintAuthenticationCallback
.onAuthenticationError(FINGERPRINT_ERROR_LOCKOUT, "Fingerprint locked out");
}
@@ -2596,8 +2682,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
any(),
mAuthenticationCallbackCaptor.capture(),
any(),
- anyInt(),
- anyBoolean());
+ any());
mAuthenticationCallbackCaptor.getValue()
.onAuthenticationSucceeded(
new FaceManager.AuthenticationResult(null, null, mCurrentUserId, false));
@@ -2708,6 +2793,30 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
receiver.setPendingResult(pendingResult);
}
+ private void givenDetectFingerprintWithClearingFingerprintManagerInvocations() {
+ // Clear invocations, since previous setup (e.g. registering BiometricManager callbacks)
+ // will trigger updateBiometricListeningState();
+ clearInvocations(mFingerprintManager);
+ mKeyguardUpdateMonitor.resetBiometricListeningState();
+
+ when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
+ mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
+ mTestableLooper.processAllMessages();
+ }
+
+ private void givenDetectFace() {
+ // GIVEN bypass is enabled, face detection is supported and strong auth is required
+ lockscreenBypassIsAllowed();
+ supportsFaceDetection();
+ strongAuthRequiredEncrypted();
+ keyguardIsVisible();
+ // fingerprint is NOT running, UDFPS is NOT supported
+
+ // WHEN the device wakes up
+ mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
+ mTestableLooper.processAllMessages();
+ }
+
private Intent putPhoneInfo(Intent intent, Bundle data, Boolean simInited) {
int subscription = simInited
? 1/* mock subid=1 */ : SubscriptionManager.PLACEHOLDER_SUBSCRIPTION_ID_BASE;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/mediator/ScreenOnCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/mediator/ScreenOnCoordinatorTest.kt
index e9a2789bb5c8..9fe32f1e378b 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/mediator/ScreenOnCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/mediator/ScreenOnCoordinatorTest.kt
@@ -32,6 +32,7 @@ import org.mockito.ArgumentCaptor
import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito.`when`
+import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
import java.util.Optional
@@ -83,6 +84,33 @@ class ScreenOnCoordinatorTest : SysuiTestCase() {
}
@Test
+ fun testTasksReady_onScreenTurningOnAndTurnedOnEventsCalledTogether_callsDrawnCallback() {
+ screenOnCoordinator.onScreenTurningOn(runnable)
+ screenOnCoordinator.onScreenTurnedOn()
+
+ onUnfoldOverlayReady()
+ onFoldAodReady()
+ waitHandlerIdle(testHandler)
+
+ // Should be called when both unfold overlay and keyguard drawn ready
+ verify(runnable).run()
+ }
+
+ @Test
+ fun testTasksReady_onScreenTurnedOnAndTurnedOffBeforeCompletion_doesNotCallDrawnCallback() {
+ screenOnCoordinator.onScreenTurningOn(runnable)
+ screenOnCoordinator.onScreenTurnedOn()
+ screenOnCoordinator.onScreenTurnedOff()
+
+ onUnfoldOverlayReady()
+ onFoldAodReady()
+ waitHandlerIdle(testHandler)
+
+ // Should not be called because this screen turning on call is not valid anymore
+ verify(runnable, never()).run()
+ }
+
+ @Test
fun testUnfoldTransitionDisabledDrawnTasksReady_onScreenTurningOn_callsDrawnCallback() {
// Recreate with empty unfoldComponent
screenOnCoordinator = ScreenOnCoordinator(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java
index 47c91911e52a..52a70ee9cce2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java
@@ -201,6 +201,13 @@ public class WindowMagnificationSettingsTest extends SysuiTestCase {
assertThat(magnifierMediumButton.isSelected()).isTrue();
}
+ @Test
+ public void showSettingPanel_focusOnThePanel() {
+ mWindowMagnificationSettings.showSettingPanel();
+
+ assertThat(mSettingView.isFocused()).isTrue();
+ }
+
private <T extends View> T getInternalView(@IdRes int idRes) {
T view = mSettingView.findViewById(idRes);
assertNotNull(view);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/fontscaling/FontScalingDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/accessibility/fontscaling/FontScalingDialogTest.kt
index 777dd4e0b4a3..ca6f42618e2a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/fontscaling/FontScalingDialogTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/fontscaling/FontScalingDialogTest.kt
@@ -19,7 +19,7 @@ import android.os.Handler
import android.provider.Settings
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
-import android.widget.ImageView
+import android.view.ViewGroup
import android.widget.SeekBar
import androidx.test.filters.SmallTest
import com.android.systemui.R
@@ -68,14 +68,14 @@ class FontScalingDialogTest : SysuiTestCase() {
fun progressIsZero_clickIconEnd_seekBarProgressIncreaseOne_fontSizeScaled() {
fontScalingDialog.show()
- val iconEnd: ImageView = fontScalingDialog.findViewById(R.id.icon_end)!!
+ val iconEndFrame: ViewGroup = fontScalingDialog.findViewById(R.id.icon_end_frame)!!
val seekBarWithIconButtonsView: SeekBarWithIconButtonsView =
fontScalingDialog.findViewById(R.id.font_scaling_slider)!!
val seekBar: SeekBar = fontScalingDialog.findViewById(R.id.seekbar)!!
seekBarWithIconButtonsView.setProgress(0)
- iconEnd.performClick()
+ iconEndFrame.performClick()
val currentScale = systemSettings.getFloat(Settings.System.FONT_SCALE, /* def = */ 1.0f)
assertThat(seekBar.getProgress()).isEqualTo(1)
@@ -88,14 +88,14 @@ class FontScalingDialogTest : SysuiTestCase() {
fun progressIsMax_clickIconStart_seekBarProgressDecreaseOne_fontSizeScaled() {
fontScalingDialog.show()
- val iconStart: ImageView = fontScalingDialog.findViewById(R.id.icon_start)!!
+ val iconStartFrame: ViewGroup = fontScalingDialog.findViewById(R.id.icon_start_frame)!!
val seekBarWithIconButtonsView: SeekBarWithIconButtonsView =
fontScalingDialog.findViewById(R.id.font_scaling_slider)!!
val seekBar: SeekBar = fontScalingDialog.findViewById(R.id.seekbar)!!
seekBarWithIconButtonsView.setProgress(fontSizeValueArray.size - 1)
- iconStart.performClick()
+ iconStartFrame.performClick()
val currentScale = systemSettings.getFloat(Settings.System.FONT_SCALE, /* def = */ 1.0f)
assertThat(seekBar.getProgress()).isEqualTo(fontSizeValueArray.size - 2)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt
index bce98cf116d4..05748382534f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt
@@ -15,27 +15,49 @@
*/
package com.android.systemui.biometrics
+import android.content.Context
import android.hardware.biometrics.BiometricAuthenticator
+import android.hardware.biometrics.SensorLocationInternal
+import android.hardware.biometrics.SensorProperties
+import android.hardware.display.DisplayManagerGlobal
+import android.hardware.fingerprint.FingerprintManager
+import android.hardware.fingerprint.FingerprintSensorProperties
+import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
import android.os.Bundle
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.testing.TestableLooper.RunWithLooper
+import android.view.Display
+import android.view.DisplayAdjustments
+import android.view.DisplayInfo
+import android.view.Surface
import android.view.View
+import android.view.ViewGroup
import androidx.test.filters.SmallTest
+import com.airbnb.lottie.LottieAnimationView
import com.android.systemui.R
+import com.android.systemui.biometrics.AuthBiometricView.STATE_AUTHENTICATING_ANIMATING_IN
import com.android.systemui.SysuiTestCase
+import com.android.systemui.SysuiTestableContext
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers
import org.mockito.ArgumentMatchers.eq
import org.mockito.Mock
+import org.mockito.Mockito.mock
import org.mockito.Mockito.never
+import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.junit.MockitoJUnit
+import org.mockito.Mockito.`when` as whenEver
+
+private const val DISPLAY_ID = 2
+private const val SENSOR_ID = 1
@RunWith(AndroidTestingRunner::class)
@RunWithLooper(setAsMainLooper = true)
@@ -50,9 +72,22 @@ class AuthBiometricFingerprintViewTest : SysuiTestCase() {
private lateinit var callback: AuthBiometricView.Callback
@Mock
+ private lateinit var fingerprintManager: FingerprintManager
+
+ @Mock
+ private lateinit var iconView: LottieAnimationView
+
+ @Mock
+ private lateinit var iconViewOverlay: LottieAnimationView
+
+ @Mock
+ private lateinit var iconLayoutParamSize: Pair<Int, Int>
+
+ @Mock
private lateinit var panelController: AuthPanelController
private lateinit var biometricView: AuthBiometricView
+ private lateinit var iconController: AuthBiometricFingerprintIconController
private fun createView(allowDeviceCredential: Boolean = false): AuthBiometricFingerprintView {
val view: AuthBiometricFingerprintView =
@@ -277,5 +312,186 @@ class AuthBiometricFingerprintViewTest : SysuiTestCase() {
verify(callback).onAction(AuthBiometricView.Callback.ACTION_USE_DEVICE_CREDENTIAL)
}
+ private fun testWithSfpsDisplay(
+ isReverseDefaultRotation: Boolean = false,
+ inRearDisplayMode: Boolean = false,
+ isFolded: Boolean = false,
+ initInfo: DisplayInfo.() -> Unit = {},
+ block: () -> Unit
+ ) {
+ val displayInfo = DisplayInfo()
+ displayInfo.initInfo()
+
+ val dmGlobal = mock(DisplayManagerGlobal::class.java)
+ val display = Display(dmGlobal, DISPLAY_ID, displayInfo,
+ DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS)
+
+ whenEver(dmGlobal.getDisplayInfo(eq(DISPLAY_ID))).thenReturn(displayInfo)
+
+ val iconControllerContext = context.createDisplayContext(display) as SysuiTestableContext
+ iconControllerContext.orCreateTestableResources.addOverride(
+ com.android.internal.R.bool.config_reverseDefaultRotation,
+ isReverseDefaultRotation
+ )
+
+ val rearDisplayDeviceStates = if (inRearDisplayMode) intArrayOf(3) else intArrayOf()
+ iconControllerContext.orCreateTestableResources.addOverride(
+ com.android.internal.R.array.config_rearDisplayDeviceStates,
+ rearDisplayDeviceStates
+ )
+
+ val layoutParams = mock(ViewGroup.LayoutParams::class.java)
+ whenEver(iconView.layoutParams).thenReturn(layoutParams)
+ whenEver(iconViewOverlay.layoutParams).thenReturn(layoutParams)
+
+ var locations = listOf(SensorLocationInternal("", 2500, 0, 0))
+ whenEver(fingerprintManager.sensorPropertiesInternal)
+ .thenReturn(
+ listOf(
+ FingerprintSensorPropertiesInternal(
+ SENSOR_ID,
+ SensorProperties.STRENGTH_STRONG,
+ 5 /* maxEnrollmentsPerUser */,
+ listOf() /* componentInfo */,
+ FingerprintSensorProperties.TYPE_POWER_BUTTON,
+ true /* halControlsIllumination */,
+ true /* resetLockoutRequiresHardwareAuthToken */,
+ locations
+ )
+ )
+ )
+ iconControllerContext.addMockSystemService(Context.FINGERPRINT_SERVICE, fingerprintManager)
+
+ iconController = AuthBiometricFingerprintIconController(
+ iconControllerContext,
+ iconView,
+ iconViewOverlay
+ )
+ iconController.onFoldUpdated(isFolded)
+
+ biometricView.mIconController = iconController
+ block()
+ }
+
+ @Test
+ fun sfpsRearDisplay_showsCorrectAnimationAssetsAcrossRotations() {
+ testWithSfpsDisplay(
+ isReverseDefaultRotation = false,
+ inRearDisplayMode = true,
+ isFolded = false,
+ { rotation = Surface.ROTATION_0 }
+ ) { biometricView.updateState(STATE_AUTHENTICATING_ANIMATING_IN) }
+ testWithSfpsDisplay(
+ isReverseDefaultRotation = false,
+ inRearDisplayMode = true,
+ isFolded = false,
+ { rotation = Surface.ROTATION_90 }
+ ) { biometricView.updateState(STATE_AUTHENTICATING_ANIMATING_IN) }
+ testWithSfpsDisplay(
+ isReverseDefaultRotation = false,
+ inRearDisplayMode = true,
+ isFolded = false,
+ { rotation = Surface.ROTATION_180 }
+ ) { biometricView.updateState(STATE_AUTHENTICATING_ANIMATING_IN) }
+ testWithSfpsDisplay(
+ isReverseDefaultRotation = false,
+ inRearDisplayMode = true,
+ isFolded = false,
+ { rotation = Surface.ROTATION_270 }
+ ) { biometricView.updateState(STATE_AUTHENTICATING_ANIMATING_IN) }
+ val expectedLottieAssetOrder: List<Int> = listOf(
+ R.raw.biometricprompt_rear_landscape_base,
+ R.raw.biometricprompt_rear_portrait_reverse_base,
+ R.raw.biometricprompt_rear_landscape_base,
+ R.raw.biometricprompt_rear_portrait_base,
+ )
+
+ val lottieAssetCaptor: ArgumentCaptor<Int> = ArgumentCaptor.forClass(Int::class.java)
+ verify(iconView, times(4)).setAnimation(lottieAssetCaptor.capture())
+ val observedLottieAssetOrder: List<Int> = lottieAssetCaptor.getAllValues()
+ assertThat(observedLottieAssetOrder).containsExactlyElementsIn(expectedLottieAssetOrder)
+ .inOrder()
+ }
+
+ @Test
+ fun sfpsDefaultDisplayFolded_showsAnimationsAssetsCorrectlyAcrossRotations() {
+ testWithSfpsDisplay(
+ isReverseDefaultRotation = false,
+ inRearDisplayMode = false,
+ isFolded = true,
+ { rotation = Surface.ROTATION_0 }
+ ) { biometricView.updateState(STATE_AUTHENTICATING_ANIMATING_IN) }
+ testWithSfpsDisplay(
+ isReverseDefaultRotation = false,
+ inRearDisplayMode = false,
+ isFolded = true,
+ { rotation = Surface.ROTATION_90 }
+ ) { biometricView.updateState(STATE_AUTHENTICATING_ANIMATING_IN); }
+ testWithSfpsDisplay(
+ isReverseDefaultRotation = false,
+ inRearDisplayMode = false,
+ isFolded = true,
+ { rotation = Surface.ROTATION_180 }
+ ) { biometricView.updateState(STATE_AUTHENTICATING_ANIMATING_IN); }
+ testWithSfpsDisplay(
+ isReverseDefaultRotation = false,
+ inRearDisplayMode = false,
+ isFolded = true,
+ { rotation = Surface.ROTATION_270 }
+ ) { biometricView.updateState(STATE_AUTHENTICATING_ANIMATING_IN); }
+ val expectedLottieAssetOrder: List<Int> = listOf(
+ R.raw.biometricprompt_folded_base_default,
+ R.raw.biometricprompt_folded_base_topleft,
+ R.raw.biometricprompt_folded_base_default,
+ R.raw.biometricprompt_folded_base_bottomright,
+ )
+
+ val lottieAssetCaptor: ArgumentCaptor<Int> = ArgumentCaptor.forClass(Int::class.java)
+ verify(iconView, times(4)).setAnimation(lottieAssetCaptor.capture())
+ val observedLottieAssetOrder: List<Int> = lottieAssetCaptor.getAllValues()
+ assertThat(observedLottieAssetOrder).containsExactlyElementsIn(expectedLottieAssetOrder)
+ .inOrder()
+ }
+
+ @Test
+ fun sfpsDefaultDisplayUnfolded_showsAnimationsAssetsCorrectlyAcrossRotations() {
+ testWithSfpsDisplay(
+ isReverseDefaultRotation = false,
+ inRearDisplayMode = false,
+ isFolded = false,
+ { rotation = Surface.ROTATION_0 }
+ ) { biometricView.updateState(STATE_AUTHENTICATING_ANIMATING_IN) }
+ testWithSfpsDisplay(
+ isReverseDefaultRotation = false,
+ inRearDisplayMode = false,
+ isFolded = false,
+ { rotation = Surface.ROTATION_90 }
+ ) { biometricView.updateState(STATE_AUTHENTICATING_ANIMATING_IN) }
+ testWithSfpsDisplay(
+ isReverseDefaultRotation = false,
+ inRearDisplayMode = false,
+ isFolded = false,
+ { rotation = Surface.ROTATION_180 }
+ ) { biometricView.updateState(STATE_AUTHENTICATING_ANIMATING_IN) }
+ testWithSfpsDisplay(
+ isReverseDefaultRotation = false,
+ inRearDisplayMode = false,
+ isFolded = false,
+ { rotation = Surface.ROTATION_270 }
+ ) { biometricView.updateState(STATE_AUTHENTICATING_ANIMATING_IN) }
+ val expectedLottieAssetOrder: List<Int> = listOf(
+ R.raw.biometricprompt_landscape_base,
+ R.raw.biometricprompt_portrait_base_topleft,
+ R.raw.biometricprompt_landscape_base,
+ R.raw.biometricprompt_portrait_base_bottomright,
+ )
+
+ val lottieAssetCaptor: ArgumentCaptor<Int> = ArgumentCaptor.forClass(Int::class.java)
+ verify(iconView, times(4)).setAnimation(lottieAssetCaptor.capture())
+ val observedLottieAssetOrder: List<Int> = lottieAssetCaptor.getAllValues()
+ assertThat(observedLottieAssetOrder).containsExactlyElementsIn(expectedLottieAssetOrder)
+ .inOrder()
+ }
+
override fun waitForIdleSync() = TestableLooper.get(this).processAllMessages()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
index 612e55732bc1..3ec49b263c54 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
@@ -63,6 +63,7 @@ import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintA
import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.recents.OverviewProxyService
+import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
@@ -97,6 +98,7 @@ class SideFpsControllerTest : SysuiTestCase() {
@JvmField @Rule var rule = MockitoJUnit.rule()
+ @Mock lateinit var keyguardStateController: KeyguardStateController
@Mock lateinit var layoutInflater: LayoutInflater
@Mock lateinit var fingerprintManager: FingerprintManager
@Mock lateinit var windowManager: WindowManager
@@ -136,6 +138,7 @@ class SideFpsControllerTest : SysuiTestCase() {
keyguardBouncerRepository = FakeKeyguardBouncerRepository()
alternateBouncerInteractor =
AlternateBouncerInteractor(
+ keyguardStateController,
keyguardBouncerRepository,
FakeBiometricSettingsRepository(),
FakeDeviceEntryFingerprintAuthRepository(),
@@ -169,6 +172,7 @@ class SideFpsControllerTest : SysuiTestCase() {
isReverseDefaultRotation: Boolean = false,
initInfo: DisplayInfo.() -> Unit = {},
windowInsets: WindowInsets = insetsForSmallNavbar(),
+ inRearDisplayMode: Boolean = false,
block: () -> Unit
) {
this.deviceConfig = deviceConfig
@@ -229,6 +233,12 @@ class SideFpsControllerTest : SysuiTestCase() {
isReverseDefaultRotation
)
+ val rearDisplayDeviceStates = if (inRearDisplayMode) intArrayOf(3) else intArrayOf()
+ sideFpsControllerContext.orCreateTestableResources.addOverride(
+ com.android.internal.R.array.config_rearDisplayDeviceStates,
+ rearDisplayDeviceStates
+ )
+
sideFpsController =
SideFpsController(
sideFpsControllerContext,
@@ -344,7 +354,9 @@ class SideFpsControllerTest : SysuiTestCase() {
deviceConfig = DeviceConfig.X_ALIGNED,
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_0 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_90() =
@@ -352,7 +364,9 @@ class SideFpsControllerTest : SysuiTestCase() {
deviceConfig = DeviceConfig.X_ALIGNED,
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_90 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_180() =
@@ -360,7 +374,9 @@ class SideFpsControllerTest : SysuiTestCase() {
deviceConfig = DeviceConfig.X_ALIGNED,
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_180 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarCollapsedDownForXAlignedSensor_180() =
@@ -369,7 +385,9 @@ class SideFpsControllerTest : SysuiTestCase() {
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_180 },
windowInsets = insetsForSmallNavbar()
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun hidesSfpsIndicatorWhenOccludingTaskbarForXAlignedSensor_180() =
@@ -378,7 +396,9 @@ class SideFpsControllerTest : SysuiTestCase() {
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_180 },
windowInsets = insetsForLargeNavbar()
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_270() =
@@ -386,7 +406,9 @@ class SideFpsControllerTest : SysuiTestCase() {
deviceConfig = DeviceConfig.X_ALIGNED,
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_270 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_InReverseDefaultRotation_0() =
@@ -394,7 +416,9 @@ class SideFpsControllerTest : SysuiTestCase() {
deviceConfig = DeviceConfig.X_ALIGNED,
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_0 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_InReverseDefaultRotation_90() =
@@ -402,7 +426,9 @@ class SideFpsControllerTest : SysuiTestCase() {
deviceConfig = DeviceConfig.X_ALIGNED,
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_90 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarCollapsedDownForXAlignedSensor_InReverseDefaultRotation_90() =
@@ -411,7 +437,9 @@ class SideFpsControllerTest : SysuiTestCase() {
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_90 },
windowInsets = insetsForSmallNavbar()
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun hidesSfpsIndicatorWhenOccludingTaskbarForXAlignedSensor_InReverseDefaultRotation_90() =
@@ -420,7 +448,9 @@ class SideFpsControllerTest : SysuiTestCase() {
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_90 },
windowInsets = insetsForLargeNavbar()
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_InReverseDefaultRotation_180() =
@@ -428,7 +458,9 @@ class SideFpsControllerTest : SysuiTestCase() {
deviceConfig = DeviceConfig.X_ALIGNED,
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_180 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_InReverseDefaultRotation_270() =
@@ -436,7 +468,9 @@ class SideFpsControllerTest : SysuiTestCase() {
deviceConfig = DeviceConfig.X_ALIGNED,
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_270 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_0() =
@@ -444,7 +478,9 @@ class SideFpsControllerTest : SysuiTestCase() {
deviceConfig = DeviceConfig.Y_ALIGNED,
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_0 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_90() =
@@ -452,7 +488,9 @@ class SideFpsControllerTest : SysuiTestCase() {
deviceConfig = DeviceConfig.Y_ALIGNED,
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_90 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_180() =
@@ -470,7 +508,9 @@ class SideFpsControllerTest : SysuiTestCase() {
deviceConfig = DeviceConfig.Y_ALIGNED,
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_270 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarCollapsedDownForYAlignedSensor_270() =
@@ -479,7 +519,9 @@ class SideFpsControllerTest : SysuiTestCase() {
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_270 },
windowInsets = insetsForSmallNavbar()
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun hidesSfpsIndicatorWhenOccludingTaskbarForYAlignedSensor_270() =
@@ -488,7 +530,9 @@ class SideFpsControllerTest : SysuiTestCase() {
isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_270 },
windowInsets = insetsForLargeNavbar()
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_InReverseDefaultRotation_0() =
@@ -496,7 +540,9 @@ class SideFpsControllerTest : SysuiTestCase() {
deviceConfig = DeviceConfig.Y_ALIGNED,
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_0 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_InReverseDefaultRotation_90() =
@@ -514,7 +560,9 @@ class SideFpsControllerTest : SysuiTestCase() {
deviceConfig = DeviceConfig.Y_ALIGNED,
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_180 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarCollapsedDownForYAlignedSensor_InReverseDefaultRotation_180() =
@@ -523,7 +571,9 @@ class SideFpsControllerTest : SysuiTestCase() {
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_180 },
windowInsets = insetsForSmallNavbar()
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
@Test
fun hidesSfpsIndicatorWhenOccludingTaskbarForYAlignedSensor_InReverseDefaultRotation_180() =
@@ -532,7 +582,9 @@ class SideFpsControllerTest : SysuiTestCase() {
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_180 },
windowInsets = insetsForLargeNavbar()
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false)
+ }
@Test
fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_InReverseDefaultRotation_270() =
@@ -540,12 +592,66 @@ class SideFpsControllerTest : SysuiTestCase() {
deviceConfig = DeviceConfig.Y_ALIGNED,
isReverseDefaultRotation = true,
{ rotation = Surface.ROTATION_270 }
- ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
+
+ @Test
+ fun verifiesSfpsIndicatorNotAddedInRearDisplayMode_0() =
+ testWithDisplay(
+ deviceConfig = DeviceConfig.Y_ALIGNED,
+ isReverseDefaultRotation = false,
+ { rotation = Surface.ROTATION_0 },
+ inRearDisplayMode = true,
+ ) {
+ verifySfpsIndicator_notAdded_InRearDisplayMode()
+ }
+
+ @Test
+ fun verifiesSfpsIndicatorNotAddedInRearDisplayMode_90() =
+ testWithDisplay(
+ deviceConfig = DeviceConfig.Y_ALIGNED,
+ isReverseDefaultRotation = false,
+ { rotation = Surface.ROTATION_90 },
+ inRearDisplayMode = true,
+ ) {
+ verifySfpsIndicator_notAdded_InRearDisplayMode()
+ }
+
+ @Test
+ fun verifiesSfpsIndicatorNotAddedInRearDisplayMode_180() =
+ testWithDisplay(
+ deviceConfig = DeviceConfig.Y_ALIGNED,
+ isReverseDefaultRotation = false,
+ { rotation = Surface.ROTATION_180 },
+ inRearDisplayMode = true,
+ ) {
+ verifySfpsIndicator_notAdded_InRearDisplayMode()
+ }
+
+ @Test
+ fun verifiesSfpsIndicatorNotAddedInRearDisplayMode_270() =
+ testWithDisplay(
+ deviceConfig = DeviceConfig.Y_ALIGNED,
+ isReverseDefaultRotation = false,
+ { rotation = Surface.ROTATION_270 },
+ inRearDisplayMode = true,
+ ) {
+ verifySfpsIndicator_notAdded_InRearDisplayMode()
+ }
private fun verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible: Boolean) {
sideFpsController.overlayOffsets = sensorLocation
}
+ private fun verifySfpsIndicator_notAdded_InRearDisplayMode() {
+ sideFpsController.overlayOffsets = sensorLocation
+ overlayController.show(SENSOR_ID, REASON_UNKNOWN)
+ executor.runAllReady()
+
+ verify(windowManager, never()).addView(any(), any())
+ }
+
fun alternateBouncerVisibility_showAndHideSideFpsUI() = testWithDisplay {
// WHEN alternate bouncer is visible
keyguardBouncerRepository.setAlternateVisible(true)
@@ -582,7 +688,7 @@ class SideFpsControllerTest : SysuiTestCase() {
* in other rotations have been omitted.
*/
@Test
- fun verifiesIndicatorPlacementForXAlignedSensor_0() {
+ fun verifiesIndicatorPlacementForXAlignedSensor_0() =
testWithDisplay(
deviceConfig = DeviceConfig.X_ALIGNED,
isReverseDefaultRotation = false,
@@ -599,7 +705,6 @@ class SideFpsControllerTest : SysuiTestCase() {
assertThat(overlayViewParamsCaptor.value.x).isEqualTo(sensorLocation.sensorLocationX)
assertThat(overlayViewParamsCaptor.value.y).isEqualTo(0)
}
- }
/**
* {@link SideFpsController#updateOverlayParams} calculates indicator placement for ROTATION_270
@@ -608,7 +713,7 @@ class SideFpsControllerTest : SysuiTestCase() {
* correctly, tests for indicator placement in other rotations have been omitted.
*/
@Test
- fun verifiesIndicatorPlacementForXAlignedSensor_InReverseDefaultRotation_270() {
+ fun verifiesIndicatorPlacementForXAlignedSensor_InReverseDefaultRotation_270() =
testWithDisplay(
deviceConfig = DeviceConfig.X_ALIGNED,
isReverseDefaultRotation = true,
@@ -625,7 +730,6 @@ class SideFpsControllerTest : SysuiTestCase() {
assertThat(overlayViewParamsCaptor.value.x).isEqualTo(sensorLocation.sensorLocationX)
assertThat(overlayViewParamsCaptor.value.y).isEqualTo(0)
}
- }
/**
* {@link SideFpsController#updateOverlayParams} calculates indicator placement for ROTATION_0,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt
index 54c9d392ad1c..86fb279d4ed6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt
@@ -37,6 +37,7 @@ import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.time.FakeSystemClock
import com.android.systemui.util.time.SystemClock
import kotlinx.coroutines.Dispatchers
@@ -92,6 +93,7 @@ class UdfpsKeyguardViewControllerWithCoroutinesTest : UdfpsKeyguardViewControlle
)
mAlternateBouncerInteractor =
AlternateBouncerInteractor(
+ mock(KeyguardStateController::class.java),
keyguardBouncerRepository,
mock(BiometricSettingsRepository::class.java),
mock(DeviceEntryFingerprintAuthRepository::class.java),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/BroadcastDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/BroadcastDialogTest.java
index a61cecbabf30..35039026fe9e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/BroadcastDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/BroadcastDialogTest.java
@@ -20,14 +20,14 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
-import androidx.test.filters.SmallTest;
-
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
+import androidx.test.filters.SmallTest;
+
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
@@ -44,18 +44,21 @@ import org.mockito.MockitoAnnotations;
@TestableLooper.RunWithLooper(setAsMainLooper = true)
public class BroadcastDialogTest extends SysuiTestCase {
- private static final String SWITCH_APP = "Music";
+ private static final String CURRENT_BROADCAST_APP = "Music";
+ private static final String SWITCH_APP = "Files by Google";
private static final String TEST_PACKAGE = "com.google.android.apps.nbu.files";
private BroadcastDialog mBroadcastDialog;
private View mDialogView;
+ private TextView mTitle;
private TextView mSubTitle;
+ private Button mSwitchBroadcastAppButton;
private Button mChangeOutputButton;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mBroadcastDialog = new BroadcastDialog(mContext, mock(MediaOutputDialogFactory.class),
- SWITCH_APP, TEST_PACKAGE, mock(UiEventLogger.class));
+ CURRENT_BROADCAST_APP, TEST_PACKAGE, mock(UiEventLogger.class));
mBroadcastDialog.show();
mDialogView = mBroadcastDialog.mDialogView;
}
@@ -66,7 +69,15 @@ public class BroadcastDialogTest extends SysuiTestCase {
}
@Test
- public void onCreate_withCurrentApp_checkSwitchAppContent() {
+ public void onCreate_withCurrentApp_titleIsCurrentAppName() {
+ mTitle = mDialogView.requireViewById(R.id.dialog_title);
+
+ assertThat(mTitle.getText().toString()).isEqualTo(mContext.getString(
+ R.string.bt_le_audio_broadcast_dialog_title, CURRENT_BROADCAST_APP));
+ }
+
+ @Test
+ public void onCreate_withCurrentApp_subTitleIsSwitchAppName() {
mSubTitle = mDialogView.requireViewById(R.id.dialog_subtitle);
assertThat(mSubTitle.getText()).isEqualTo(
@@ -74,6 +85,14 @@ public class BroadcastDialogTest extends SysuiTestCase {
}
@Test
+ public void onCreate_withCurrentApp_switchBtnIsSwitchAppName() {
+ mSwitchBroadcastAppButton = mDialogView.requireViewById(R.id.switch_broadcast);
+
+ assertThat(mSwitchBroadcastAppButton.getText().toString()).isEqualTo(
+ mContext.getString(R.string.bt_le_audio_broadcast_dialog_switch_app, SWITCH_APP));
+ }
+
+ @Test
public void onClick_withChangeOutput_dismissBroadcastDialog() {
mChangeOutputButton = mDialogView.requireViewById(R.id.change_output);
mChangeOutputButton.performClick();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsViewTest.java
index 2ed03465c6f0..eafe727ee7dc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsViewTest.java
@@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.SeekBar;
@@ -42,6 +43,8 @@ public class SeekBarWithIconButtonsViewTest extends SysuiTestCase {
private ImageView mIconStart;
private ImageView mIconEnd;
+ private ViewGroup mIconStartFrame;
+ private ViewGroup mIconEndFrame;
private SeekBar mSeekbar;
private SeekBarWithIconButtonsView mIconDiscreteSliderLinearLayout;
@@ -50,6 +53,8 @@ public class SeekBarWithIconButtonsViewTest extends SysuiTestCase {
mIconDiscreteSliderLinearLayout = new SeekBarWithIconButtonsView(mContext);
mIconStart = mIconDiscreteSliderLinearLayout.findViewById(R.id.icon_start);
mIconEnd = mIconDiscreteSliderLinearLayout.findViewById(R.id.icon_end);
+ mIconStartFrame = mIconDiscreteSliderLinearLayout.findViewById(R.id.icon_start_frame);
+ mIconEndFrame = mIconDiscreteSliderLinearLayout.findViewById(R.id.icon_end_frame);
mSeekbar = mIconDiscreteSliderLinearLayout.findViewById(R.id.seekbar);
}
@@ -59,6 +64,8 @@ public class SeekBarWithIconButtonsViewTest extends SysuiTestCase {
assertThat(mIconStart.isEnabled()).isFalse();
assertThat(mIconEnd.isEnabled()).isTrue();
+ assertThat(mIconStartFrame.isEnabled()).isFalse();
+ assertThat(mIconEndFrame.isEnabled()).isTrue();
}
@Test
@@ -67,6 +74,8 @@ public class SeekBarWithIconButtonsViewTest extends SysuiTestCase {
assertThat(mIconEnd.isEnabled()).isFalse();
assertThat(mIconStart.isEnabled()).isTrue();
+ assertThat(mIconEndFrame.isEnabled()).isFalse();
+ assertThat(mIconStartFrame.isEnabled()).isTrue();
}
@Test
@@ -77,12 +86,15 @@ public class SeekBarWithIconButtonsViewTest extends SysuiTestCase {
assertThat(mIconStart.isEnabled()).isTrue();
assertThat(mIconEnd.isEnabled()).isTrue();
+ assertThat(mIconStartFrame.isEnabled()).isTrue();
+ assertThat(mIconEndFrame.isEnabled()).isTrue();
}
@Test
public void clickIconEnd_currentProgressIsOneToMax_reachesMax() {
mIconDiscreteSliderLinearLayout.setProgress(mSeekbar.getMax() - 1);
- mIconEnd.performClick();
+
+ mIconEndFrame.performClick();
assertThat(mSeekbar.getProgress()).isEqualTo(mSeekbar.getMax());
}
@@ -90,7 +102,8 @@ public class SeekBarWithIconButtonsViewTest extends SysuiTestCase {
@Test
public void clickIconStart_currentProgressIsOne_reachesZero() {
mIconDiscreteSliderLinearLayout.setProgress(1);
- mIconStart.performClick();
+
+ mIconStartFrame.performClick();
assertThat(mSeekbar.getProgress()).isEqualTo(0);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
index e35b2a384bd0..28e80057a672 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
@@ -39,11 +39,9 @@ import com.android.systemui.dump.DumpManager
import com.android.systemui.settings.UserFileManager
import com.android.systemui.settings.UserTracker
import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
-import java.io.File
-import java.util.Optional
-import java.util.function.Consumer
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
@@ -58,7 +56,9 @@ import org.mockito.ArgumentMatchers.anyString
import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito
+import org.mockito.Mockito.`when`
import org.mockito.Mockito.anyInt
+import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.inOrder
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
@@ -66,9 +66,10 @@ import org.mockito.Mockito.reset
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions
-import org.mockito.Mockito.`when`
-import org.mockito.Mockito.clearInvocations
import org.mockito.MockitoAnnotations
+import java.io.File
+import java.util.*
+import java.util.function.Consumer
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -146,6 +147,7 @@ class ControlsControllerImplTest : SysuiTestCase() {
fun setUp() {
MockitoAnnotations.initMocks(this)
+ whenever(authorizedPanelsRepository.getAuthorizedPanels()).thenReturn(setOf())
`when`(userTracker.userHandle).thenReturn(UserHandle.of(user))
delayableExecutor = FakeExecutor(FakeSystemClock())
@@ -945,6 +947,28 @@ class ControlsControllerImplTest : SysuiTestCase() {
controller.bindComponentForPanel(TEST_COMPONENT)
verify(bindingController).bindServiceForPanel(TEST_COMPONENT)
}
+
+ @Test
+ fun testRemoveFavoriteRemovesFavorite() {
+ val componentName = ComponentName(context, "test.Cls")
+ controller.addFavorite(
+ componentName,
+ "test structure",
+ ControlInfo(
+ controlId = "testId",
+ controlTitle = "Test Control",
+ controlSubtitle = "test control subtitle",
+ deviceType = DeviceTypes.TYPE_LIGHT,
+ ),
+ )
+
+ controller.removeFavorites(componentName)
+ delayableExecutor.runAllReady()
+
+ verify(authorizedPanelsRepository)
+ .removeAuthorizedPanels(eq(setOf(componentName.packageName)))
+ assertThat(controller.getFavorites()).isEmpty()
+ }
}
private class DidRunRunnable() : Runnable {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImplTest.kt
index b91a3fd4b28c..7ac1953ee495 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImplTest.kt
@@ -115,6 +115,18 @@ class AuthorizedPanelsRepositoryImplTest : SysuiTestCase() {
assertThat(sharedPrefs.getStringSet(KEY, null)).containsExactly(TEST_PACKAGE)
}
+ @Test
+ fun testRemoveAuthorizedPackageRemovesIt() {
+ val sharedPrefs = FakeSharedPreferences()
+ val fileManager = FakeUserFileManager(mapOf(0 to sharedPrefs))
+ val repository = createRepository(fileManager)
+ repository.addAuthorizedPanels(setOf(TEST_PACKAGE))
+
+ repository.removeAuthorizedPanels(setOf(TEST_PACKAGE))
+
+ assertThat(sharedPrefs.getStringSet(KEY, null)).isEmpty()
+ }
+
private fun createRepository(userFileManager: UserFileManager): AuthorizedPanelsRepositoryImpl {
return AuthorizedPanelsRepositoryImpl(mContext, userFileManager, userTracker)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/settings/ControlsSettingsDialogManagerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/settings/ControlsSettingsDialogManagerImplTest.kt
index 0c9986d82447..5a613aa9225e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/settings/ControlsSettingsDialogManagerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/settings/ControlsSettingsDialogManagerImplTest.kt
@@ -104,7 +104,9 @@ class ControlsSettingsDialogManagerImplTest : SysuiTestCase() {
controlsSettingsRepository,
userTracker,
activityStarter
- ) { context, _ -> TestableAlertDialog(context).also { dialog = it } }
+ ) { context, _ ->
+ TestableAlertDialog(context).also { dialog = it }
+ }
}
@After
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsDialogsFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsDialogsFactoryTest.kt
new file mode 100644
index 000000000000..1e8cd4117688
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsDialogsFactoryTest.kt
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2023 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.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.FakeSystemUIDialogController
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.eq
+import org.mockito.Mockito.verify
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class ControlsDialogsFactoryTest : SysuiTestCase() {
+
+ private companion object {
+ const val APP_NAME = "Test App"
+ }
+
+ private val fakeDialogController = FakeSystemUIDialogController()
+
+ private lateinit var underTest: ControlsDialogsFactory
+
+ @Before
+ fun setup() {
+ underTest = ControlsDialogsFactory { fakeDialogController.dialog }
+ }
+
+ @Test
+ fun testCreatesRemoveAppDialog() {
+ val dialog = underTest.createRemoveAppDialog(context, APP_NAME) {}
+
+ verify(dialog)
+ .setTitle(
+ eq(context.getString(R.string.controls_panel_remove_app_authorization, APP_NAME))
+ )
+ verify(dialog).setCanceledOnTouchOutside(eq(true))
+ }
+
+ @Test
+ fun testPositiveClickRemoveAppDialogWorks() {
+ var dialogResult: Boolean? = null
+ underTest.createRemoveAppDialog(context, APP_NAME) { dialogResult = it }
+
+ fakeDialogController.clickPositive()
+
+ assertThat(dialogResult).isTrue()
+ }
+
+ @Test
+ fun testNeutralClickRemoveAppDialogWorks() {
+ var dialogResult: Boolean? = null
+ underTest.createRemoveAppDialog(context, APP_NAME) { dialogResult = it }
+
+ fakeDialogController.clickNeutral()
+
+ assertThat(dialogResult).isFalse()
+ }
+
+ @Test
+ fun testCancelRemoveAppDialogWorks() {
+ var dialogResult: Boolean? = null
+ underTest.createRemoveAppDialog(context, APP_NAME) { dialogResult = it }
+
+ fakeDialogController.cancel()
+
+ assertThat(dialogResult).isFalse()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt
index aa90e2a45f10..23faa99c0b9d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt
@@ -52,6 +52,7 @@ import com.android.systemui.shade.ShadeController
import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.FakeSharedPreferences
+import com.android.systemui.util.FakeSystemUIDialogController
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.argumentCaptor
@@ -63,21 +64,20 @@ import com.android.systemui.util.time.FakeSystemClock
import com.android.wm.shell.TaskView
import com.android.wm.shell.TaskViewFactory
import com.google.common.truth.Truth.assertThat
-import dagger.Lazy
-import java.util.Optional
-import java.util.function.Consumer
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
+import org.mockito.Mockito.`when`
import org.mockito.Mockito.anyInt
import org.mockito.Mockito.anyString
import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.never
import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
+import java.util.Optional
+import java.util.function.Consumer
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -98,13 +98,15 @@ class ControlsUiControllerImplTest : SysuiTestCase() {
@Mock lateinit var authorizedPanelsRepository: AuthorizedPanelsRepository
@Mock lateinit var featureFlags: FeatureFlags
@Mock lateinit var packageManager: PackageManager
- val sharedPreferences = FakeSharedPreferences()
- lateinit var controlsSettingsRepository: FakeControlsSettingsRepository
- var uiExecutor = FakeExecutor(FakeSystemClock())
- var bgExecutor = FakeExecutor(FakeSystemClock())
- lateinit var underTest: ControlsUiControllerImpl
- lateinit var parent: FrameLayout
+ private val sharedPreferences = FakeSharedPreferences()
+ private val fakeDialogController = FakeSystemUIDialogController()
+ private val uiExecutor = FakeExecutor(FakeSystemClock())
+ private val bgExecutor = FakeExecutor(FakeSystemClock())
+
+ private lateinit var controlsSettingsRepository: FakeControlsSettingsRepository
+ private lateinit var parent: FrameLayout
+ private lateinit var underTest: ControlsUiControllerImpl
@Before
fun setup() {
@@ -125,12 +127,12 @@ class ControlsUiControllerImplTest : SysuiTestCase() {
underTest =
ControlsUiControllerImpl(
- Lazy { controlsController },
+ { controlsController },
context,
packageManager,
uiExecutor,
bgExecutor,
- Lazy { controlsListingController },
+ { controlsListingController },
controlActionCoordinator,
activityStarter,
iconCache,
@@ -142,7 +144,8 @@ class ControlsUiControllerImplTest : SysuiTestCase() {
controlsSettingsRepository,
authorizedPanelsRepository,
featureFlags,
- dumpManager
+ ControlsDialogsFactory { fakeDialogController.dialog },
+ dumpManager,
)
`when`(
userFileManager.getSharedPreferences(
@@ -410,8 +413,45 @@ class ControlsUiControllerImplTest : SysuiTestCase() {
verify(controlsListingController, never()).removeCallback(any())
}
+ @Test
+ fun testRemovingAppsRemovesFavorite() {
+ val componentName = ComponentName(context, "cls")
+ whenever(controlsController.removeFavorites(eq(componentName))).thenReturn(true)
+ val panel = SelectedItem.PanelItem("App name", componentName)
+ sharedPreferences
+ .edit()
+ .putString("controls_component", panel.componentName.flattenToString())
+ .putString("controls_structure", panel.appName.toString())
+ .putBoolean("controls_is_panel", true)
+ .commit()
+ underTest.show(parent, {}, context)
+ underTest.startRemovingApp(componentName, "Test App")
+
+ fakeDialogController.clickPositive()
+
+ verify(controlsController).removeFavorites(eq(componentName))
+ assertThat(underTest.getPreferredSelectedItem(emptyList()))
+ .isEqualTo(SelectedItem.EMPTY_SELECTION)
+ with(sharedPreferences) {
+ assertThat(contains("controls_component")).isFalse()
+ assertThat(contains("controls_structure")).isFalse()
+ assertThat(contains("controls_is_panel")).isFalse()
+ }
+ }
+
+ @Test
+ fun testHideCancelsTheRemoveAppDialog() {
+ val componentName = ComponentName(context, "cls")
+ underTest.show(parent, {}, context)
+ underTest.startRemovingApp(componentName, "Test App")
+
+ underTest.hide(parent)
+
+ verify(fakeDialogController.dialog).cancel()
+ }
+
private fun setUpPanel(panel: SelectedItem.PanelItem): ControlsServiceInfo {
- val activity = ComponentName("pkg", "activity")
+ val activity = ComponentName(context, "activity")
sharedPreferences
.edit()
.putString("controls_component", panel.componentName.flattenToString())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/OverflowMenuAdapterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/OverflowMenuAdapterTest.kt
index dbaf94f1018c..483ab3bae6f1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/OverflowMenuAdapterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/OverflowMenuAdapterTest.kt
@@ -37,7 +37,9 @@ class OverflowMenuAdapterTest : SysuiTestCase() {
context,
layoutId = 0,
labels.zip(ids).map { OverflowMenuAdapter.MenuItem(it.first, it.second) }
- ) { true }
+ ) {
+ true
+ }
ids.forEachIndexed { index, id -> assertThat(adapter.getItemId(index)).isEqualTo(id) }
}
@@ -51,7 +53,9 @@ class OverflowMenuAdapterTest : SysuiTestCase() {
context,
layoutId = 0,
labels.zip(ids).map { OverflowMenuAdapter.MenuItem(it.first, it.second) }
- ) { position -> position == 0 }
+ ) { position ->
+ position == 0
+ }
assertThat(adapter.isEnabled(0)).isTrue()
assertThat(adapter.isEnabled(1)).isFalse()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/devicepolicy/DevicePolicyManagerExtTest.kt b/packages/SystemUI/tests/src/com/android/systemui/devicepolicy/DevicePolicyManagerExtTest.kt
new file mode 100644
index 000000000000..820329119f8d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/devicepolicy/DevicePolicyManagerExtTest.kt
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2023 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.devicepolicy
+
+import android.app.admin.DevicePolicyManager
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FACE
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(JUnit4::class)
+class DevicePolicyManagerExtTest : SysuiTestCase() {
+
+ @Mock lateinit var devicePolicyManager: DevicePolicyManager
+ @Mock private lateinit var userTracker: UserTracker
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ whenever(userTracker.userId).thenReturn(CURRENT_USER_ID)
+ }
+
+ // region areKeyguardShortcutsDisabled
+ @Test
+ fun areKeyguardShortcutsDisabled_noDisabledKeyguardFeature_shouldReturnFalse() {
+ whenever(devicePolicyManager.getKeyguardDisabledFeatures(eq(null), anyInt()))
+ .thenReturn(KEYGUARD_DISABLE_FEATURES_NONE)
+
+ assertThat(devicePolicyManager.areKeyguardShortcutsDisabled(userId = CURRENT_USER_ID))
+ .isFalse()
+ }
+
+ @Test
+ fun areKeyguardShortcutsDisabled_otherDisabledKeyguardFeatures_shouldReturnFalse() {
+ whenever(devicePolicyManager.getKeyguardDisabledFeatures(eq(null), anyInt()))
+ .thenReturn(KEYGUARD_DISABLE_SECURE_CAMERA or KEYGUARD_DISABLE_FACE)
+
+ assertThat(devicePolicyManager.areKeyguardShortcutsDisabled(userId = CURRENT_USER_ID))
+ .isFalse()
+ }
+
+ @Test
+ fun areKeyguardShortcutsDisabled_disabledShortcutsKeyguardFeature_shouldReturnTrue() {
+ whenever(devicePolicyManager.getKeyguardDisabledFeatures(eq(null), anyInt()))
+ .thenReturn(KEYGUARD_DISABLE_SHORTCUTS_ALL)
+
+ assertThat(devicePolicyManager.areKeyguardShortcutsDisabled(userId = CURRENT_USER_ID))
+ .isTrue()
+ }
+
+ @Test
+ fun areKeyguardShortcutsDisabled_disabledAllKeyguardFeatures_shouldReturnTrue() {
+ whenever(devicePolicyManager.getKeyguardDisabledFeatures(eq(null), anyInt()))
+ .thenReturn(KEYGUARD_DISABLE_FEATURES_ALL)
+
+ assertThat(devicePolicyManager.areKeyguardShortcutsDisabled(userId = CURRENT_USER_ID))
+ .isTrue()
+ }
+ // endregion
+
+ private companion object {
+ const val CURRENT_USER_ID = 123
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
index 9d4bef621988..aa17d4985f82 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
@@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
@@ -72,6 +73,7 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
private static final ComponentName LOW_LIGHT_COMPONENT = new ComponentName("package",
"lowlight");
private static final String DREAM_COMPONENT = "package/dream";
+ private static final String WINDOW_NAME = "test";
private final FakeSystemClock mFakeSystemClock = new FakeSystemClock();
private final FakeExecutor mMainExecutor = new FakeExecutor(mFakeSystemClock);
@@ -189,7 +191,8 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
mUiEventLogger,
mTouchInsetManager,
LOW_LIGHT_COMPONENT,
- mDreamOverlayCallbackController);
+ mDreamOverlayCallbackController,
+ WINDOW_NAME);
}
public IDreamOverlayClient getClient() throws RemoteException {
@@ -231,6 +234,31 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
verify(mWindowManager).addView(any(), any());
}
+ // Validates that {@link DreamOverlayService} properly handles the case where the dream's
+ // window is no longer valid by the time start is called.
+ @Test
+ public void testInvalidWindowAddStart() throws Exception {
+ final IDreamOverlayClient client = getClient();
+
+ doThrow(new WindowManager.BadTokenException()).when(mWindowManager).addView(any(), any());
+ // Inform the overlay service of dream starting.
+ client.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
+ false /*shouldShowComplication*/);
+ mMainExecutor.runAllReady();
+
+ verify(mWindowManager).addView(any(), any());
+
+ verify(mStateController).setOverlayActive(false);
+ verify(mStateController).setLowLightActive(false);
+ verify(mStateController).setEntryAnimationsFinished(false);
+
+ verify(mStateController, never()).setOverlayActive(true);
+ verify(mUiEventLogger, never()).log(
+ DreamOverlayService.DreamOverlayEvent.DREAM_OVERLAY_COMPLETE_START);
+
+ verify(mDreamOverlayCallbackController, never()).onStartDream();
+ }
+
@Test
public void testDreamOverlayContainerViewControllerInitialized() throws Exception {
final IDreamOverlayClient client = getClient();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java
index ef62abfe36de..175da0b7a5c2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java
@@ -33,6 +33,8 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.condition.SelfExecutingMonitor;
import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.dreams.smartspace.DreamSmartspaceController;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.BcSmartspaceDataPlugin;
import com.android.systemui.shared.condition.Condition;
import com.android.systemui.shared.condition.Monitor;
@@ -65,6 +67,9 @@ public class SmartSpaceComplicationTest extends SysuiTestCase {
@Mock
private View mBcSmartspaceView;
+ @Mock
+ private FeatureFlags mFeatureFlags;
+
private Monitor mMonitor;
private final Set<Condition> mPreconditions = new HashSet<>();
@@ -73,6 +78,8 @@ public class SmartSpaceComplicationTest extends SysuiTestCase {
public void setup() {
MockitoAnnotations.initMocks(this);
mMonitor = SelfExecutingMonitor.createInstance();
+
+ when(mFeatureFlags.isEnabled(Flags.HIDE_SMARTSPACE_ON_DREAM_OVERLAY)).thenReturn(false);
}
/**
@@ -85,12 +92,22 @@ public class SmartSpaceComplicationTest extends SysuiTestCase {
verify(mDreamOverlayStateController, never()).addComplication(eq(mComplication));
}
- private SmartSpaceComplication.Registrant getRegistrant() {
- return new SmartSpaceComplication.Registrant(
- mDreamOverlayStateController,
- mComplication,
- mSmartspaceController,
- mMonitor);
+ @Test
+ public void testRegistrantStart_featureEnabled_addOverlayStateCallback() {
+ final SmartSpaceComplication.Registrant registrant = getRegistrant();
+ registrant.start();
+
+ verify(mDreamOverlayStateController).addCallback(any());
+ }
+
+ @Test
+ public void testRegistrantStart_featureDisabled_doesNotAddOverlayStateCallback() {
+ when(mFeatureFlags.isEnabled(Flags.HIDE_SMARTSPACE_ON_DREAM_OVERLAY)).thenReturn(true);
+
+ final SmartSpaceComplication.Registrant registrant = getRegistrant();
+ registrant.start();
+
+ verify(mDreamOverlayStateController, never()).addCallback(any());
}
@Test
@@ -188,4 +205,13 @@ public class SmartSpaceComplicationTest extends SysuiTestCase {
when(mSmartspaceController.buildAndConnectView(any())).thenReturn(mBcSmartspaceView);
assertEquals(viewHolder.getView(), viewHolder.getView());
}
+
+ private SmartSpaceComplication.Registrant getRegistrant() {
+ return new SmartSpaceComplication.Registrant(
+ mDreamOverlayStateController,
+ mComplication,
+ mSmartspaceController,
+ mMonitor,
+ mFeatureFlags);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt
new file mode 100644
index 000000000000..f6ff4b214035
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2023 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.keyboard.data.repository
+
+import android.hardware.input.InputManager
+import android.view.InputDevice
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.nullable
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class KeyboardRepositoryTest : SysuiTestCase() {
+
+ @Captor
+ private lateinit var deviceListenerCaptor: ArgumentCaptor<InputManager.InputDeviceListener>
+ @Mock private lateinit var inputManager: InputManager
+
+ private lateinit var underTest: KeyboardRepository
+ private lateinit var dispatcher: CoroutineDispatcher
+ private lateinit var testScope: TestScope
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ whenever(inputManager.inputDeviceIds).thenReturn(intArrayOf())
+ whenever(inputManager.getInputDevice(any())).then { invocation ->
+ val id = invocation.arguments.first()
+ INPUT_DEVICES_MAP[id]
+ }
+ dispatcher = StandardTestDispatcher()
+ testScope = TestScope(dispatcher)
+ underTest = KeyboardRepositoryImpl(testScope.backgroundScope, dispatcher, inputManager)
+ }
+
+ @Test
+ fun emitsDisconnected_ifNothingIsConnected() =
+ testScope.runTest {
+ val initialState = underTest.keyboardConnected.first()
+ assertThat(initialState).isFalse()
+ }
+
+ @Test
+ fun emitsConnected_ifKeyboardAlreadyConnectedAtTheStart() =
+ testScope.runTest {
+ whenever(inputManager.inputDeviceIds).thenReturn(intArrayOf(PHYSICAL_FULL_KEYBOARD_ID))
+ val initialValue = underTest.keyboardConnected.first()
+ assertThat(initialValue).isTrue()
+ }
+
+ @Test
+ fun emitsConnected_whenNewPhysicalKeyboardConnects() =
+ testScope.runTest {
+ val deviceListener = captureDeviceListener()
+ val isKeyboardConnected by collectLastValue(underTest.keyboardConnected)
+
+ deviceListener.onInputDeviceAdded(PHYSICAL_FULL_KEYBOARD_ID)
+
+ assertThat(isKeyboardConnected).isTrue()
+ }
+
+ @Test
+ fun emitsDisconnected_whenKeyboardDisconnects() =
+ testScope.runTest {
+ val deviceListener = captureDeviceListener()
+ val isKeyboardConnected by collectLastValue(underTest.keyboardConnected)
+
+ deviceListener.onInputDeviceAdded(PHYSICAL_FULL_KEYBOARD_ID)
+ assertThat(isKeyboardConnected).isTrue()
+
+ deviceListener.onInputDeviceRemoved(PHYSICAL_FULL_KEYBOARD_ID)
+ assertThat(isKeyboardConnected).isFalse()
+ }
+
+ private suspend fun captureDeviceListener(): InputManager.InputDeviceListener {
+ underTest.keyboardConnected.first()
+ verify(inputManager).registerInputDeviceListener(deviceListenerCaptor.capture(), nullable())
+ return deviceListenerCaptor.value
+ }
+
+ @Test
+ fun emitsDisconnected_whenVirtualOrNotFullKeyboardConnects() =
+ testScope.runTest {
+ val deviceListener = captureDeviceListener()
+ val isKeyboardConnected by collectLastValue(underTest.keyboardConnected)
+
+ deviceListener.onInputDeviceAdded(PHYSICAL_NOT_FULL_KEYBOARD_ID)
+ assertThat(isKeyboardConnected).isFalse()
+
+ deviceListener.onInputDeviceAdded(VIRTUAL_FULL_KEYBOARD_ID)
+ assertThat(isKeyboardConnected).isFalse()
+ }
+
+ @Test
+ fun emitsDisconnected_whenKeyboardDisconnectsAndWasAlreadyConnectedAtTheStart() =
+ testScope.runTest {
+ val deviceListener = captureDeviceListener()
+ val isKeyboardConnected by collectLastValue(underTest.keyboardConnected)
+
+ deviceListener.onInputDeviceRemoved(PHYSICAL_FULL_KEYBOARD_ID)
+ assertThat(isKeyboardConnected).isFalse()
+ }
+
+ @Test
+ fun emitsConnected_whenAnotherDeviceDisconnects() =
+ testScope.runTest {
+ val deviceListener = captureDeviceListener()
+ val isKeyboardConnected by collectLastValue(underTest.keyboardConnected)
+
+ deviceListener.onInputDeviceAdded(PHYSICAL_FULL_KEYBOARD_ID)
+ deviceListener.onInputDeviceRemoved(VIRTUAL_FULL_KEYBOARD_ID)
+
+ assertThat(isKeyboardConnected).isTrue()
+ }
+
+ @Test
+ fun emitsConnected_whenOnePhysicalKeyboardDisconnectsButAnotherRemainsConnected() =
+ testScope.runTest {
+ val deviceListener = captureDeviceListener()
+ val isKeyboardConnected by collectLastValue(underTest.keyboardConnected)
+
+ deviceListener.onInputDeviceAdded(PHYSICAL_FULL_KEYBOARD_ID)
+ deviceListener.onInputDeviceAdded(ANOTHER_PHYSICAL_FULL_KEYBOARD_ID)
+ deviceListener.onInputDeviceRemoved(ANOTHER_PHYSICAL_FULL_KEYBOARD_ID)
+
+ assertThat(isKeyboardConnected).isTrue()
+ }
+
+ @Test
+ fun passesKeyboardBacklightValues_fromBacklightListener() {
+ // TODO(b/268645734): implement when implementing backlight listener
+ }
+
+ private companion object {
+ private const val PHYSICAL_FULL_KEYBOARD_ID = 1
+ private const val VIRTUAL_FULL_KEYBOARD_ID = 2
+ private const val PHYSICAL_NOT_FULL_KEYBOARD_ID = 3
+ private const val ANOTHER_PHYSICAL_FULL_KEYBOARD_ID = 4
+
+ private val INPUT_DEVICES_MAP: Map<Int, InputDevice> =
+ mapOf(
+ PHYSICAL_FULL_KEYBOARD_ID to inputDevice(virtual = false, fullKeyboard = true),
+ VIRTUAL_FULL_KEYBOARD_ID to inputDevice(virtual = true, fullKeyboard = true),
+ PHYSICAL_NOT_FULL_KEYBOARD_ID to inputDevice(virtual = false, fullKeyboard = false),
+ ANOTHER_PHYSICAL_FULL_KEYBOARD_ID to
+ inputDevice(virtual = false, fullKeyboard = true)
+ )
+
+ private fun inputDevice(virtual: Boolean, fullKeyboard: Boolean): InputDevice =
+ mock<InputDevice>().also {
+ whenever(it.isVirtual).thenReturn(virtual)
+ whenever(it.isFullKeyboard).thenReturn(fullKeyboard)
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index 7c20e3c9baff..c93e677071cd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -29,7 +29,6 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.atLeast;
-import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -67,7 +66,6 @@ import com.android.systemui.classifier.FalsingCollectorFake;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shade.NotificationShadeWindowControllerImpl;
@@ -136,7 +134,6 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
private @Mock SysuiColorExtractor mColorExtractor;
private @Mock AuthController mAuthController;
private @Mock ShadeExpansionStateManager mShadeExpansionStateManager;
- private @Mock FeatureFlags mFeatureFlags;
private @Mock ShadeWindowLogger mShadeWindowLogger;
private DeviceConfigProxy mDeviceConfig = new DeviceConfigProxyFake();
private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
@@ -545,7 +542,6 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
mScreenOnCoordinator,
mInteractionJankMonitor,
mDreamOverlayStateController,
- mFeatureFlags,
() -> mShadeController,
() -> mNotificationShadeWindowController,
() -> mActivityLaunchAnimator,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt
index 21ad5e2cd311..5dc04f7efa63 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt
@@ -30,6 +30,7 @@ import androidx.test.filters.SmallTest
import com.android.internal.widget.LockPatternUtils
import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED
import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT
+import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.AuthController
import com.android.systemui.coroutines.collectLastValue
@@ -38,11 +39,14 @@ import com.android.systemui.keyguard.data.repository.BiometricType.FACE
import com.android.systemui.keyguard.data.repository.BiometricType.REAR_FINGERPRINT
import com.android.systemui.keyguard.data.repository.BiometricType.SIDE_FINGERPRINT
import com.android.systemui.keyguard.data.repository.BiometricType.UNDER_DISPLAY_FINGERPRINT
+import com.android.systemui.keyguard.shared.model.DevicePosture
+import com.android.systemui.statusbar.policy.DevicePostureController
import com.android.systemui.user.data.repository.FakeUserRepository
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestDispatcher
import kotlinx.coroutines.test.TestScope
@@ -62,6 +66,7 @@ import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
+@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@RunWith(AndroidTestingRunner::class)
@@ -78,6 +83,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() {
private lateinit var biometricManagerCallback:
ArgumentCaptor<IBiometricEnabledOnKeyguardCallback.Stub>
private lateinit var userRepository: FakeUserRepository
+ private lateinit var devicePostureRepository: FakeDevicePostureRepository
private lateinit var testDispatcher: TestDispatcher
private lateinit var testScope: TestScope
@@ -90,6 +96,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() {
testDispatcher = StandardTestDispatcher()
testScope = TestScope(testDispatcher)
userRepository = FakeUserRepository()
+ devicePostureRepository = FakeDevicePostureRepository()
}
private suspend fun createBiometricSettingsRepository() {
@@ -108,6 +115,7 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() {
looper = testableLooper!!.looper,
dumpManager = dumpManager,
biometricManager = biometricManager,
+ devicePostureRepository = devicePostureRepository,
)
testScope.runCurrent()
}
@@ -299,6 +307,50 @@ class BiometricSettingsRepositoryTest : SysuiTestCase() {
verify(biometricManager, times(1)).registerEnabledOnKeyguardCallback(any())
}
+ @Test
+ fun faceAuthIsAlwaysSupportedIfSpecificPostureIsNotConfigured() =
+ testScope.runTest {
+ overrideResource(
+ R.integer.config_face_auth_supported_posture,
+ DevicePostureController.DEVICE_POSTURE_UNKNOWN
+ )
+
+ createBiometricSettingsRepository()
+
+ assertThat(collectLastValue(underTest.isFaceAuthSupportedInCurrentPosture)()).isTrue()
+ }
+
+ @Test
+ fun faceAuthIsSupportedOnlyWhenDevicePostureMatchesConfigValue() =
+ testScope.runTest {
+ overrideResource(
+ R.integer.config_face_auth_supported_posture,
+ DevicePostureController.DEVICE_POSTURE_FLIPPED
+ )
+
+ createBiometricSettingsRepository()
+
+ val isFaceAuthSupported =
+ collectLastValue(underTest.isFaceAuthSupportedInCurrentPosture)
+
+ assertThat(isFaceAuthSupported()).isFalse()
+
+ devicePostureRepository.setCurrentPosture(DevicePosture.CLOSED)
+ assertThat(isFaceAuthSupported()).isFalse()
+
+ devicePostureRepository.setCurrentPosture(DevicePosture.HALF_OPENED)
+ assertThat(isFaceAuthSupported()).isFalse()
+
+ devicePostureRepository.setCurrentPosture(DevicePosture.OPENED)
+ assertThat(isFaceAuthSupported()).isFalse()
+
+ devicePostureRepository.setCurrentPosture(DevicePosture.UNKNOWN)
+ assertThat(isFaceAuthSupported()).isFalse()
+
+ devicePostureRepository.setCurrentPosture(DevicePosture.FLIPPED)
+ assertThat(isFaceAuthSupported()).isTrue()
+ }
+
private fun enrollmentChange(biometricType: BiometricType, userId: Int, enabled: Boolean) {
authControllerCallback.value.onEnrollmentsChanged(biometricType, userId, enabled)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DevicePostureRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DevicePostureRepositoryTest.kt
new file mode 100644
index 000000000000..bd6b7a853dfc
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DevicePostureRepositoryTest.kt
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2023 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.keyguard.data.repository
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.keyguard.shared.model.DevicePosture
+import com.android.systemui.statusbar.policy.DevicePostureController
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class DevicePostureRepositoryTest : SysuiTestCase() {
+ private lateinit var underTest: DevicePostureRepository
+ private lateinit var testScope: TestScope
+ @Mock private lateinit var devicePostureController: DevicePostureController
+ @Captor private lateinit var callback: ArgumentCaptor<DevicePostureController.Callback>
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ testScope = TestScope()
+ underTest = DevicePostureRepositoryImpl(postureController = devicePostureController)
+ }
+
+ @Test
+ fun postureChangesArePropagated() =
+ testScope.runTest {
+ whenever(devicePostureController.devicePosture)
+ .thenReturn(DevicePostureController.DEVICE_POSTURE_FLIPPED)
+ val currentPosture = collectLastValue(underTest.currentDevicePosture)
+ assertThat(currentPosture()).isEqualTo(DevicePosture.FLIPPED)
+
+ verify(devicePostureController).addCallback(callback.capture())
+
+ callback.value.onPostureChanged(DevicePostureController.DEVICE_POSTURE_UNKNOWN)
+ assertThat(currentPosture()).isEqualTo(DevicePosture.UNKNOWN)
+
+ callback.value.onPostureChanged(DevicePostureController.DEVICE_POSTURE_CLOSED)
+ assertThat(currentPosture()).isEqualTo(DevicePosture.CLOSED)
+
+ callback.value.onPostureChanged(DevicePostureController.DEVICE_POSTURE_HALF_OPENED)
+ assertThat(currentPosture()).isEqualTo(DevicePosture.HALF_OPENED)
+
+ callback.value.onPostureChanged(DevicePostureController.DEVICE_POSTURE_OPENED)
+ assertThat(currentPosture()).isEqualTo(DevicePosture.OPENED)
+
+ callback.value.onPostureChanged(DevicePostureController.DEVICE_POSTURE_FLIPPED)
+ assertThat(currentPosture()).isEqualTo(DevicePosture.FLIPPED)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManagerTest.kt
index 7c604f760681..d55370b20d09 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManagerTest.kt
@@ -21,6 +21,7 @@ import android.content.pm.UserInfo
import android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_CANCELED
import android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT
import android.hardware.biometrics.ComponentInfoInternal
+import android.hardware.face.FaceAuthenticateOptions
import android.hardware.face.FaceManager
import android.hardware.face.FaceSensorProperties
import android.hardware.face.FaceSensorPropertiesInternal
@@ -62,7 +63,6 @@ import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers.any
-import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.eq
import org.mockito.Captor
import org.mockito.Mock
@@ -276,7 +276,7 @@ class KeyguardFaceAuthManagerTest : SysuiTestCase() {
underTest.detect()
- verify(faceManager, never()).detectFace(any(), any(), anyInt())
+ verify(faceManager, never()).detectFace(any(), any(), any())
}
@Test
@@ -379,7 +379,7 @@ class KeyguardFaceAuthManagerTest : SysuiTestCase() {
.detectFace(
cancellationSignal.capture(),
detectionCallback.capture(),
- eq(currentUserId)
+ eq(FaceAuthenticateOptions.Builder().setUserId(currentUserId).build())
)
}
@@ -390,8 +390,7 @@ class KeyguardFaceAuthManagerTest : SysuiTestCase() {
cancellationSignal.capture(),
authenticationCallback.capture(),
isNull(),
- eq(currentUserId),
- eq(true)
+ eq(FaceAuthenticateOptions.Builder().setUserId(currentUserId).build())
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt
index d2db910ad443..f9493d10ff61 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt
@@ -62,7 +62,9 @@ class LightRevealScrimRepositoryTest : SysuiTestCase() {
fakeKeyguardRepository.setBiometricUnlockState(BiometricUnlockModel.WAKE_AND_UNLOCK)
runCurrent()
- values.assertEffectsMatchPredicates({ it == DEFAULT_REVEAL_EFFECT },)
+ values.assertEffectsMatchPredicates(
+ { it == DEFAULT_REVEAL_EFFECT },
+ )
// We got a source but still have no sensor locations, so should be sticking with
// the default effect.
@@ -71,14 +73,18 @@ class LightRevealScrimRepositoryTest : SysuiTestCase() {
)
runCurrent()
- values.assertEffectsMatchPredicates({ it == DEFAULT_REVEAL_EFFECT },)
+ values.assertEffectsMatchPredicates(
+ { it == DEFAULT_REVEAL_EFFECT },
+ )
// We got a location for the face sensor, but we unlocked with fingerprint.
val faceLocation = Point(250, 0)
fakeKeyguardRepository.setFaceSensorLocation(faceLocation)
runCurrent()
- values.assertEffectsMatchPredicates({ it == DEFAULT_REVEAL_EFFECT },)
+ values.assertEffectsMatchPredicates(
+ { it == DEFAULT_REVEAL_EFFECT },
+ )
// Now we have fingerprint sensor locations, and wake and unlock via fingerprint.
val fingerprintLocation = Point(500, 500)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt
index 18e80ea40c5c..1365132d6dac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt
@@ -28,6 +28,8 @@ import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintA
import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepositoryImpl
import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
import com.android.systemui.util.time.SystemClock
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -50,6 +52,7 @@ class AlternateBouncerInteractorTest : SysuiTestCase() {
private lateinit var biometricSettingsRepository: FakeBiometricSettingsRepository
private lateinit var deviceEntryFingerprintAuthRepository:
FakeDeviceEntryFingerprintAuthRepository
+ @Mock private lateinit var keyguardStateController: KeyguardStateController
@Mock private lateinit var systemClock: SystemClock
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
@Mock private lateinit var bouncerLogger: TableLogBuffer
@@ -70,6 +73,7 @@ class AlternateBouncerInteractorTest : SysuiTestCase() {
featureFlags = FakeFeatureFlags().apply { this.set(Flags.MODERN_ALTERNATE_BOUNCER, true) }
underTest =
AlternateBouncerInteractor(
+ keyguardStateController,
bouncerRepository,
biometricSettingsRepository,
deviceEntryFingerprintAuthRepository,
@@ -134,6 +138,14 @@ class AlternateBouncerInteractorTest : SysuiTestCase() {
}
@Test
+ fun canShowAlternateBouncerForFingerprint_butCanDismissLockScreen() {
+ givenCanShowAlternateBouncer()
+ whenever(keyguardStateController.isUnlocked).thenReturn(true)
+
+ assertFalse(underTest.canShowAlternateBouncerForFingerprint())
+ }
+
+ @Test
fun show_whenCannotShow() {
givenCannotShowAlternateBouncer()
@@ -163,6 +175,7 @@ class AlternateBouncerInteractorTest : SysuiTestCase() {
biometricSettingsRepository.setStrongBiometricAllowed(true)
biometricSettingsRepository.setFingerprintEnabledByDevicePolicy(true)
deviceEntryFingerprintAuthRepository.setLockedOut(false)
+ whenever(keyguardStateController.isUnlocked).thenReturn(false)
}
private fun givenCannotShowAlternateBouncer() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt
index 8bd8be565eee..c727b3a6cd10 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt
@@ -308,7 +308,7 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() {
TestConfig(
isVisible = true,
isClickable = false,
- isActivated = true,
+ isActivated = false,
icon = icon,
canShowWhileLocked = false,
intent = Intent("action"),
@@ -363,7 +363,7 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() {
TestConfig(
isVisible = true,
isClickable = false,
- isActivated = true,
+ isActivated = false,
icon = icon,
canShowWhileLocked = false,
intent = Intent("action"),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt
index a07a714ebc77..ab0669a28f04 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt
@@ -93,6 +93,8 @@ private const val SYSTEM_PACKAGE_NAME = "com.android.systemui"
private const val APP_NAME = "SystemUI"
private const val SESSION_ARTIST = "artist"
private const val SESSION_TITLE = "title"
+private const val SESSION_BLANK_TITLE = " "
+private const val SESSION_EMPTY_TITLE = ""
private const val USER_ID = 0
private val DISMISS_INTENT = Intent().apply { action = "dismiss" }
@@ -137,6 +139,7 @@ class MediaDataManagerTest : SysuiTestCase() {
@Mock private lateinit var logger: MediaUiEventLogger
lateinit var mediaDataManager: MediaDataManager
lateinit var mediaNotification: StatusBarNotification
+ lateinit var remoteCastNotification: StatusBarNotification
@Captor lateinit var mediaDataCaptor: ArgumentCaptor<MediaData>
private val clock = FakeSystemClock()
@Mock private lateinit var tunerService: TunerService
@@ -205,6 +208,20 @@ class MediaDataManagerTest : SysuiTestCase() {
}
build()
}
+ remoteCastNotification =
+ SbnBuilder().run {
+ setPkg(SYSTEM_PACKAGE_NAME)
+ modifyNotification(context).also {
+ it.setSmallIcon(android.R.drawable.ic_media_pause)
+ it.setStyle(
+ MediaStyle().apply {
+ setMediaSession(session.sessionToken)
+ setRemotePlaybackInfo("Remote device", 0, null)
+ }
+ )
+ }
+ build()
+ }
metadataBuilder =
MediaMetadata.Builder().apply {
putString(MediaMetadata.METADATA_KEY_ARTIST, SESSION_ARTIST)
@@ -214,6 +231,7 @@ class MediaDataManagerTest : SysuiTestCase() {
whenever(mediaControllerFactory.create(eq(session.sessionToken))).thenReturn(controller)
whenever(controller.transportControls).thenReturn(transportControls)
whenever(controller.playbackInfo).thenReturn(playbackInfo)
+ whenever(controller.metadata).thenReturn(metadataBuilder.build())
whenever(playbackInfo.playbackType)
.thenReturn(MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL)
@@ -244,6 +262,7 @@ class MediaDataManagerTest : SysuiTestCase() {
whenever(mediaFlags.isExplicitIndicatorEnabled()).thenReturn(true)
whenever(mediaFlags.isRetainingPlayersEnabled()).thenReturn(false)
whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(false)
+ whenever(mediaFlags.isRemoteResumeAllowed()).thenReturn(false)
whenever(logger.getNewInstanceId()).thenReturn(instanceIdSequence.newInstanceId())
whenever(keyguardUpdateMonitor.isUserInLockdown(any())).thenReturn(false)
}
@@ -318,18 +337,15 @@ class MediaDataManagerTest : SysuiTestCase() {
@Test
fun testLoadMetadata_withExplicitIndicator() {
- val metadata =
- MediaMetadata.Builder().run {
- putString(MediaMetadata.METADATA_KEY_ARTIST, SESSION_ARTIST)
- putString(MediaMetadata.METADATA_KEY_TITLE, SESSION_TITLE)
- putLong(
- MediaConstants.METADATA_KEY_IS_EXPLICIT,
- MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT
- )
- build()
- }
- whenever(mediaControllerFactory.create(anyObject())).thenReturn(controller)
- whenever(controller.metadata).thenReturn(metadata)
+ whenever(controller.metadata)
+ .thenReturn(
+ metadataBuilder
+ .putLong(
+ MediaConstants.METADATA_KEY_IS_EXPLICIT,
+ MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT
+ )
+ .build()
+ )
mediaDataManager.addListener(listener)
mediaDataManager.onNotificationAdded(KEY, mediaNotification)
@@ -350,9 +366,6 @@ class MediaDataManagerTest : SysuiTestCase() {
@Test
fun testOnMetaDataLoaded_withoutExplicitIndicator() {
- whenever(mediaControllerFactory.create(anyObject())).thenReturn(controller)
- whenever(controller.metadata).thenReturn(metadataBuilder.build())
-
mediaDataManager.addListener(listener)
mediaDataManager.onNotificationAdded(KEY, mediaNotification)
@@ -385,7 +398,6 @@ class MediaDataManagerTest : SysuiTestCase() {
@Test
fun testOnMetaDataLoaded_conservesActiveFlag() {
whenever(mediaControllerFactory.create(anyObject())).thenReturn(controller)
- whenever(controller.metadata).thenReturn(metadataBuilder.build())
mediaDataManager.addListener(listener)
mediaDataManager.onNotificationAdded(KEY, mediaNotification)
assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
@@ -404,33 +416,8 @@ class MediaDataManagerTest : SysuiTestCase() {
@Test
fun testOnNotificationAdded_isRcn_markedRemote() {
- val rcn =
- SbnBuilder().run {
- setPkg(SYSTEM_PACKAGE_NAME)
- modifyNotification(context).also {
- it.setSmallIcon(android.R.drawable.ic_media_pause)
- it.setStyle(
- MediaStyle().apply {
- setMediaSession(session.sessionToken)
- setRemotePlaybackInfo("Remote device", 0, null)
- }
- )
- }
- build()
- }
+ addNotificationAndLoad(remoteCastNotification)
- mediaDataManager.onNotificationAdded(KEY, rcn)
- assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
- assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
- verify(listener)
- .onMediaDataLoaded(
- eq(KEY),
- eq(null),
- capture(mediaDataCaptor),
- eq(true),
- eq(0),
- eq(false)
- )
assertThat(mediaDataCaptor.value!!.playbackLocation)
.isEqualTo(MediaData.PLAYBACK_CAST_REMOTE)
verify(logger)
@@ -530,9 +517,78 @@ class MediaDataManagerTest : SysuiTestCase() {
}
@Test
+ fun testOnNotificationRemoved_emptyTitle_notConverted() {
+ // GIVEN that the manager has a notification with a resume action and empty title.
+ whenever(controller.metadata)
+ .thenReturn(
+ metadataBuilder
+ .putString(MediaMetadata.METADATA_KEY_TITLE, SESSION_EMPTY_TITLE)
+ .build()
+ )
+ addNotificationAndLoad()
+ val data = mediaDataCaptor.value
+ val instanceId = data.instanceId
+ assertThat(data.resumption).isFalse()
+ mediaDataManager.onMediaDataLoaded(KEY, null, data.copy(resumeAction = Runnable {}))
+
+ // WHEN the notification is removed
+ reset(listener)
+ mediaDataManager.onNotificationRemoved(KEY)
+
+ // THEN active media is not converted to resume.
+ verify(listener, never())
+ .onMediaDataLoaded(
+ eq(PACKAGE_NAME),
+ eq(KEY),
+ capture(mediaDataCaptor),
+ eq(true),
+ eq(0),
+ eq(false)
+ )
+ verify(logger, never())
+ .logActiveConvertedToResume(anyInt(), eq(PACKAGE_NAME), eq(instanceId))
+ verify(logger, never()).logResumeMediaAdded(anyInt(), eq(PACKAGE_NAME), any())
+ verify(logger).logMediaRemoved(anyInt(), eq(PACKAGE_NAME), eq(instanceId))
+ }
+
+ @Test
+ fun testOnNotificationRemoved_blankTitle_notConverted() {
+ // GIVEN that the manager has a notification with a resume action and blank title.
+ whenever(controller.metadata)
+ .thenReturn(
+ metadataBuilder
+ .putString(MediaMetadata.METADATA_KEY_TITLE, SESSION_BLANK_TITLE)
+ .build()
+ )
+ addNotificationAndLoad()
+ val data = mediaDataCaptor.value
+ val instanceId = data.instanceId
+ assertThat(data.resumption).isFalse()
+ mediaDataManager.onMediaDataLoaded(KEY, null, data.copy(resumeAction = Runnable {}))
+
+ // WHEN the notification is removed
+ reset(listener)
+ mediaDataManager.onNotificationRemoved(KEY)
+
+ // THEN active media is not converted to resume.
+ verify(listener, never())
+ .onMediaDataLoaded(
+ eq(PACKAGE_NAME),
+ eq(KEY),
+ capture(mediaDataCaptor),
+ eq(true),
+ eq(0),
+ eq(false)
+ )
+ verify(logger, never())
+ .logActiveConvertedToResume(anyInt(), eq(PACKAGE_NAME), eq(instanceId))
+ verify(logger, never()).logResumeMediaAdded(anyInt(), eq(PACKAGE_NAME), any())
+ verify(logger).logMediaRemoved(anyInt(), eq(PACKAGE_NAME), eq(instanceId))
+ }
+
+ @Test
fun testOnNotificationRemoved_withResumption() {
// GIVEN that the manager has a notification with a resume action
- whenever(controller.metadata).thenReturn(metadataBuilder.build())
addNotificationAndLoad()
val data = mediaDataCaptor.value
assertThat(data.resumption).isFalse()
@@ -557,7 +613,6 @@ class MediaDataManagerTest : SysuiTestCase() {
@Test
fun testOnNotificationRemoved_twoWithResumption() {
// GIVEN that the manager has two notifications with resume actions
- whenever(controller.metadata).thenReturn(metadataBuilder.build())
mediaDataManager.onNotificationAdded(KEY, mediaNotification)
mediaDataManager.onNotificationAdded(KEY_2, mediaNotification)
assertThat(backgroundExecutor.runAllReady()).isEqualTo(2)
@@ -623,7 +678,6 @@ class MediaDataManagerTest : SysuiTestCase() {
@Test
fun testOnNotificationRemoved_withResumption_butNotLocal() {
// GIVEN that the manager has a notification with a resume action, but is not local
- whenever(controller.metadata).thenReturn(metadataBuilder.build())
whenever(playbackInfo.playbackType)
.thenReturn(MediaController.PlaybackInfo.PLAYBACK_TYPE_REMOTE)
addNotificationAndLoad()
@@ -647,6 +701,56 @@ class MediaDataManagerTest : SysuiTestCase() {
}
@Test
+ fun testOnNotificationRemoved_withResumption_isRemoteAndRemoteAllowed() {
+ // With the flag enabled to allow remote media to resume
+ whenever(mediaFlags.isRemoteResumeAllowed()).thenReturn(true)
+
+ // GIVEN that the manager has a notification with a resume action, but is not local
+ whenever(controller.metadata).thenReturn(metadataBuilder.build())
+ whenever(playbackInfo.playbackType)
+ .thenReturn(MediaController.PlaybackInfo.PLAYBACK_TYPE_REMOTE)
+ addNotificationAndLoad()
+ val data = mediaDataCaptor.value
+ val dataRemoteWithResume =
+ data.copy(resumeAction = Runnable {}, playbackLocation = MediaData.PLAYBACK_CAST_LOCAL)
+ mediaDataManager.onMediaDataLoaded(KEY, null, dataRemoteWithResume)
+
+ // WHEN the notification is removed
+ mediaDataManager.onNotificationRemoved(KEY)
+
+ // THEN the media data is converted to a resume state
+ verify(listener)
+ .onMediaDataLoaded(
+ eq(PACKAGE_NAME),
+ eq(KEY),
+ capture(mediaDataCaptor),
+ eq(true),
+ eq(0),
+ eq(false)
+ )
+ assertThat(mediaDataCaptor.value.resumption).isTrue()
+ }
+
+ @Test
+ fun testOnNotificationRemoved_withResumption_isRcnAndRemoteAllowed() {
+ // With the flag enabled to allow remote media to resume
+ whenever(mediaFlags.isRemoteResumeAllowed()).thenReturn(true)
+
+ // GIVEN that the manager has a remote cast notification
+ addNotificationAndLoad(remoteCastNotification)
+ val data = mediaDataCaptor.value
+ assertThat(data.playbackLocation).isEqualTo(MediaData.PLAYBACK_CAST_REMOTE)
+ val dataRemoteWithResume = data.copy(resumeAction = Runnable {})
+ mediaDataManager.onMediaDataLoaded(KEY, null, dataRemoteWithResume)
+
+ // WHEN the RCN is removed
+ mediaDataManager.onNotificationRemoved(KEY)
+
+ // THEN the media data is removed
+ verify(listener).onMediaDataRemoved(eq(KEY))
+ }
+
+ @Test
fun testOnNotificationRemoved_withResumption_tooManyPlayers() {
// Given the maximum number of resume controls already
val desc =
@@ -660,7 +764,6 @@ class MediaDataManagerTest : SysuiTestCase() {
}
// And an active, resumable notification
- whenever(controller.metadata).thenReturn(metadataBuilder.build())
addNotificationAndLoad()
val data = mediaDataCaptor.value
assertThat(data.resumption).isFalse()
@@ -845,6 +948,74 @@ class MediaDataManagerTest : SysuiTestCase() {
}
@Test
+ fun testAddResumptionControls_hasEmptyTitle() {
+ whenever(mediaFlags.isResumeProgressEnabled()).thenReturn(true)
+
+ // WHEN resumption controls are added that have empty title
+ val desc =
+ MediaDescription.Builder().run {
+ setTitle(SESSION_EMPTY_TITLE)
+ build()
+ }
+ mediaDataManager.addResumptionControls(
+ USER_ID,
+ desc,
+ Runnable {},
+ session.sessionToken,
+ APP_NAME,
+ pendingIntent,
+ PACKAGE_NAME
+ )
+
+ // Resumption controls are not added.
+ assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
+ assertThat(foregroundExecutor.runAllReady()).isEqualTo(0)
+ verify(listener, never())
+ .onMediaDataLoaded(
+ eq(PACKAGE_NAME),
+ eq(null),
+ capture(mediaDataCaptor),
+ eq(true),
+ eq(0),
+ eq(false)
+ )
+ }
+
+ @Test
+ fun testAddResumptionControls_hasBlankTitle() {
+ whenever(mediaFlags.isResumeProgressEnabled()).thenReturn(true)
+
+ // WHEN resumption controls are added that have a blank title
+ val desc =
+ MediaDescription.Builder().run {
+ setTitle(SESSION_BLANK_TITLE)
+ build()
+ }
+ mediaDataManager.addResumptionControls(
+ USER_ID,
+ desc,
+ Runnable {},
+ session.sessionToken,
+ APP_NAME,
+ pendingIntent,
+ PACKAGE_NAME
+ )
+
+ // Resumption controls are not added.
+ assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
+ assertThat(foregroundExecutor.runAllReady()).isEqualTo(0)
+ verify(listener, never())
+ .onMediaDataLoaded(
+ eq(PACKAGE_NAME),
+ eq(null),
+ capture(mediaDataCaptor),
+ eq(true),
+ eq(0),
+ eq(false)
+ )
+ }
+
+ @Test
fun testResumptionDisabled_dismissesResumeControls() {
// WHEN there are resume controls and resumption is switched off
val desc =
@@ -1213,7 +1384,6 @@ class MediaDataManagerTest : SysuiTestCase() {
@Test
fun testOnActiveMediaConverted_doesNotUpdateLastActiveTime() {
// GIVEN that the manager has a notification with a resume action
- whenever(controller.metadata).thenReturn(metadataBuilder.build())
addNotificationAndLoad()
val data = mediaDataCaptor.value
val instanceId = data.instanceId
@@ -1513,7 +1683,6 @@ class MediaDataManagerTest : SysuiTestCase() {
val instanceId = mediaDataCaptor.value.instanceId
// Location is updated to local cast
- whenever(controller.metadata).thenReturn(metadataBuilder.build())
whenever(playbackInfo.playbackType)
.thenReturn(MediaController.PlaybackInfo.PLAYBACK_TYPE_REMOTE)
addNotificationAndLoad()
@@ -1526,22 +1695,7 @@ class MediaDataManagerTest : SysuiTestCase() {
)
// update to remote cast
- val rcn =
- SbnBuilder().run {
- setPkg(SYSTEM_PACKAGE_NAME) // System package
- modifyNotification(context).also {
- it.setSmallIcon(android.R.drawable.ic_media_pause)
- it.setStyle(
- MediaStyle().apply {
- setMediaSession(session.sessionToken)
- setRemotePlaybackInfo("Remote device", 0, null)
- }
- )
- }
- build()
- }
-
- mediaDataManager.onNotificationAdded(KEY, rcn)
+ mediaDataManager.onNotificationAdded(KEY, remoteCastNotification)
assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
verify(logger)
@@ -1589,7 +1743,6 @@ class MediaDataManagerTest : SysuiTestCase() {
@Test
fun testPlaybackStateChange_keyHasNullToken_doesNothing() {
// When we get an update that sets the data's token to null
- whenever(controller.metadata).thenReturn(metadataBuilder.build())
addNotificationAndLoad()
val data = mediaDataCaptor.value
assertThat(data.resumption).isFalse()
@@ -1911,9 +2064,14 @@ class MediaDataManagerTest : SysuiTestCase() {
verify(listener).onMediaDataRemoved(eq(KEY))
}
- /** Helper function to add a media notification and capture the resulting MediaData */
+ /** Helper function to add a basic media notification and capture the resulting MediaData */
private fun addNotificationAndLoad() {
- mediaDataManager.onNotificationAdded(KEY, mediaNotification)
+ addNotificationAndLoad(mediaNotification)
+ }
+
+ /** Helper function to add the given notification and capture the resulting MediaData */
+ private fun addNotificationAndLoad(sbn: StatusBarNotification) {
+ mediaDataManager.onNotificationAdded(KEY, sbn)
assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
verify(listener)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/resume/MediaResumeListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/resume/MediaResumeListenerTest.kt
index 136ace173795..4dfa6261b868 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/resume/MediaResumeListenerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/resume/MediaResumeListenerTest.kt
@@ -38,6 +38,7 @@ import com.android.systemui.media.controls.models.player.MediaData
import com.android.systemui.media.controls.models.player.MediaDeviceData
import com.android.systemui.media.controls.pipeline.MediaDataManager
import com.android.systemui.media.controls.pipeline.RESUME_MEDIA_TIMEOUT
+import com.android.systemui.media.controls.util.MediaFlags
import com.android.systemui.settings.UserTracker
import com.android.systemui.tuner.TunerService
import com.android.systemui.util.concurrency.FakeExecutor
@@ -92,6 +93,7 @@ class MediaResumeListenerTest : SysuiTestCase() {
@Mock private lateinit var mockContext: Context
@Mock private lateinit var pendingIntent: PendingIntent
@Mock private lateinit var dumpManager: DumpManager
+ @Mock private lateinit var mediaFlags: MediaFlags
@Captor lateinit var callbackCaptor: ArgumentCaptor<ResumeMediaBrowser.Callback>
@Captor lateinit var actionCaptor: ArgumentCaptor<Runnable>
@@ -134,6 +136,7 @@ class MediaResumeListenerTest : SysuiTestCase() {
whenever(mockContext.packageManager).thenReturn(context.packageManager)
whenever(mockContext.contentResolver).thenReturn(context.contentResolver)
whenever(mockContext.userId).thenReturn(context.userId)
+ whenever(mediaFlags.isRemoteResumeAllowed()).thenReturn(false)
executor = FakeExecutor(clock)
resumeListener =
@@ -146,7 +149,8 @@ class MediaResumeListenerTest : SysuiTestCase() {
tunerService,
resumeBrowserFactory,
dumpManager,
- clock
+ clock,
+ mediaFlags,
)
resumeListener.setManager(mediaDataManager)
mediaDataManager.addListener(resumeListener)
@@ -188,7 +192,8 @@ class MediaResumeListenerTest : SysuiTestCase() {
tunerService,
resumeBrowserFactory,
dumpManager,
- clock
+ clock,
+ mediaFlags,
)
listener.setManager(mediaDataManager)
verify(broadcastDispatcher, never())
@@ -244,6 +249,32 @@ class MediaResumeListenerTest : SysuiTestCase() {
}
@Test
+ fun testOnLoad_localCast_remoteResumeAllowed_doesCheck() {
+ // If local cast media is allowed to resume
+ whenever(mediaFlags.isRemoteResumeAllowed()).thenReturn(true)
+
+ // When media data is loaded that has not been checked yet, and is a local cast
+ val dataCast = data.copy(playbackLocation = MediaData.PLAYBACK_CAST_LOCAL)
+ resumeListener.onMediaDataLoaded(KEY, null, dataCast)
+
+ // Then we report back to the manager
+ verify(mediaDataManager).setResumeAction(KEY, null)
+ }
+
+ @Test
+ fun testOnLoad_remoteCast_remoteResumeAllowed_doesCheck() {
+ // If local cast media is allowed to resume
+ whenever(mediaFlags.isRemoteResumeAllowed()).thenReturn(true)
+
+ // When media data is loaded that has not been checked yet, and is a remote cast
+ val dataRcn = data.copy(playbackLocation = MediaData.PLAYBACK_CAST_REMOTE)
+ resumeListener.onMediaDataLoaded(KEY, null, dataRcn)
+
+ // Then we do not take action
+ verify(mediaDataManager, never()).setResumeAction(any(), any())
+ }
+
+ @Test
fun testOnLoad_checksForResume_hasService() {
setUpMbsWithValidResolveInfo()
@@ -389,7 +420,8 @@ class MediaResumeListenerTest : SysuiTestCase() {
tunerService,
resumeBrowserFactory,
dumpManager,
- clock
+ clock,
+ mediaFlags,
)
resumeListener.setManager(mediaDataManager)
mediaDataManager.addListener(resumeListener)
@@ -421,7 +453,8 @@ class MediaResumeListenerTest : SysuiTestCase() {
tunerService,
resumeBrowserFactory,
dumpManager,
- clock
+ clock,
+ mediaFlags,
)
resumeListener.setManager(mediaDataManager)
mediaDataManager.addListener(resumeListener)
@@ -463,7 +496,8 @@ class MediaResumeListenerTest : SysuiTestCase() {
tunerService,
resumeBrowserFactory,
dumpManager,
- clock
+ clock,
+ mediaFlags,
)
resumeListener.setManager(mediaDataManager)
mediaDataManager.addListener(resumeListener)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt
index a72634bcb807..7f5707722b9c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt
@@ -17,6 +17,7 @@
package com.android.systemui.media.controls.ui
import android.app.PendingIntent
+import android.content.res.ColorStateList
import android.content.res.Configuration
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
@@ -26,9 +27,9 @@ import androidx.test.filters.SmallTest
import com.android.internal.logging.InstanceId
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
+import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.FalsingCollector
-import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dump.DumpManager
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
@@ -49,7 +50,7 @@ import com.android.systemui.qs.PageIndicator
import com.android.systemui.statusbar.notification.collection.provider.OnReorderingAllowedListener
import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider
import com.android.systemui.statusbar.policy.ConfigurationController
-import com.android.systemui.util.concurrency.DelayableExecutor
+import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.time.FakeSystemClock
@@ -89,7 +90,6 @@ class MediaCarouselControllerTest : SysuiTestCase() {
@Mock lateinit var mediaHostStatesManager: MediaHostStatesManager
@Mock lateinit var mediaHostState: MediaHostState
@Mock lateinit var activityStarter: ActivityStarter
- @Mock @Main private lateinit var executor: DelayableExecutor
@Mock lateinit var mediaDataManager: MediaDataManager
@Mock lateinit var configurationController: ConfigurationController
@Mock lateinit var falsingCollector: FalsingCollector
@@ -113,11 +113,15 @@ class MediaCarouselControllerTest : SysuiTestCase() {
private val clock = FakeSystemClock()
private lateinit var mediaCarouselController: MediaCarouselController
+ private lateinit var mainExecutor: FakeExecutor
+ private lateinit var backgroundExecutor: FakeExecutor
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
transitionRepository = FakeKeyguardTransitionRepository()
+ mainExecutor = FakeExecutor(clock)
+ backgroundExecutor = FakeExecutor(clock)
mediaCarouselController =
MediaCarouselController(
context,
@@ -126,7 +130,8 @@ class MediaCarouselControllerTest : SysuiTestCase() {
mediaHostStatesManager,
activityStarter,
clock,
- executor,
+ mainExecutor,
+ backgroundExecutor,
mediaDataManager,
configurationController,
falsingCollector,
@@ -401,6 +406,7 @@ class MediaCarouselControllerTest : SysuiTestCase() {
resumption = true
)
)
+ runAllReady()
assertEquals(
MediaPlayerData.getMediaPlayerIndex("paused local"),
@@ -510,6 +516,8 @@ class MediaCarouselControllerTest : SysuiTestCase() {
false
)
mediaCarouselController.shouldScrollToKey = true
+ runAllReady()
+
// switching between media players.
listener.value.onMediaDataLoaded(
"playing local",
@@ -531,6 +539,7 @@ class MediaCarouselControllerTest : SysuiTestCase() {
resumption = false
)
)
+ runAllReady()
assertEquals(
MediaPlayerData.getMediaPlayerIndex("paused local"),
@@ -555,6 +564,7 @@ class MediaCarouselControllerTest : SysuiTestCase() {
resumption = false
)
)
+ runAllReady()
var playerIndex = MediaPlayerData.getMediaPlayerIndex("playing local")
assertEquals(
@@ -577,6 +587,8 @@ class MediaCarouselControllerTest : SysuiTestCase() {
packageName = "PACKAGE_NAME"
)
)
+ runAllReady()
+
playerIndex = MediaPlayerData.getMediaPlayerIndex("playing local")
assertEquals(playerIndex, 0)
}
@@ -674,6 +686,8 @@ class MediaCarouselControllerTest : SysuiTestCase() {
@Test
fun testOnConfigChanged_playersAreAddedBack() {
+ mediaCarouselController.pageIndicator = pageIndicator
+
listener.value.onMediaDataLoaded(
"playing local",
null,
@@ -694,11 +708,15 @@ class MediaCarouselControllerTest : SysuiTestCase() {
resumption = false
)
)
+ runAllReady()
val playersSize = MediaPlayerData.players().size
configListener.value.onConfigChanged(Configuration())
+ runAllReady()
+ verify(pageIndicator).tintList =
+ ColorStateList.valueOf(context.getColor(R.color.media_paging_indicator))
assertEquals(playersSize, MediaPlayerData.players().size)
assertEquals(
MediaPlayerData.getMediaPlayerIndex("playing local"),
@@ -707,6 +725,93 @@ class MediaCarouselControllerTest : SysuiTestCase() {
}
@Test
+ fun testOnUiModeChanged_playersAreAddedBack() {
+ mediaCarouselController.pageIndicator = pageIndicator
+
+ listener.value.onMediaDataLoaded(
+ "paused local",
+ null,
+ DATA.copy(
+ active = true,
+ isPlaying = false,
+ playbackLocation = MediaData.PLAYBACK_LOCAL,
+ resumption = false
+ )
+ )
+ runAllReady()
+
+ val playersSize = MediaPlayerData.players().size
+ configListener.value.onUiModeChanged()
+ runAllReady()
+
+ verify(pageIndicator).tintList =
+ ColorStateList.valueOf(context.getColor(R.color.media_paging_indicator))
+ assertEquals(playersSize, MediaPlayerData.players().size)
+ assertEquals(
+ MediaPlayerData.getMediaPlayerIndex("paused local"),
+ mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex
+ )
+ }
+
+ @Test
+ fun testOnDensityOrFontScaleChanged_playersAreAddedBack() {
+ mediaCarouselController.pageIndicator = pageIndicator
+
+ listener.value.onMediaDataLoaded(
+ "paused local",
+ null,
+ DATA.copy(
+ active = true,
+ isPlaying = false,
+ playbackLocation = MediaData.PLAYBACK_LOCAL,
+ resumption = false
+ )
+ )
+ runAllReady()
+
+ val playersSize = MediaPlayerData.players().size
+ configListener.value.onDensityOrFontScaleChanged()
+ runAllReady()
+
+ verify(pageIndicator).tintList =
+ ColorStateList.valueOf(context.getColor(R.color.media_paging_indicator))
+ assertEquals(playersSize, MediaPlayerData.players().size)
+ assertEquals(
+ MediaPlayerData.getMediaPlayerIndex("paused local"),
+ mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex
+ )
+ }
+
+ @Test
+ fun testOnThemeChanged_playersAreAddedBack() {
+ mediaCarouselController.pageIndicator = pageIndicator
+
+ listener.value.onMediaDataLoaded(
+ "paused local",
+ null,
+ DATA.copy(
+ active = true,
+ isPlaying = false,
+ playbackLocation = MediaData.PLAYBACK_LOCAL,
+ resumption = false
+ )
+ )
+ runAllReady()
+
+ val playersSize = MediaPlayerData.players().size
+ configListener.value.onThemeChanged()
+ runAllReady()
+
+ verify(pageIndicator).tintList =
+ ColorStateList.valueOf(context.getColor(R.color.media_paging_indicator))
+ assertEquals(playersSize, MediaPlayerData.players().size)
+ assertEquals(
+ MediaPlayerData.getMediaPlayerIndex("paused local"),
+ mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex
+ )
+ }
+
+ @Test
fun testRecommendation_persistentEnabled_newSmartspaceLoaded_updatesSort() {
testRecommendation_persistentEnabled_inactiveSmartspaceDataLoaded_isAdded()
@@ -832,4 +937,9 @@ class MediaCarouselControllerTest : SysuiTestCase() {
// Verify that seekbar listening attribute in media control panel is set to false.
verify(panel, times(MediaPlayerData.players().size)).listening = false
}
+
+ private fun runAllReady() {
+ backgroundExecutor.runAllReady()
+ mainExecutor.runAllReady()
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt
index 4fc9ca71aeaa..85e8d072bd99 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt
@@ -70,8 +70,7 @@ class MediaTttUtilsTest : SysuiTestCase() {
context,
appPackageName = null,
isReceiver = false,
- ) {
- }
+ ) {}
assertThat(iconInfo.isAppIcon).isFalse()
assertThat(iconInfo.contentDescription.loadContentDescription(context))
@@ -86,8 +85,7 @@ class MediaTttUtilsTest : SysuiTestCase() {
context,
appPackageName = null,
isReceiver = true,
- ) {
- }
+ ) {}
assertThat(iconInfo.isAppIcon).isFalse()
assertThat(iconInfo.contentDescription.loadContentDescription(context))
@@ -119,8 +117,7 @@ class MediaTttUtilsTest : SysuiTestCase() {
context,
appPackageName = "fakePackageName",
isReceiver = false,
- ) {
- }
+ ) {}
assertThat(iconInfo.isAppIcon).isFalse()
assertThat(iconInfo.contentDescription.loadContentDescription(context))
@@ -135,8 +132,7 @@ class MediaTttUtilsTest : SysuiTestCase() {
context,
appPackageName = "fakePackageName",
isReceiver = true,
- ) {
- }
+ ) {}
assertThat(iconInfo.isAppIcon).isFalse()
assertThat(iconInfo.contentDescription.loadContentDescription(context))
@@ -154,7 +150,9 @@ class MediaTttUtilsTest : SysuiTestCase() {
context,
appPackageName = "fakePackageName",
isReceiver = false
- ) { exceptionTriggered = true }
+ ) {
+ exceptionTriggered = true
+ }
assertThat(exceptionTriggered).isTrue()
}
@@ -167,7 +165,9 @@ class MediaTttUtilsTest : SysuiTestCase() {
context,
appPackageName = "fakePackageName",
isReceiver = true
- ) { exceptionTriggered = true }
+ ) {
+ exceptionTriggered = true
+ }
assertThat(exceptionTriggered).isTrue()
}
@@ -179,8 +179,7 @@ class MediaTttUtilsTest : SysuiTestCase() {
context,
PACKAGE_NAME,
isReceiver = false,
- ) {
- }
+ ) {}
assertThat(iconInfo.isAppIcon).isTrue()
assertThat(iconInfo.icon).isEqualTo(MediaTttIcon.Loaded(appIconFromPackageName))
@@ -194,8 +193,7 @@ class MediaTttUtilsTest : SysuiTestCase() {
context,
PACKAGE_NAME,
isReceiver = true,
- ) {
- }
+ ) {}
assertThat(iconInfo.isAppIcon).isTrue()
assertThat(iconInfo.icon).isEqualTo(MediaTttIcon.Loaded(appIconFromPackageName))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/DynamicColorTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/DynamicColorTest.java
index 41ac3213d402..d364f47d78b5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/monet/DynamicColorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/DynamicColorTest.java
@@ -18,13 +18,21 @@ package com.android.systemui.monet;
import static com.android.systemui.monet.utils.ArgbSubject.assertThat;
+import static org.junit.Assert.assertTrue;
+
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.monet.contrast.Contrast;
import com.android.systemui.monet.dynamiccolor.DynamicColor;
+import com.android.systemui.monet.dynamiccolor.MaterialDynamicColors;
import com.android.systemui.monet.dynamiccolor.ToneDeltaConstraint;
import com.android.systemui.monet.dynamiccolor.TonePolarity;
import com.android.systemui.monet.hct.Hct;
+import com.android.systemui.monet.scheme.DynamicScheme;
+import com.android.systemui.monet.scheme.SchemeContent;
+import com.android.systemui.monet.scheme.SchemeFidelity;
+import com.android.systemui.monet.scheme.SchemeMonochrome;
import com.android.systemui.monet.scheme.SchemeTonalSpot;
import org.junit.Test;
@@ -90,4 +98,92 @@ public final class DynamicColorTest extends SysuiTestCase {
final SchemeTonalSpot darkScheme = new SchemeTonalSpot(Hct.fromInt(0xff4285f4), true, 0.0);
assertThat(dynamicColor.getArgb(darkScheme)).isSameColorAs(0x33ffffff);
}
+
+ @Test
+ public void respectsContrast() {
+ final Hct[] seedColors =
+ new Hct[]{
+ Hct.fromInt(0xFFFF0000),
+ Hct.fromInt(0xFFFFFF00),
+ Hct.fromInt(0xFF00FF00),
+ Hct.fromInt(0xFF0000FF)
+ };
+
+ final double[] contrastLevels = {-1.0, -0.5, 0.0, 0.5, 1.0};
+
+ for (Hct seedColor : seedColors) {
+ for (double contrastLevel : contrastLevels) {
+ for (boolean isDark : new boolean[]{false, true}) {
+ final DynamicScheme[] schemes =
+ new DynamicScheme[]{
+ new SchemeContent(seedColor, isDark, contrastLevel),
+ new SchemeMonochrome(seedColor, isDark, contrastLevel),
+ new SchemeTonalSpot(seedColor, isDark, contrastLevel),
+ new SchemeFidelity(seedColor, isDark, contrastLevel)
+ };
+ for (final DynamicScheme scheme : schemes) {
+ assertTrue(
+ pairSatisfiesContrast(
+ scheme, MaterialDynamicColors.onPrimary,
+ MaterialDynamicColors.primary));
+ assertTrue(
+ pairSatisfiesContrast(
+ scheme,
+ MaterialDynamicColors.onPrimaryContainer,
+ MaterialDynamicColors.primaryContainer));
+ assertTrue(
+ pairSatisfiesContrast(
+ scheme, MaterialDynamicColors.onSecondary,
+ MaterialDynamicColors.secondary));
+ assertTrue(
+ pairSatisfiesContrast(
+ scheme,
+ MaterialDynamicColors.onSecondaryContainer,
+ MaterialDynamicColors.secondaryContainer));
+ assertTrue(
+ pairSatisfiesContrast(
+ scheme, MaterialDynamicColors.onTertiary,
+ MaterialDynamicColors.tertiary));
+ assertTrue(
+ pairSatisfiesContrast(
+ scheme,
+ MaterialDynamicColors.onTertiaryContainer,
+ MaterialDynamicColors.tertiaryContainer));
+ assertTrue(
+ pairSatisfiesContrast(
+ scheme, MaterialDynamicColors.onError,
+ MaterialDynamicColors.error));
+ assertTrue(
+ pairSatisfiesContrast(
+ scheme,
+ MaterialDynamicColors.onErrorContainer,
+ MaterialDynamicColors.errorContainer));
+ assertTrue(
+ pairSatisfiesContrast(
+ scheme, MaterialDynamicColors.onBackground,
+ MaterialDynamicColors.background));
+ assertTrue(
+ pairSatisfiesContrast(
+ scheme,
+ MaterialDynamicColors.onSurfaceVariant,
+ MaterialDynamicColors.surfaceVariant));
+ assertTrue(
+ pairSatisfiesContrast(
+ scheme,
+ MaterialDynamicColors.onSurfaceInverse,
+ MaterialDynamicColors.surfaceInverse));
+ }
+ }
+ }
+ }
+ }
+
+ private boolean pairSatisfiesContrast(DynamicScheme scheme, DynamicColor fg, DynamicColor bg) {
+ double fgTone = fg.getHct(scheme).getTone();
+ double bgTone = bg.getHct(scheme).getTone();
+ // TODO(b/270915664) - Fix inconsistencies.
+ // TODO(b/270915664) - Minimum requirement should be 4.5 when not reducing contrast.
+ double minimumRequirement = 3.0;
+ return Contrast.ratioOfTones(fgTone, bgTone) >= minimumRequirement;
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
index 2212bbda8021..89405c109224 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
@@ -141,8 +141,8 @@ public class NavigationBarControllerTest extends SysuiTestCase {
@Test
public void testCreateNavigationBarsIncludeDefaultTrue() {
- // Tablets may be using taskbar and the logic is different
- mNavigationBarController.mIsTablet = false;
+ // Large screens may be using taskbar and the logic is different
+ mNavigationBarController.mIsLargeScreen = false;
doNothing().when(mNavigationBarController).createNavigationBar(any(), any(), any());
mNavigationBarController.createNavigationBars(true, null);
@@ -290,7 +290,7 @@ public class NavigationBarControllerTest extends SysuiTestCase {
@Test
public void testConfigurationChange_taskbarNotInitialized() {
Configuration configuration = mContext.getResources().getConfiguration();
- when(Utilities.isTablet(any())).thenReturn(true);
+ when(Utilities.isLargeScreen(any())).thenReturn(true);
mNavigationBarController.onConfigChanged(configuration);
verify(mTaskbarDelegate, never()).onConfigurationChanged(configuration);
}
@@ -298,7 +298,7 @@ public class NavigationBarControllerTest extends SysuiTestCase {
@Test
public void testConfigurationChange_taskbarInitialized() {
Configuration configuration = mContext.getResources().getConfiguration();
- when(Utilities.isTablet(any())).thenReturn(true);
+ when(Utilities.isLargeScreen(any())).thenReturn(true);
when(mTaskbarDelegate.isInitialized()).thenReturn(true);
mNavigationBarController.onConfigChanged(configuration);
verify(mTaskbarDelegate, times(1)).onConfigurationChanged(configuration);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt
index 537dfb821fef..1c9336a3fc66 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt
@@ -13,6 +13,7 @@ import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.phone.AutoHideController
import com.android.systemui.statusbar.phone.LightBarController
import com.android.systemui.statusbar.phone.LightBarTransitionsController
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
import com.android.wm.shell.back.BackAnimation
import com.android.wm.shell.pip.Pip
import org.junit.Before
@@ -66,6 +67,8 @@ class TaskbarDelegateTest : SysuiTestCase() {
lateinit var mBackAnimation: BackAnimation
@Mock
lateinit var mCurrentSysUiState: NavBarHelper.CurrentSysuiState
+ @Mock
+ lateinit var mStatusBarKeyguardViewManager: StatusBarKeyguardViewManager
@Before
fun setup() {
@@ -76,7 +79,7 @@ class TaskbarDelegateTest : SysuiTestCase() {
`when`(mSysUiState.setFlag(anyInt(), anyBoolean())).thenReturn(mSysUiState)
mTaskStackChangeListeners = TaskStackChangeListeners.getTestInstance()
mTaskbarDelegate = TaskbarDelegate(context, mEdgeBackGestureHandlerFactory,
- mLightBarControllerFactory)
+ mLightBarControllerFactory, mStatusBarKeyguardViewManager)
mTaskbarDelegate.setDependencies(mCommandQueue, mOverviewProxyService, mNavBarHelper,
mNavigationModeController, mSysUiState, mDumpManager, mAutoHideController,
mLightBarController, mOptionalPip, mBackAnimation, mTaskStackChangeListeners)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
index 39c4e06ff0bb..376b7cc70150 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
@@ -16,40 +16,36 @@
package com.android.systemui.notetask
import android.app.KeyguardManager
+import android.app.admin.DevicePolicyManager
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.UserManager
-import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.filters.SmallTest
import androidx.test.runner.AndroidJUnit4
-import com.android.internal.logging.UiEventLogger
import com.android.systemui.SysuiTestCase
-import com.android.systemui.notetask.NoteTaskController.Companion.INTENT_EXTRA_USE_STYLUS_MODE
-import com.android.systemui.notetask.NoteTaskController.ShowNoteTaskUiEvent
-import com.android.systemui.notetask.NoteTaskInfoResolver.NoteTaskInfo
import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.whenever
+import com.android.wm.shell.bubbles.Bubble
import com.android.wm.shell.bubbles.Bubbles
import com.google.common.truth.Truth.assertThat
import java.util.Optional
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyZeroInteractions
import org.mockito.MockitoAnnotations
-/**
- * Tests for [NoteTaskController].
- *
- * Build/Install/Run:
- * - atest SystemUITests:NoteTaskControllerTest
- */
+/** atest SystemUITests:NoteTaskControllerTest */
@SmallTest
@RunWith(AndroidJUnit4::class)
internal class NoteTaskControllerTest : SysuiTestCase() {
@@ -58,191 +54,301 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
@Mock lateinit var packageManager: PackageManager
@Mock lateinit var resolver: NoteTaskInfoResolver
@Mock lateinit var bubbles: Bubbles
- @Mock lateinit var optionalBubbles: Optional<Bubbles>
@Mock lateinit var keyguardManager: KeyguardManager
- @Mock lateinit var optionalKeyguardManager: Optional<KeyguardManager>
- @Mock lateinit var optionalUserManager: Optional<UserManager>
@Mock lateinit var userManager: UserManager
- @Mock lateinit var uiEventLogger: UiEventLogger
+ @Mock lateinit var eventLogger: NoteTaskEventLogger
+ @Mock private lateinit var userTracker: UserTracker
+ @Mock private lateinit var devicePolicyManager: DevicePolicyManager
+
+ private val noteTaskInfo = NoteTaskInfo(packageName = NOTES_PACKAGE_NAME, uid = NOTES_UID)
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
whenever(context.packageManager).thenReturn(packageManager)
- whenever(resolver.resolveInfo()).thenReturn(NoteTaskInfo(NOTES_PACKAGE_NAME, NOTES_UID))
- whenever(optionalBubbles.orElse(null)).thenReturn(bubbles)
- whenever(optionalKeyguardManager.orElse(null)).thenReturn(keyguardManager)
- whenever(optionalUserManager.orElse(null)).thenReturn(userManager)
+ whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(noteTaskInfo)
whenever(userManager.isUserUnlocked).thenReturn(true)
+ whenever(
+ devicePolicyManager.getKeyguardDisabledFeatures(
+ /* admin= */ eq(null),
+ /* userHandle= */ anyInt()
+ )
+ )
+ .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE)
}
- private fun createNoteTaskController(isEnabled: Boolean = true): NoteTaskController {
- return NoteTaskController(
+ private fun createNoteTaskController(
+ isEnabled: Boolean = true,
+ bubbles: Bubbles? = this.bubbles,
+ keyguardManager: KeyguardManager? = this.keyguardManager,
+ userManager: UserManager? = this.userManager,
+ ): NoteTaskController =
+ NoteTaskController(
context = context,
resolver = resolver,
- optionalBubbles = optionalBubbles,
- optionalKeyguardManager = optionalKeyguardManager,
- optionalUserManager = optionalUserManager,
+ eventLogger = eventLogger,
+ optionalBubbles = Optional.ofNullable(bubbles),
+ optionalUserManager = Optional.ofNullable(userManager),
+ optionalKeyguardManager = Optional.ofNullable(keyguardManager),
isEnabled = isEnabled,
- uiEventLogger = uiEventLogger,
+ devicePolicyManager = devicePolicyManager,
+ userTracker = userTracker,
)
+
+ // region onBubbleExpandChanged
+ @Test
+ fun onBubbleExpandChanged_expanding_logNoteTaskOpened() {
+ val expectedInfo = noteTaskInfo.copy(isKeyguardLocked = false, isInMultiWindowMode = false)
+
+ createNoteTaskController()
+ .apply { infoReference.set(expectedInfo) }
+ .onBubbleExpandChanged(
+ isExpanding = true,
+ key = Bubble.KEY_APP_BUBBLE,
+ )
+
+ verify(eventLogger).logNoteTaskOpened(expectedInfo)
+ verifyZeroInteractions(context, bubbles, keyguardManager, userManager)
}
- // region showNoteTask
@Test
- fun showNoteTask_keyguardIsLocked_shouldStartActivityAndLogUiEvent() {
- whenever(keyguardManager.isKeyguardLocked).thenReturn(true)
+ fun onBubbleExpandChanged_collapsing_logNoteTaskClosed() {
+ val expectedInfo = noteTaskInfo.copy(isKeyguardLocked = false, isInMultiWindowMode = false)
createNoteTaskController()
- .showNoteTask(
- isInMultiWindowMode = false,
- uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE,
+ .apply { infoReference.set(expectedInfo) }
+ .onBubbleExpandChanged(
+ isExpanding = false,
+ key = Bubble.KEY_APP_BUBBLE,
)
- val intentCaptor = argumentCaptor<Intent>()
- verify(context).startActivity(capture(intentCaptor))
- intentCaptor.value.let { intent ->
- assertThat(intent.action).isEqualTo(NoteTaskController.ACTION_CREATE_NOTE)
- assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
- assertThat(intent.flags).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK)
- assertThat(intent.getBooleanExtra(INTENT_EXTRA_USE_STYLUS_MODE, false)).isTrue()
- }
- verifyZeroInteractions(bubbles)
- verify(uiEventLogger)
- .log(
- ShowNoteTaskUiEvent.NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE,
- NOTES_UID,
- NOTES_PACKAGE_NAME
+ verify(eventLogger).logNoteTaskClosed(expectedInfo)
+ verifyZeroInteractions(context, bubbles, keyguardManager, userManager)
+ }
+
+ @Test
+ fun onBubbleExpandChanged_expandingAndKeyguardLocked_doNothing() {
+ val expectedInfo = noteTaskInfo.copy(isKeyguardLocked = true, isInMultiWindowMode = false)
+
+ createNoteTaskController()
+ .apply { infoReference.set(expectedInfo) }
+ .onBubbleExpandChanged(
+ isExpanding = true,
+ key = Bubble.KEY_APP_BUBBLE,
)
+
+ verifyZeroInteractions(context, bubbles, keyguardManager, userManager, eventLogger)
}
@Test
- fun showNoteTask_keyguardIsUnlocked_shouldStartBubblesAndLogUiEvent() {
- whenever(keyguardManager.isKeyguardLocked).thenReturn(false)
+ fun onBubbleExpandChanged_notExpandingAndKeyguardLocked_doNothing() {
+ val expectedInfo = noteTaskInfo.copy(isKeyguardLocked = true, isInMultiWindowMode = false)
createNoteTaskController()
- .showNoteTask(
+ .apply { infoReference.set(expectedInfo) }
+ .onBubbleExpandChanged(
+ isExpanding = false,
+ key = Bubble.KEY_APP_BUBBLE,
+ )
+
+ verifyZeroInteractions(context, bubbles, keyguardManager, userManager, eventLogger)
+ }
+
+ @Test
+ fun onBubbleExpandChanged_expandingAndInMultiWindowMode_doNothing() {
+ val expectedInfo = noteTaskInfo.copy(isKeyguardLocked = false, isInMultiWindowMode = true)
+
+ createNoteTaskController()
+ .apply { infoReference.set(expectedInfo) }
+ .onBubbleExpandChanged(
+ isExpanding = true,
+ key = Bubble.KEY_APP_BUBBLE,
+ )
+
+ verifyZeroInteractions(context, bubbles, keyguardManager, userManager)
+ }
+
+ @Test
+ fun onBubbleExpandChanged_notExpandingAndInMultiWindowMode_doNothing() {
+ val expectedInfo = noteTaskInfo.copy(isKeyguardLocked = false, isInMultiWindowMode = true)
+
+ createNoteTaskController()
+ .apply { infoReference.set(expectedInfo) }
+ .onBubbleExpandChanged(
+ isExpanding = false,
+ key = Bubble.KEY_APP_BUBBLE,
+ )
+
+ verifyZeroInteractions(context, bubbles, keyguardManager, userManager, eventLogger)
+ }
+
+ @Test
+ fun onBubbleExpandChanged_notKeyAppBubble_shouldDoNothing() {
+ createNoteTaskController()
+ .onBubbleExpandChanged(
+ isExpanding = true,
+ key = "any other key",
+ )
+
+ verifyZeroInteractions(context, bubbles, keyguardManager, userManager, eventLogger)
+ }
+
+ @Test
+ fun onBubbleExpandChanged_flagDisabled_shouldDoNothing() {
+ createNoteTaskController(isEnabled = false)
+ .onBubbleExpandChanged(
+ isExpanding = true,
+ key = Bubble.KEY_APP_BUBBLE,
+ )
+
+ verifyZeroInteractions(context, bubbles, keyguardManager, userManager, eventLogger)
+ }
+ // endregion
+
+ // region showNoteTask
+ @Test
+ fun showNoteTask_keyguardIsLocked_shouldStartActivityAndLogUiEvent() {
+ val expectedInfo =
+ noteTaskInfo.copy(
+ entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
isInMultiWindowMode = false,
- uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON,
+ isKeyguardLocked = true,
+ )
+ whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
+ whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
+
+ createNoteTaskController()
+ .showNoteTask(
+ entryPoint = expectedInfo.entryPoint!!,
+ isInMultiWindowMode = expectedInfo.isInMultiWindowMode,
)
- verifyZeroInteractions(context)
val intentCaptor = argumentCaptor<Intent>()
- verify(bubbles).showOrHideAppBubble(capture(intentCaptor))
+ verify(context).startActivity(capture(intentCaptor))
intentCaptor.value.let { intent ->
- assertThat(intent.action).isEqualTo(NoteTaskController.ACTION_CREATE_NOTE)
+ assertThat(intent.action).isEqualTo(Intent.ACTION_CREATE_NOTE)
assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
assertThat(intent.flags).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK)
- assertThat(intent.getBooleanExtra(INTENT_EXTRA_USE_STYLUS_MODE, false)).isTrue()
+ assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, false)).isTrue()
}
- verify(uiEventLogger)
- .log(
- ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON,
- NOTES_UID,
- NOTES_PACKAGE_NAME
- )
+ verify(eventLogger).logNoteTaskOpened(expectedInfo)
+ verifyZeroInteractions(bubbles)
}
@Test
- fun showNoteTask_keyguardIsUnlocked_uiEventIsNull_shouldStartBubblesWithoutLoggingUiEvent() {
- whenever(keyguardManager.isKeyguardLocked).thenReturn(false)
+ fun showNoteTask_keyguardIsUnlocked_shouldStartBubblesWithoutLoggingUiEvent() {
+ val expectedInfo =
+ noteTaskInfo.copy(
+ entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
+ isInMultiWindowMode = false,
+ isKeyguardLocked = false,
+ )
+ whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
+ whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
- createNoteTaskController().showNoteTask(isInMultiWindowMode = false, uiEvent = null)
+ createNoteTaskController()
+ .showNoteTask(
+ entryPoint = expectedInfo.entryPoint!!,
+ isInMultiWindowMode = expectedInfo.isInMultiWindowMode,
+ )
verifyZeroInteractions(context)
val intentCaptor = argumentCaptor<Intent>()
verify(bubbles).showOrHideAppBubble(capture(intentCaptor))
intentCaptor.value.let { intent ->
- assertThat(intent.action).isEqualTo(NoteTaskController.ACTION_CREATE_NOTE)
+ assertThat(intent.action).isEqualTo(Intent.ACTION_CREATE_NOTE)
assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
assertThat(intent.flags).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK)
- assertThat(intent.getBooleanExtra(INTENT_EXTRA_USE_STYLUS_MODE, false)).isTrue()
+ assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, false)).isTrue()
}
- verifyZeroInteractions(uiEventLogger)
+ verifyZeroInteractions(eventLogger)
}
@Test
fun showNoteTask_isInMultiWindowMode_shouldStartActivityAndLogUiEvent() {
- whenever(keyguardManager.isKeyguardLocked).thenReturn(false)
+ val expectedInfo =
+ noteTaskInfo.copy(
+ entryPoint = NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT,
+ isInMultiWindowMode = true,
+ isKeyguardLocked = false,
+ )
+ whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
+ whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
createNoteTaskController()
.showNoteTask(
- isInMultiWindowMode = true,
- uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_SHORTCUT,
+ entryPoint = expectedInfo.entryPoint!!,
+ isInMultiWindowMode = expectedInfo.isInMultiWindowMode,
)
val intentCaptor = argumentCaptor<Intent>()
verify(context).startActivity(capture(intentCaptor))
intentCaptor.value.let { intent ->
- assertThat(intent.action).isEqualTo(NoteTaskController.ACTION_CREATE_NOTE)
+ assertThat(intent.action).isEqualTo(Intent.ACTION_CREATE_NOTE)
assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
assertThat(intent.flags).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK)
- assertThat(intent.getBooleanExtra(INTENT_EXTRA_USE_STYLUS_MODE, false)).isTrue()
+ assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, false)).isTrue()
}
+ verify(eventLogger).logNoteTaskOpened(expectedInfo)
verifyZeroInteractions(bubbles)
- verify(uiEventLogger)
- .log(ShowNoteTaskUiEvent.NOTE_OPENED_VIA_SHORTCUT, NOTES_UID, NOTES_PACKAGE_NAME)
}
@Test
fun showNoteTask_bubblesIsNull_shouldDoNothing() {
- whenever(optionalBubbles.orElse(null)).thenReturn(null)
-
- createNoteTaskController()
+ createNoteTaskController(bubbles = null)
.showNoteTask(
+ entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
isInMultiWindowMode = false,
- uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON
)
- verifyZeroInteractions(context, bubbles, uiEventLogger)
+ verifyZeroInteractions(context, bubbles, eventLogger)
}
@Test
fun showNoteTask_keyguardManagerIsNull_shouldDoNothing() {
- whenever(optionalKeyguardManager.orElse(null)).thenReturn(null)
-
- createNoteTaskController()
+ createNoteTaskController(keyguardManager = null)
.showNoteTask(
+ entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
isInMultiWindowMode = false,
- uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON,
)
- verifyZeroInteractions(context, bubbles, uiEventLogger)
+ verifyZeroInteractions(context, bubbles, eventLogger)
}
@Test
fun showNoteTask_userManagerIsNull_shouldDoNothing() {
- whenever(optionalUserManager.orElse(null)).thenReturn(null)
-
- createNoteTaskController()
+ createNoteTaskController(userManager = null)
.showNoteTask(
+ entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
isInMultiWindowMode = false,
- uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON,
)
- verifyZeroInteractions(context, bubbles, uiEventLogger)
+ verifyZeroInteractions(context, bubbles, eventLogger)
}
@Test
fun showNoteTask_intentResolverReturnsNull_shouldDoNothing() {
- whenever(resolver.resolveInfo()).thenReturn(null)
+ whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(null)
createNoteTaskController()
.showNoteTask(
+ entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
isInMultiWindowMode = false,
- uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON,
)
- verifyZeroInteractions(context, bubbles, uiEventLogger)
+ verifyZeroInteractions(context, bubbles, eventLogger)
}
@Test
fun showNoteTask_flagDisabled_shouldDoNothing() {
createNoteTaskController(isEnabled = false)
- .showNoteTask(uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON)
+ .showNoteTask(
+ entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
+ isInMultiWindowMode = false,
+ )
- verifyZeroInteractions(context, bubbles, uiEventLogger)
+ verifyZeroInteractions(context, bubbles, eventLogger)
}
@Test
@@ -251,11 +357,11 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
createNoteTaskController()
.showNoteTask(
+ entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
isInMultiWindowMode = false,
- uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON,
)
- verifyZeroInteractions(context, bubbles, uiEventLogger)
+ verifyZeroInteractions(context, bubbles, eventLogger)
}
// endregion
@@ -291,6 +397,102 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
}
// endregion
+ // region keyguard policy
+ @Test
+ fun showNoteTask_keyguardLocked_keyguardDisableShortcutsAll_shouldDoNothing() {
+ whenever(keyguardManager.isKeyguardLocked).thenReturn(true)
+ whenever(
+ devicePolicyManager.getKeyguardDisabledFeatures(
+ /* admin= */ eq(null),
+ /* userHandle= */ anyInt()
+ )
+ )
+ .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL)
+
+ createNoteTaskController()
+ .showNoteTask(
+ isInMultiWindowMode = false,
+ entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE
+ )
+
+ verifyZeroInteractions(context, bubbles, eventLogger)
+ }
+
+ @Test
+ fun showNoteTask_keyguardLocked_keyguardDisableFeaturesAll_shouldDoNothing() {
+ whenever(keyguardManager.isKeyguardLocked).thenReturn(true)
+ whenever(
+ devicePolicyManager.getKeyguardDisabledFeatures(
+ /* admin= */ eq(null),
+ /* userHandle= */ anyInt()
+ )
+ )
+ .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL)
+
+ createNoteTaskController()
+ .showNoteTask(
+ isInMultiWindowMode = false,
+ entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE
+ )
+
+ verifyZeroInteractions(context, bubbles, eventLogger)
+ }
+
+ @Test
+ fun showNoteTask_keyguardUnlocked_keyguardDisableShortcutsAll_shouldStartBubble() {
+ whenever(keyguardManager.isKeyguardLocked).thenReturn(false)
+ whenever(
+ devicePolicyManager.getKeyguardDisabledFeatures(
+ /* admin= */ eq(null),
+ /* userHandle= */ anyInt()
+ )
+ )
+ .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL)
+
+ createNoteTaskController()
+ .showNoteTask(
+ isInMultiWindowMode = false,
+ entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE
+ )
+
+ val intentCaptor = argumentCaptor<Intent>()
+ verify(bubbles).showOrHideAppBubble(capture(intentCaptor))
+ intentCaptor.value.let { intent ->
+ assertThat(intent.action).isEqualTo(NoteTaskController.ACTION_CREATE_NOTE)
+ assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
+ assertThat(intent.flags).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK)
+ assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, false)).isTrue()
+ }
+ }
+
+ @Test
+ fun showNoteTask_keyguardUnlocked_keyguardDisableFeaturesAll_shouldStartBubble() {
+ whenever(keyguardManager.isKeyguardLocked).thenReturn(false)
+ whenever(
+ devicePolicyManager.getKeyguardDisabledFeatures(
+ /* admin= */ eq(null),
+ /* userHandle= */ anyInt()
+ )
+ )
+ .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL)
+
+ createNoteTaskController()
+ .showNoteTask(
+ isInMultiWindowMode = false,
+ entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE
+ )
+
+ val intentCaptor = argumentCaptor<Intent>()
+ verify(bubbles).showOrHideAppBubble(capture(intentCaptor))
+ intentCaptor.value.let { intent ->
+ assertThat(intent.action).isEqualTo(NoteTaskController.ACTION_CREATE_NOTE)
+ assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
+ assertThat(intent.flags).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK)
+ assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, false)).isTrue()
+ }
+ }
+ // endregion
+
private companion object {
const val NOTES_PACKAGE_NAME = "com.android.note.app"
const val NOTES_UID = 123456
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskEventLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskEventLoggerTest.kt
new file mode 100644
index 000000000000..a4df346776a0
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskEventLoggerTest.kt
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2023 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.notetask
+
+import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.logging.UiEventLogger
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_CLOSED_VIA_STYLUS_TAIL_BUTTON
+import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_CLOSED_VIA_STYLUS_TAIL_BUTTON_LOCKED
+import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE
+import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_OPENED_VIA_SHORTCUT
+import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON
+import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON_LOCKED
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyNoMoreInteractions
+import org.mockito.MockitoAnnotations
+
+/** atest SystemUITests:MonitoringNoteTaskEventListenerTest */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+internal class NoteTaskEventLoggerTest : SysuiTestCase() {
+
+ @Mock lateinit var uiEventLogger: UiEventLogger
+
+ private fun createNoteTaskEventLogger(): NoteTaskEventLogger =
+ NoteTaskEventLogger(uiEventLogger)
+
+ private fun createNoteTaskInfo(): NoteTaskInfo =
+ NoteTaskInfo(packageName = NOTES_PACKAGE_NAME, uid = NOTES_UID)
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ }
+
+ // region logNoteTaskOpened
+ @Test
+ fun logNoteTaskOpened_entryPointWidgetPickerShortcut_noteOpenedViaShortcut() {
+ val info = createNoteTaskInfo().copy(entryPoint = NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT)
+
+ createNoteTaskEventLogger().logNoteTaskOpened(info)
+
+ val expected = NOTE_OPENED_VIA_SHORTCUT
+ verify(uiEventLogger).log(expected, info.uid, info.packageName)
+ }
+
+ @Test
+ fun onNoteTaskBubbleExpanded_entryPointQuickAffordance_noteOpenedViaQuickAffordance() {
+ val info = createNoteTaskInfo().copy(entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE)
+
+ createNoteTaskEventLogger().logNoteTaskOpened(info)
+
+ val expected = NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE
+ verify(uiEventLogger).log(expected, info.uid, info.packageName)
+ }
+
+ @Test
+ fun onNoteTaskBubbleExpanded_entryPointTailButtonAndIsKeyguardUnlocked_noteOpenedViaTailButtonUnlocked() { // ktlint-disable max-line-length
+ val info =
+ createNoteTaskInfo()
+ .copy(
+ entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
+ isKeyguardLocked = false,
+ )
+
+ createNoteTaskEventLogger().logNoteTaskOpened(info)
+
+ val expected = NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON
+ verify(uiEventLogger).log(expected, info.uid, info.packageName)
+ }
+
+ @Test
+ fun onNoteTaskBubbleExpanded_entryPointTailButtonAndIsKeyguardLocked_noteOpenedViaTailButtonLocked() { // ktlint-disable max-line-length
+ val info =
+ createNoteTaskInfo()
+ .copy(
+ entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
+ isKeyguardLocked = true,
+ )
+
+ createNoteTaskEventLogger().logNoteTaskOpened(info)
+
+ val expected = NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON_LOCKED
+ verify(uiEventLogger).log(expected, info.uid, info.packageName)
+ }
+
+ @Test
+ fun onNoteTaskBubbleExpanded_noEntryPoint_noLog() {
+ val info = createNoteTaskInfo().copy(entryPoint = null)
+
+ createNoteTaskEventLogger().logNoteTaskOpened(info)
+
+ verifyNoMoreInteractions(uiEventLogger)
+ }
+ // endregion
+
+ // region logNoteTaskClosed
+ @Test
+ fun logNoteTaskClosed_entryPointTailButton_noteClosedViaTailButtonUnlocked() {
+ val info =
+ createNoteTaskInfo()
+ .copy(
+ entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
+ isKeyguardLocked = false,
+ )
+
+ createNoteTaskEventLogger().logNoteTaskClosed(info)
+
+ val expected = NOTE_CLOSED_VIA_STYLUS_TAIL_BUTTON
+ verify(uiEventLogger).log(expected, info.uid, info.packageName)
+ }
+
+ @Test
+ fun logNoteTaskClosed_entryPointTailButtonAndKeyguardLocked_noteClosedViaTailButtonLocked() {
+ val info =
+ createNoteTaskInfo()
+ .copy(
+ entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
+ isKeyguardLocked = true,
+ )
+
+ createNoteTaskEventLogger().logNoteTaskClosed(info)
+
+ val expected = NOTE_CLOSED_VIA_STYLUS_TAIL_BUTTON_LOCKED
+ verify(uiEventLogger).log(expected, info.uid, info.packageName)
+ }
+
+ @Test
+ fun logNoteTaskClosed_noEntryPoint_noLog() {
+ val info = createNoteTaskInfo().copy(entryPoint = null)
+
+ createNoteTaskEventLogger().logNoteTaskOpened(info)
+
+ verifyNoMoreInteractions(uiEventLogger)
+ }
+ // endregion
+
+ private companion object {
+ const val NOTES_PACKAGE_NAME = "com.android.note.app"
+ const val NOTES_UID = 123456
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoResolverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoResolverTest.kt
index d6495d8fe1b7..7f64f8a123e0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoResolverTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoResolverTest.kt
@@ -57,8 +57,9 @@ internal class NoteTaskInfoResolverTest : SysuiTestCase() {
fun resolveInfo_shouldReturnInfo() {
val packageName = "com.android.note.app"
val uid = 123456
- whenever(roleManager.getRoleHoldersAsUser(NoteTaskInfoResolver.ROLE_NOTES, context.user))
- .then { listOf(packageName) }
+ whenever(roleManager.getRoleHoldersAsUser(RoleManager.ROLE_NOTES, context.user)).then {
+ listOf(packageName)
+ }
whenever(
packageManager.getApplicationInfoAsUser(
eq(packageName),
@@ -78,8 +79,9 @@ internal class NoteTaskInfoResolverTest : SysuiTestCase() {
@Test
fun resolveInfo_packageManagerThrowsException_shouldReturnInfoWithZeroUid() {
val packageName = "com.android.note.app"
- whenever(roleManager.getRoleHoldersAsUser(NoteTaskInfoResolver.ROLE_NOTES, context.user))
- .then { listOf(packageName) }
+ whenever(roleManager.getRoleHoldersAsUser(RoleManager.ROLE_NOTES, context.user)).then {
+ listOf(packageName)
+ }
whenever(
packageManager.getApplicationInfoAsUser(
eq(packageName),
@@ -98,8 +100,9 @@ internal class NoteTaskInfoResolverTest : SysuiTestCase() {
@Test
fun resolveInfo_noRoleHolderIsSet_shouldReturnNull() {
- whenever(roleManager.getRoleHoldersAsUser(eq(NoteTaskInfoResolver.ROLE_NOTES), any()))
- .then { listOf<String>() }
+ whenever(roleManager.getRoleHoldersAsUser(eq(RoleManager.ROLE_NOTES), any())).then {
+ emptyList<String>()
+ }
val actual = underTest.resolveInfo()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoTest.kt
new file mode 100644
index 000000000000..7e975b6732a5
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoTest.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2023 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.notetask
+
+import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/** atest SystemUITests:NoteTaskInfoTest */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+internal class NoteTaskInfoTest : SysuiTestCase() {
+
+ private fun createNoteTaskInfo(): NoteTaskInfo =
+ NoteTaskInfo(packageName = NOTES_PACKAGE_NAME, uid = NOTES_UID)
+
+ @Test
+ fun launchMode_notInMultiWindowModeAndKeyguardUnlocked_launchModeAppBubble() {
+ val underTest =
+ createNoteTaskInfo()
+ .copy(
+ isKeyguardLocked = false,
+ isInMultiWindowMode = false,
+ )
+
+ assertThat(underTest.launchMode).isEqualTo(NoteTaskLaunchMode.AppBubble)
+ }
+
+ @Test
+ fun launchMode_inMultiWindowMode_launchModeActivity() {
+ val underTest =
+ createNoteTaskInfo()
+ .copy(
+ isKeyguardLocked = false,
+ isInMultiWindowMode = true,
+ )
+
+ assertThat(underTest.launchMode).isEqualTo(NoteTaskLaunchMode.Activity)
+ }
+
+ @Test
+ fun launchMode_keyguardLocked_launchModeActivity() {
+ val underTest =
+ createNoteTaskInfo()
+ .copy(
+ isKeyguardLocked = true,
+ isInMultiWindowMode = false,
+ )
+
+ assertThat(underTest.launchMode).isEqualTo(NoteTaskLaunchMode.Activity)
+ }
+
+ private companion object {
+ const val NOTES_PACKAGE_NAME = "com.android.note.app"
+ const val NOTES_UID = 123456
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInitializerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInitializerTest.kt
index 53720ffdff94..46e02788b2df 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInitializerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInitializerTest.kt
@@ -15,15 +15,11 @@
*/
package com.android.systemui.notetask
-import android.app.KeyguardManager
import android.test.suitebuilder.annotation.SmallTest
import android.view.KeyEvent
import androidx.test.runner.AndroidJUnit4
import com.android.systemui.SysuiTestCase
-import com.android.systemui.notetask.NoteTaskController.ShowNoteTaskUiEvent
import com.android.systemui.statusbar.CommandQueue
-import com.android.systemui.util.mockito.mock
-import com.android.systemui.util.mockito.whenever
import com.android.wm.shell.bubbles.Bubbles
import java.util.Optional
import org.junit.Before
@@ -48,27 +44,22 @@ internal class NoteTaskInitializerTest : SysuiTestCase() {
@Mock lateinit var commandQueue: CommandQueue
@Mock lateinit var bubbles: Bubbles
- @Mock lateinit var optionalBubbles: Optional<Bubbles>
@Mock lateinit var noteTaskController: NoteTaskController
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
-
- whenever(optionalBubbles.isPresent).thenReturn(true)
- whenever(optionalBubbles.orElse(null)).thenReturn(bubbles)
}
private fun createNoteTaskInitializer(
isEnabled: Boolean = true,
- optionalKeyguardManager: Optional<KeyguardManager> = Optional.empty(),
+ bubbles: Bubbles? = this.bubbles,
): NoteTaskInitializer {
return NoteTaskInitializer(
- optionalBubbles = optionalBubbles,
- noteTaskController = noteTaskController,
+ controller = noteTaskController,
commandQueue = commandQueue,
+ optionalBubbles = Optional.ofNullable(bubbles),
isEnabled = isEnabled,
- optionalKeyguardManager = optionalKeyguardManager,
)
}
@@ -89,9 +80,7 @@ internal class NoteTaskInitializerTest : SysuiTestCase() {
@Test
fun initialize_bubblesNotPresent_shouldDoNothing() {
- whenever(optionalBubbles.isPresent).thenReturn(false)
-
- createNoteTaskInitializer().initialize()
+ createNoteTaskInitializer(bubbles = null).initialize()
verify(commandQueue, never()).addCallback(any())
}
@@ -113,37 +102,10 @@ internal class NoteTaskInitializerTest : SysuiTestCase() {
// region handleSystemKey
@Test
- fun handleSystemKey_receiveValidSystemKey_keyguardNotLocked_shouldShowNoteTaskWithUnlocked() {
- val keyguardManager =
- mock<KeyguardManager>() { whenever(isKeyguardLocked).thenReturn(false) }
- createNoteTaskInitializer(optionalKeyguardManager = Optional.of(keyguardManager))
- .callbacks
- .handleSystemKey(NoteTaskController.NOTE_TASK_KEY_EVENT)
-
- verify(noteTaskController)
- .showNoteTask(uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON)
- }
-
- @Test
- fun handleSystemKey_receiveValidSystemKey_keyguardLocked_shouldShowNoteTaskWithLocked() {
- val keyguardManager =
- mock<KeyguardManager>() { whenever(isKeyguardLocked).thenReturn(true) }
- createNoteTaskInitializer(optionalKeyguardManager = Optional.of(keyguardManager))
- .callbacks
- .handleSystemKey(NoteTaskController.NOTE_TASK_KEY_EVENT)
-
- verify(noteTaskController)
- .showNoteTask(uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON_LOCKED)
- }
-
- @Test
- fun handleSystemKey_receiveValidSystemKey_nullKeyguardManager_shouldShowNoteTaskWithUnlocked() {
- createNoteTaskInitializer(optionalKeyguardManager = Optional.empty())
- .callbacks
- .handleSystemKey(NoteTaskController.NOTE_TASK_KEY_EVENT)
+ fun handleSystemKey_receiveValidSystemKey_shouldShowNoteTask() {
+ createNoteTaskInitializer().callbacks.handleSystemKey(KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL)
- verify(noteTaskController)
- .showNoteTask(uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON)
+ verify(noteTaskController).showNoteTask(entryPoint = NoteTaskEntryPoint.TAIL_BUTTON)
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/OWNERS b/packages/SystemUI/tests/src/com/android/systemui/notetask/OWNERS
index 7ccb316dbca5..0ec996be72de 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/OWNERS
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/OWNERS
@@ -5,4 +5,6 @@ juliacr@google.com
madym@google.com
mgalhardo@google.com
petrcermak@google.com
+stevenckng@google.com
+tkachenkoi@google.com
vanjan@google.com \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfigTest.kt
index cdc683f8f8f8..e57d0d943aab 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfigTest.kt
@@ -27,7 +27,7 @@ import com.android.systemui.common.shared.model.Icon
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.LockScreenState
import com.android.systemui.notetask.NoteTaskController
-import com.android.systemui.notetask.NoteTaskController.ShowNoteTaskUiEvent
+import com.android.systemui.notetask.NoteTaskEntryPoint
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
@@ -95,7 +95,6 @@ internal class NoteTaskQuickAffordanceConfigTest : SysuiTestCase() {
underTest.onTriggered(expandable = null)
- verify(noteTaskController)
- .showNoteTask(uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE)
+ verify(noteTaskController).showNoteTask(entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE)
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
index 5058373e39b0..3d55c5131b40 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
@@ -71,7 +71,7 @@ public class QSPanelControllerBaseTest extends SysuiTestCase {
@Mock
private QSPanel mQSPanel;
@Mock
- private QSTileHost mQSTileHost;
+ private QSHost mQSHost;
@Mock
private QSCustomizerController mQSCustomizerController;
@Mock
@@ -105,7 +105,7 @@ public class QSPanelControllerBaseTest extends SysuiTestCase {
/** Implementation needed to ensure we have a reflectively-available class name. */
private class TestableQSPanelControllerBase extends QSPanelControllerBase<QSPanel> {
- protected TestableQSPanelControllerBase(QSPanel view, QSTileHost host,
+ protected TestableQSPanelControllerBase(QSPanel view, QSHost host,
QSCustomizerController qsCustomizerController, MediaHost mediaHost,
MetricsLogger metricsLogger, UiEventLogger uiEventLogger, QSLogger qsLogger,
DumpManager dumpManager) {
@@ -130,8 +130,8 @@ public class QSPanelControllerBaseTest extends SysuiTestCase {
when(mQSPanel.getOrCreateTileLayout()).thenReturn(mPagedTileLayout);
when(mQSPanel.getTileLayout()).thenReturn(mPagedTileLayout);
when(mQSTile.getTileSpec()).thenReturn("dnd");
- when(mQSTileHost.getTiles()).thenReturn(Collections.singleton(mQSTile));
- when(mQSTileHost.createTileView(any(), eq(mQSTile), anyBoolean())).thenReturn(mQSTileView);
+ when(mQSHost.getTiles()).thenReturn(Collections.singleton(mQSTile));
+ when(mQSHost.createTileView(any(), eq(mQSTile), anyBoolean())).thenReturn(mQSTileView);
when(mQSTileRevealControllerFactory.create(any(), any()))
.thenReturn(mQSTileRevealController);
when(mMediaHost.getDisappearParameters()).thenReturn(new DisappearParameters());
@@ -142,7 +142,7 @@ public class QSPanelControllerBaseTest extends SysuiTestCase {
return null;
}).when(mQSPanel).setListening(anyBoolean());
- mController = new TestableQSPanelControllerBase(mQSPanel, mQSTileHost,
+ mController = new TestableQSPanelControllerBase(mQSPanel, mQSHost,
mQSCustomizerController, mMediaHost,
mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager);
@@ -155,7 +155,7 @@ public class QSPanelControllerBaseTest extends SysuiTestCase {
mController.onViewDetached();
QSPanelControllerBase<QSPanel> controller = new TestableQSPanelControllerBase(mQSPanel,
- mQSTileHost, mQSCustomizerController, mMediaHost,
+ mQSHost, mQSCustomizerController, mMediaHost,
mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager) {
@Override
protected QSTileRevealController createTileRevealController() {
@@ -250,7 +250,7 @@ public class QSPanelControllerBaseTest extends SysuiTestCase {
when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(false);
when(mQSPanel.getDumpableTag()).thenReturn("QSPanelLandscape");
- mController = new TestableQSPanelControllerBase(mQSPanel, mQSTileHost,
+ mController = new TestableQSPanelControllerBase(mQSPanel, mQSHost,
mQSCustomizerController, mMediaHost,
mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager);
mController.init();
@@ -259,7 +259,7 @@ public class QSPanelControllerBaseTest extends SysuiTestCase {
when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(true);
when(mQSPanel.getDumpableTag()).thenReturn("QSPanelPortrait");
- mController = new TestableQSPanelControllerBase(mQSPanel, mQSTileHost,
+ mController = new TestableQSPanelControllerBase(mQSPanel, mQSHost,
mQSCustomizerController, mMediaHost,
mMetricsLogger, mUiEventLogger, mQSLogger, mDumpManager);
mController.init();
@@ -291,7 +291,7 @@ public class QSPanelControllerBaseTest extends SysuiTestCase {
@Test
public void testRefreshAllTilesDoesntRefreshListeningTiles() {
- when(mQSTileHost.getTiles()).thenReturn(List.of(mQSTile, mOtherTile));
+ when(mQSHost.getTiles()).thenReturn(List.of(mQSTile, mOtherTile));
mController.setTiles();
when(mQSTile.isListening()).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
index 09156d6d6752..a0d8f98a4ad1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
@@ -9,7 +9,6 @@ import com.android.internal.logging.UiEventLogger
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
-import com.android.systemui.flags.FeatureFlags
import com.android.systemui.media.controls.ui.MediaHost
import com.android.systemui.media.controls.ui.MediaHostState
import com.android.systemui.plugins.FalsingManager
@@ -41,7 +40,7 @@ class QSPanelControllerTest : SysuiTestCase() {
@Mock private lateinit var qsPanel: QSPanel
@Mock private lateinit var tunerService: TunerService
- @Mock private lateinit var qsTileHost: QSTileHost
+ @Mock private lateinit var qsHost: QSHost
@Mock private lateinit var qsCustomizerController: QSCustomizerController
@Mock private lateinit var qsTileRevealControllerFactory: QSTileRevealController.Factory
@Mock private lateinit var dumpManager: DumpManager
@@ -57,7 +56,6 @@ class QSPanelControllerTest : SysuiTestCase() {
@Mock private lateinit var tile: QSTile
@Mock private lateinit var otherTile: QSTile
@Mock private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager
- @Mock private lateinit var featureFlags: FeatureFlags
@Mock private lateinit var configuration: Configuration
@Mock private lateinit var pagedTileLayout: PagedTileLayout
@@ -81,7 +79,7 @@ class QSPanelControllerTest : SysuiTestCase() {
controller = QSPanelController(
qsPanel,
tunerService,
- qsTileHost,
+ qsHost,
qsCustomizerController,
/* usingMediaPlayer= */ true,
mediaHost,
@@ -93,8 +91,7 @@ class QSPanelControllerTest : SysuiTestCase() {
brightnessControllerFactory,
brightnessSliderFactory,
falsingManager,
- statusBarKeyguardViewManager,
- featureFlags
+ statusBarKeyguardViewManager
)
}
@@ -112,7 +109,7 @@ class QSPanelControllerTest : SysuiTestCase() {
@Test
fun testSetListeningDoesntRefreshListeningTiles() {
- whenever(qsTileHost.getTiles()).thenReturn(listOf(tile, otherTile))
+ whenever(qsHost.getTiles()).thenReturn(listOf(tile, otherTile))
controller.setTiles()
whenever(tile.isListening()).thenReturn(false)
whenever(otherTile.isListening()).thenReturn(true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt
index a8cfb256bc7c..93cebe2bcd16 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt
@@ -165,26 +165,11 @@ class QSPanelTest : SysuiTestCase() {
}
@Test
- fun testTopPadding_notCombinedHeaders() {
- qsPanel.setUsingCombinedHeaders(false)
+ fun testTopPadding() {
val padding = 10
val paddingCombined = 100
context.orCreateTestableResources.addOverride(R.dimen.qs_panel_padding_top, padding)
- context.orCreateTestableResources.addOverride(
- R.dimen.qs_panel_padding_top_combined_headers, paddingCombined)
-
- qsPanel.updatePadding()
- assertThat(qsPanel.paddingTop).isEqualTo(padding)
- }
-
- @Test
- fun testTopPadding_combinedHeaders() {
- qsPanel.setUsingCombinedHeaders(true)
- val padding = 10
- val paddingCombined = 100
- context.orCreateTestableResources.addOverride(R.dimen.qs_panel_padding_top, padding)
- context.orCreateTestableResources.addOverride(
- R.dimen.qs_panel_padding_top_combined_headers, paddingCombined)
+ context.orCreateTestableResources.addOverride(R.dimen.qs_panel_padding_top, paddingCombined)
qsPanel.updatePadding()
assertThat(qsPanel.paddingTop).isEqualTo(paddingCombined)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
index fb1a720b82f6..34d2b14d46a9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
@@ -69,7 +69,6 @@ import com.android.systemui.settings.UserFileManager;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.phone.AutoTileManager;
import com.android.systemui.statusbar.phone.CentralSurfaces;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.FakeSharedPreferences;
import com.android.systemui.util.concurrency.FakeExecutor;
@@ -100,11 +99,9 @@ public class QSTileHostTest extends SysuiTestCase {
private static ComponentName CUSTOM_TILE =
ComponentName.unflattenFromString("TEST_PKG/.TEST_CLS");
private static final String CUSTOM_TILE_SPEC = CustomTile.toSpec(CUSTOM_TILE);
- private static final String SETTING = QSTileHost.TILES_SETTING;
+ private static final String SETTING = QSHost.TILES_SETTING;
@Mock
- private StatusBarIconController mIconController;
- @Mock
private QSFactory mDefaultFactory;
@Mock
private PluginManager mPluginManager;
@@ -167,7 +164,7 @@ public class QSTileHostTest extends SysuiTestCase {
mSecureSettings = new FakeSettings();
saveSetting("");
- mQSTileHost = new TestQSTileHost(mContext, mIconController, mDefaultFactory, mMainExecutor,
+ mQSTileHost = new TestQSTileHost(mContext, mDefaultFactory, mMainExecutor,
mPluginManager, mTunerService, mAutoTiles, mDumpManager, mCentralSurfaces,
mQSLogger, mUiEventLogger, mUserTracker, mSecureSettings, mCustomTileStatePersister,
mTileServiceRequestControllerBuilder, mTileLifecycleManagerFactory,
@@ -248,44 +245,44 @@ public class QSTileHostTest extends SysuiTestCase {
public void testRemoveWifiAndCellularWithoutInternet() {
saveSetting("wifi, spec1, cell, spec2");
- assertEquals("internet", mQSTileHost.mTileSpecs.get(0));
- assertEquals("spec1", mQSTileHost.mTileSpecs.get(1));
- assertEquals("spec2", mQSTileHost.mTileSpecs.get(2));
+ assertEquals("internet", mQSTileHost.getSpecs().get(0));
+ assertEquals("spec1", mQSTileHost.getSpecs().get(1));
+ assertEquals("spec2", mQSTileHost.getSpecs().get(2));
}
@Test
public void testRemoveWifiAndCellularWithInternet() {
saveSetting("wifi, spec1, cell, spec2, internet");
- assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
- assertEquals("spec2", mQSTileHost.mTileSpecs.get(1));
- assertEquals("internet", mQSTileHost.mTileSpecs.get(2));
+ assertEquals("spec1", mQSTileHost.getSpecs().get(0));
+ assertEquals("spec2", mQSTileHost.getSpecs().get(1));
+ assertEquals("internet", mQSTileHost.getSpecs().get(2));
}
@Test
public void testRemoveWifiWithoutInternet() {
saveSetting("spec1, wifi, spec2");
- assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
- assertEquals("internet", mQSTileHost.mTileSpecs.get(1));
- assertEquals("spec2", mQSTileHost.mTileSpecs.get(2));
+ assertEquals("spec1", mQSTileHost.getSpecs().get(0));
+ assertEquals("internet", mQSTileHost.getSpecs().get(1));
+ assertEquals("spec2", mQSTileHost.getSpecs().get(2));
}
@Test
public void testRemoveCellWithInternet() {
saveSetting("spec1, spec2, cell, internet");
- assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
- assertEquals("spec2", mQSTileHost.mTileSpecs.get(1));
- assertEquals("internet", mQSTileHost.mTileSpecs.get(2));
+ assertEquals("spec1", mQSTileHost.getSpecs().get(0));
+ assertEquals("spec2", mQSTileHost.getSpecs().get(1));
+ assertEquals("internet", mQSTileHost.getSpecs().get(2));
}
@Test
public void testNoWifiNoCellularNoInternet() {
saveSetting("spec1,spec2");
- assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
- assertEquals("spec2", mQSTileHost.mTileSpecs.get(1));
+ assertEquals("spec1", mQSTileHost.getSpecs().get(0));
+ assertEquals("spec2", mQSTileHost.getSpecs().get(1));
}
@Test
@@ -332,9 +329,9 @@ public class QSTileHostTest extends SysuiTestCase {
mQSTileHost.addTile("spec1");
- assertEquals(2, mQSTileHost.mTileSpecs.size());
- assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
- assertEquals("spec2", mQSTileHost.mTileSpecs.get(1));
+ assertEquals(2, mQSTileHost.getSpecs().size());
+ assertEquals("spec1", mQSTileHost.getSpecs().get(0));
+ assertEquals("spec2", mQSTileHost.getSpecs().get(1));
}
@Test
@@ -346,10 +343,10 @@ public class QSTileHostTest extends SysuiTestCase {
mQSTileHost.addTile("spec2", 1);
mMainExecutor.runAllReady();
- assertEquals(3, mQSTileHost.mTileSpecs.size());
- assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
- assertEquals("spec2", mQSTileHost.mTileSpecs.get(1));
- assertEquals("spec3", mQSTileHost.mTileSpecs.get(2));
+ assertEquals(3, mQSTileHost.getSpecs().size());
+ assertEquals("spec1", mQSTileHost.getSpecs().get(0));
+ assertEquals("spec2", mQSTileHost.getSpecs().get(1));
+ assertEquals("spec3", mQSTileHost.getSpecs().get(2));
}
@Test
@@ -361,10 +358,10 @@ public class QSTileHostTest extends SysuiTestCase {
mQSTileHost.addTile("spec2", 100);
mMainExecutor.runAllReady();
- assertEquals(3, mQSTileHost.mTileSpecs.size());
- assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
- assertEquals("spec3", mQSTileHost.mTileSpecs.get(1));
- assertEquals("spec2", mQSTileHost.mTileSpecs.get(2));
+ assertEquals(3, mQSTileHost.getSpecs().size());
+ assertEquals("spec1", mQSTileHost.getSpecs().get(0));
+ assertEquals("spec3", mQSTileHost.getSpecs().get(1));
+ assertEquals("spec2", mQSTileHost.getSpecs().get(2));
}
@Test
@@ -376,10 +373,10 @@ public class QSTileHostTest extends SysuiTestCase {
mQSTileHost.addTile("spec2", QSTileHost.POSITION_AT_END);
mMainExecutor.runAllReady();
- assertEquals(3, mQSTileHost.mTileSpecs.size());
- assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
- assertEquals("spec3", mQSTileHost.mTileSpecs.get(1));
- assertEquals("spec2", mQSTileHost.mTileSpecs.get(2));
+ assertEquals(3, mQSTileHost.getSpecs().size());
+ assertEquals("spec1", mQSTileHost.getSpecs().get(0));
+ assertEquals("spec3", mQSTileHost.getSpecs().get(1));
+ assertEquals("spec2", mQSTileHost.getSpecs().get(2));
}
@Test
@@ -389,8 +386,8 @@ public class QSTileHostTest extends SysuiTestCase {
mQSTileHost.addTile(CUSTOM_TILE, /* end */ false);
mMainExecutor.runAllReady();
- assertEquals(1, mQSTileHost.mTileSpecs.size());
- assertEquals(CUSTOM_TILE_SPEC, mQSTileHost.mTileSpecs.get(0));
+ assertEquals(1, mQSTileHost.getSpecs().size());
+ assertEquals(CUSTOM_TILE_SPEC, mQSTileHost.getSpecs().get(0));
}
@Test
@@ -400,8 +397,8 @@ public class QSTileHostTest extends SysuiTestCase {
mQSTileHost.addTile(CUSTOM_TILE);
mMainExecutor.runAllReady();
- assertEquals(2, mQSTileHost.mTileSpecs.size());
- assertEquals(CUSTOM_TILE_SPEC, mQSTileHost.mTileSpecs.get(0));
+ assertEquals(2, mQSTileHost.getSpecs().size());
+ assertEquals(CUSTOM_TILE_SPEC, mQSTileHost.getSpecs().get(0));
}
@Test
@@ -411,8 +408,8 @@ public class QSTileHostTest extends SysuiTestCase {
mQSTileHost.addTile(CUSTOM_TILE, /* end */ false);
mMainExecutor.runAllReady();
- assertEquals(2, mQSTileHost.mTileSpecs.size());
- assertEquals(CUSTOM_TILE_SPEC, mQSTileHost.mTileSpecs.get(0));
+ assertEquals(2, mQSTileHost.getSpecs().size());
+ assertEquals(CUSTOM_TILE_SPEC, mQSTileHost.getSpecs().get(0));
}
@Test
@@ -422,8 +419,8 @@ public class QSTileHostTest extends SysuiTestCase {
mQSTileHost.addTile(CUSTOM_TILE, /* end */ true);
mMainExecutor.runAllReady();
- assertEquals(2, mQSTileHost.mTileSpecs.size());
- assertEquals(CUSTOM_TILE_SPEC, mQSTileHost.mTileSpecs.get(1));
+ assertEquals(2, mQSTileHost.getSpecs().size());
+ assertEquals(CUSTOM_TILE_SPEC, mQSTileHost.getSpecs().get(1));
}
@Test
@@ -478,7 +475,7 @@ public class QSTileHostTest extends SysuiTestCase {
mQSTileHost.removeTiles(List.of("spec1", "spec2"));
mMainExecutor.runAllReady();
- assertEquals(List.of("spec3"), mQSTileHost.mTileSpecs);
+ assertEquals(List.of("spec3"), mQSTileHost.getSpecs());
}
@Test
@@ -488,7 +485,7 @@ public class QSTileHostTest extends SysuiTestCase {
mQSTileHost.removeTile("spec3");
mMainExecutor.runAllReady();
- assertEquals(List.of("spec2"), mQSTileHost.mTileSpecs);
+ assertEquals(List.of("spec2"), mQSTileHost.getSpecs());
assertEquals("spec2", getSetting());
}
@@ -497,10 +494,10 @@ public class QSTileHostTest extends SysuiTestCase {
saveSetting("spec1,spec2");
mQSTileHost.addTile("spec3");
- assertEquals(List.of("spec1", "spec2"), mQSTileHost.mTileSpecs);
+ assertEquals(List.of("spec1", "spec2"), mQSTileHost.getSpecs());
mMainExecutor.runAllReady();
- assertEquals(List.of("spec1", "spec2", "spec3"), mQSTileHost.mTileSpecs);
+ assertEquals(List.of("spec1", "spec2", "spec3"), mQSTileHost.getSpecs());
}
@Test
@@ -508,10 +505,10 @@ public class QSTileHostTest extends SysuiTestCase {
saveSetting("spec1,spec2");
mQSTileHost.removeTile("spec1");
- assertEquals(List.of("spec1", "spec2"), mQSTileHost.mTileSpecs);
+ assertEquals(List.of("spec1", "spec2"), mQSTileHost.getSpecs());
mMainExecutor.runAllReady();
- assertEquals(List.of("spec2"), mQSTileHost.mTileSpecs);
+ assertEquals(List.of("spec2"), mQSTileHost.getSpecs());
}
@Test
@@ -519,10 +516,10 @@ public class QSTileHostTest extends SysuiTestCase {
saveSetting("spec1,spec2,spec3");
mQSTileHost.removeTiles(List.of("spec3", "spec1"));
- assertEquals(List.of("spec1", "spec2", "spec3"), mQSTileHost.mTileSpecs);
+ assertEquals(List.of("spec1", "spec2", "spec3"), mQSTileHost.getSpecs());
mMainExecutor.runAllReady();
- assertEquals(List.of("spec2"), mQSTileHost.mTileSpecs);
+ assertEquals(List.of("spec2"), mQSTileHost.getSpecs());
}
@Test
@@ -530,17 +527,17 @@ public class QSTileHostTest extends SysuiTestCase {
saveSetting("spec1," + CUSTOM_TILE_SPEC);
mQSTileHost.removeTileByUser(CUSTOM_TILE);
- assertEquals(List.of("spec1", CUSTOM_TILE_SPEC), mQSTileHost.mTileSpecs);
+ assertEquals(List.of("spec1", CUSTOM_TILE_SPEC), mQSTileHost.getSpecs());
mMainExecutor.runAllReady();
- assertEquals(List.of("spec1"), mQSTileHost.mTileSpecs);
+ assertEquals(List.of("spec1"), mQSTileHost.getSpecs());
}
@Test
public void testNonValidTileNotStoredInSettings() {
saveSetting("spec1,not-valid");
- assertEquals(List.of("spec1"), mQSTileHost.mTileSpecs);
+ assertEquals(List.of("spec1"), mQSTileHost.getSpecs());
assertEquals("spec1", getSetting());
}
@@ -548,14 +545,14 @@ public class QSTileHostTest extends SysuiTestCase {
public void testNotAvailableTileNotStoredInSettings() {
saveSetting("spec1,na");
- assertEquals(List.of("spec1"), mQSTileHost.mTileSpecs);
+ assertEquals(List.of("spec1"), mQSTileHost.getSpecs());
assertEquals("spec1", getSetting());
}
@Test
public void testIsTileAdded_true() {
int user = mUserTracker.getUserId();
- getSharedPreferenecesForUser(user)
+ getSharedPreferencesForUser(user)
.edit()
.putBoolean(CUSTOM_TILE.flattenToString(), true)
.apply();
@@ -566,7 +563,7 @@ public class QSTileHostTest extends SysuiTestCase {
@Test
public void testIsTileAdded_false() {
int user = mUserTracker.getUserId();
- getSharedPreferenecesForUser(user)
+ getSharedPreferencesForUser(user)
.edit()
.putBoolean(CUSTOM_TILE.flattenToString(), false)
.apply();
@@ -597,7 +594,7 @@ public class QSTileHostTest extends SysuiTestCase {
int user = mUserTracker.getUserId();
mQSTileHost.setTileAdded(CUSTOM_TILE, user, true);
- assertTrue(getSharedPreferenecesForUser(user)
+ assertTrue(getSharedPreferencesForUser(user)
.getBoolean(CUSTOM_TILE.flattenToString(), false));
}
@@ -606,7 +603,7 @@ public class QSTileHostTest extends SysuiTestCase {
int user = mUserTracker.getUserId();
mQSTileHost.setTileAdded(CUSTOM_TILE, user, false);
- assertFalse(getSharedPreferenecesForUser(user)
+ assertFalse(getSharedPreferencesForUser(user)
.getBoolean(CUSTOM_TILE.flattenToString(), false));
}
@@ -615,7 +612,7 @@ public class QSTileHostTest extends SysuiTestCase {
int user = mUserTracker.getUserId();
mQSTileHost.setTileAdded(CUSTOM_TILE, user, true);
- assertFalse(getSharedPreferenecesForUser(user + 1)
+ assertFalse(getSharedPreferencesForUser(user + 1)
.getBoolean(CUSTOM_TILE.flattenToString(), false));
}
@@ -627,8 +624,8 @@ public class QSTileHostTest extends SysuiTestCase {
// This will be done by TileServiceManager
mQSTileHost.setTileAdded(CUSTOM_TILE, user, true);
- mQSTileHost.changeTilesByUser(mQSTileHost.mTileSpecs, List.of("spec1"));
- assertFalse(getSharedPreferenecesForUser(user)
+ mQSTileHost.changeTilesByUser(mQSTileHost.getSpecs(), List.of("spec1"));
+ assertFalse(getSharedPreferencesForUser(user)
.getBoolean(CUSTOM_TILE.flattenToString(), false));
}
@@ -642,7 +639,7 @@ public class QSTileHostTest extends SysuiTestCase {
mQSTileHost.removeTileByUser(CUSTOM_TILE);
mMainExecutor.runAllReady();
- assertFalse(getSharedPreferenecesForUser(user)
+ assertFalse(getSharedPreferencesForUser(user)
.getBoolean(CUSTOM_TILE.flattenToString(), false));
}
@@ -656,7 +653,7 @@ public class QSTileHostTest extends SysuiTestCase {
mQSTileHost.removeTile(CUSTOM_TILE_SPEC);
mMainExecutor.runAllReady();
- assertFalse(getSharedPreferenecesForUser(user)
+ assertFalse(getSharedPreferencesForUser(user)
.getBoolean(CUSTOM_TILE.flattenToString(), false));
}
@@ -681,12 +678,12 @@ public class QSTileHostTest extends SysuiTestCase {
assertEquals(CUSTOM_TILE.getClassName(), proto.tiles[1].getComponentName().className);
}
- private SharedPreferences getSharedPreferenecesForUser(int user) {
+ private SharedPreferences getSharedPreferencesForUser(int user) {
return mUserFileManager.getSharedPreferences(QSTileHost.TILES, 0, user);
}
private class TestQSTileHost extends QSTileHost {
- TestQSTileHost(Context context, StatusBarIconController iconController,
+ TestQSTileHost(Context context,
QSFactory defaultFactory, Executor mainExecutor,
PluginManager pluginManager, TunerService tunerService,
Provider<AutoTileManager> autoTiles, DumpManager dumpManager,
@@ -696,7 +693,7 @@ public class QSTileHostTest extends SysuiTestCase {
TileServiceRequestController.Builder tileServiceRequestControllerBuilder,
TileLifecycleManager.Factory tileLifecycleManagerFactory,
UserFileManager userFileManager) {
- super(context, iconController, defaultFactory, mainExecutor, pluginManager,
+ super(context, defaultFactory, mainExecutor, pluginManager,
tunerService, autoTiles, dumpManager, Optional.of(centralSurfaces), qsLogger,
uiEventLogger, userTracker, secureSettings, customTileStatePersister,
tileServiceRequestControllerBuilder, tileLifecycleManagerFactory,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
index f53e997a331c..71ea831e0f92 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
@@ -50,7 +50,7 @@ import org.mockito.MockitoAnnotations
class QuickQSPanelControllerTest : SysuiTestCase() {
@Mock private lateinit var quickQSPanel: QuickQSPanel
- @Mock private lateinit var qsTileHost: QSTileHost
+ @Mock private lateinit var qsHost: QSHost
@Mock private lateinit var qsCustomizerController: QSCustomizerController
@Mock private lateinit var mediaHost: MediaHost
@Mock private lateinit var metricsLogger: MetricsLogger
@@ -75,12 +75,12 @@ class QuickQSPanelControllerTest : SysuiTestCase() {
whenever(quickQSPanel.isAttachedToWindow).thenReturn(true)
whenever(quickQSPanel.dumpableTag).thenReturn("")
whenever(quickQSPanel.resources).thenReturn(mContext.resources)
- whenever(qsTileHost.createTileView(any(), any(), anyBoolean())).thenReturn(tileView)
+ whenever(qsHost.createTileView(any(), any(), anyBoolean())).thenReturn(tileView)
controller =
TestQuickQSPanelController(
quickQSPanel,
- qsTileHost,
+ qsHost,
qsCustomizerController,
/* usingMediaPlayer = */ false,
mediaHost,
@@ -102,7 +102,7 @@ class QuickQSPanelControllerTest : SysuiTestCase() {
fun testTileSublistWithFewerTiles_noCrash() {
whenever(quickQSPanel.numQuickTiles).thenReturn(3)
- whenever(qsTileHost.tiles).thenReturn(listOf(tile, tile))
+ whenever(qsHost.tiles).thenReturn(listOf(tile, tile))
controller.setTiles()
}
@@ -111,7 +111,7 @@ class QuickQSPanelControllerTest : SysuiTestCase() {
fun testTileSublistWithTooManyTiles() {
val limit = 3
whenever(quickQSPanel.numQuickTiles).thenReturn(limit)
- whenever(qsTileHost.tiles).thenReturn(listOf(tile, tile, tile, tile))
+ whenever(qsHost.tiles).thenReturn(listOf(tile, tile, tile, tile))
controller.setTiles()
@@ -147,7 +147,7 @@ class QuickQSPanelControllerTest : SysuiTestCase() {
class TestQuickQSPanelController(
view: QuickQSPanel,
- qsTileHost: QSTileHost,
+ qsHost: QSHost,
qsCustomizerController: QSCustomizerController,
usingMediaPlayer: Boolean,
mediaHost: MediaHost,
@@ -159,7 +159,7 @@ class QuickQSPanelControllerTest : SysuiTestCase() {
) :
QuickQSPanelController(
view,
- qsTileHost,
+ qsHost,
qsCustomizerController,
usingMediaPlayer,
mediaHost,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
index 39d89bf99af2..555484cc17f8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
@@ -18,37 +18,16 @@ package com.android.systemui.qs
import android.content.Context
import android.testing.AndroidTestingRunner
-import android.view.View
import androidx.test.filters.SmallTest
-import com.android.systemui.R
import com.android.systemui.SysuiTestCase
-import com.android.systemui.battery.BatteryMeterViewController
-import com.android.systemui.colorextraction.SysuiColorExtractor
-import com.android.systemui.demomode.DemoModeController
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.qs.carrier.QSCarrierGroup
-import com.android.systemui.qs.carrier.QSCarrierGroupController
-import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
-import com.android.systemui.statusbar.phone.StatusBarIconController
-import com.android.systemui.statusbar.phone.StatusIconContainer
-import com.android.systemui.statusbar.policy.Clock
-import com.android.systemui.statusbar.policy.VariableDateView
-import com.android.systemui.statusbar.policy.VariableDateViewController
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.argumentCaptor
-import com.android.systemui.util.mockito.capture
-import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Answers
-import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
-import org.mockito.Mockito.anyBoolean
-import org.mockito.Mockito.reset
-import org.mockito.Mockito.verify
import org.mockito.Mockito.`when`
+import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@SmallTest
@@ -58,78 +37,21 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() {
@Mock
private lateinit var view: QuickStatusBarHeader
@Mock
- private lateinit var privacyIconsController: HeaderPrivacyIconsController
- @Mock
- private lateinit var statusBarIconController: StatusBarIconController
- @Mock
- private lateinit var demoModeController: DemoModeController
- @Mock
private lateinit var quickQSPanelController: QuickQSPanelController
- @Mock(answer = Answers.RETURNS_SELF)
- private lateinit var qsCarrierGroupControllerBuilder: QSCarrierGroupController.Builder
- @Mock
- private lateinit var qsCarrierGroupController: QSCarrierGroupController
- @Mock
- private lateinit var colorExtractor: SysuiColorExtractor
- @Mock
- private lateinit var iconContainer: StatusIconContainer
- @Mock
- private lateinit var qsCarrierGroup: QSCarrierGroup
- @Mock
- private lateinit var variableDateViewControllerFactory: VariableDateViewController.Factory
- @Mock
- private lateinit var variableDateViewController: VariableDateViewController
- @Mock
- private lateinit var batteryMeterViewController: BatteryMeterViewController
- @Mock
- private lateinit var clock: Clock
- @Mock
- private lateinit var variableDateView: VariableDateView
- @Mock
- private lateinit var mockView: View
+
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private lateinit var context: Context
- @Mock
- private lateinit var featureFlags: FeatureFlags
- @Mock
- private lateinit var insetsProvider: StatusBarContentInsetsProvider
- @Mock
- private lateinit var iconManagerFactory: StatusBarIconController.TintedIconManager.Factory
- @Mock
- private lateinit var iconManager: StatusBarIconController.TintedIconManager
-
- private val qsExpansionPathInterpolator = QSExpansionPathInterpolator()
private lateinit var controller: QuickStatusBarHeaderController
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
- stubViews()
- `when`(iconContainer.context).thenReturn(context)
- `when`(qsCarrierGroupControllerBuilder.build()).thenReturn(qsCarrierGroupController)
- `when`(variableDateViewControllerFactory.create(any()))
- .thenReturn(variableDateViewController)
- `when`(iconManagerFactory.create(any(), any())).thenReturn(iconManager)
`when`(view.resources).thenReturn(mContext.resources)
`when`(view.isAttachedToWindow).thenReturn(true)
`when`(view.context).thenReturn(context)
- controller = QuickStatusBarHeaderController(
- view,
- privacyIconsController,
- statusBarIconController,
- demoModeController,
- quickQSPanelController,
- qsCarrierGroupControllerBuilder,
- colorExtractor,
- qsExpansionPathInterpolator,
- featureFlags,
- variableDateViewControllerFactory,
- batteryMeterViewController,
- insetsProvider,
- iconManagerFactory,
- )
+ controller = QuickStatusBarHeaderController(view, quickQSPanelController)
}
@After
@@ -138,74 +60,11 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() {
}
@Test
- fun testClockNotClickable() {
- assertThat(clock.isClickable).isFalse()
- }
-
- @Test
- fun testSingleCarrierListenerAttachedOnInit() {
- controller.init()
-
- verify(qsCarrierGroupController).setOnSingleCarrierChangedListener(any())
- }
-
- @Test
- fun testSingleCarrierSetOnViewOnInit_false() {
- `when`(qsCarrierGroupController.isSingleCarrier).thenReturn(false)
- controller.init()
-
- verify(view).setIsSingleCarrier(false)
- }
-
- @Test
- fun testSingleCarrierSetOnViewOnInit_true() {
- `when`(qsCarrierGroupController.isSingleCarrier).thenReturn(true)
- controller.init()
-
- verify(view).setIsSingleCarrier(true)
- }
-
- @Test
- fun testRSSISlot_notCombined() {
- controller.init()
-
- val captor = argumentCaptor<List<String>>()
- verify(view).onAttach(any(), any(), capture(captor), any(), anyBoolean())
-
- assertThat(captor.value).containsExactly(
- mContext.getString(com.android.internal.R.string.status_bar_mobile)
- )
- }
-
- @Test
- fun testSingleCarrierCallback() {
- controller.init()
- reset(view)
-
- val captor = argumentCaptor<QSCarrierGroupController.OnSingleCarrierChangedListener>()
- verify(qsCarrierGroupController).setOnSingleCarrierChangedListener(capture(captor))
-
- captor.value.onSingleCarrierChanged(true)
- verify(view).setIsSingleCarrier(true)
-
- captor.value.onSingleCarrierChanged(false)
- verify(view).setIsSingleCarrier(false)
- }
-
- @Test
- fun testAlarmIconIgnored() {
- controller.init()
-
- verify(iconContainer).addIgnoredSlot(
- mContext.getString(com.android.internal.R.string.status_bar_alarm_clock))
- }
+ fun testListeningStatus() {
+ controller.setListening(true)
+ verify(quickQSPanelController).setListening(true)
- private fun stubViews() {
- `when`(view.findViewById<View>(anyInt())).thenReturn(mockView)
- `when`(view.findViewById<QSCarrierGroup>(R.id.carrier_group)).thenReturn(qsCarrierGroup)
- `when`(view.findViewById<StatusIconContainer>(R.id.statusIcons)).thenReturn(iconContainer)
- `when`(view.findViewById<Clock>(R.id.clock)).thenReturn(clock)
- `when`(view.requireViewById<VariableDateView>(R.id.date)).thenReturn(variableDateView)
- `when`(view.requireViewById<VariableDateView>(R.id.date_clock)).thenReturn(variableDateView)
+ controller.setListening(false)
+ verify(quickQSPanelController).setListening(false)
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileAdapterTest.java
index d42cbe3b698a..c041cb6d0b1f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileAdapterTest.java
@@ -25,7 +25,7 @@ import androidx.test.filters.SmallTest;
import com.android.internal.logging.testing.UiEventLoggerFake;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import org.junit.Before;
import org.junit.Test;
@@ -42,19 +42,19 @@ public class TileAdapterTest extends SysuiTestCase {
private TileAdapter mTileAdapter;
@Mock
- private QSTileHost mQSTileHost;
+ private QSHost mQSHost;
@Before
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
TestableLooper.get(this).runWithLooper(() -> mTileAdapter =
- new TileAdapter(mContext, mQSTileHost, new UiEventLoggerFake()));
+ new TileAdapter(mContext, mQSHost, new UiEventLoggerFake()));
}
@Test
public void testResetNotifiesHost() {
mTileAdapter.resetTileSpecs(Collections.emptyList());
- verify(mQSTileHost).changeTilesByUser(any(), any());
+ verify(mQSHost).changeTilesByUser(any(), any());
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
index 040af70f2077..78a02584c40a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
@@ -55,7 +55,7 @@ import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.qs.QSIconView;
import com.android.systemui.plugins.qs.QSTile;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;
@@ -102,7 +102,7 @@ public class TileQueryHelperTest extends SysuiTestCase {
@Mock
private TileQueryHelper.TileStateListener mListener;
@Mock
- private QSTileHost mQSTileHost;
+ private QSHost mQSHost;
@Mock
private PackageManager mPackageManager;
@Mock
@@ -131,7 +131,7 @@ public class TileQueryHelperTest extends SysuiTestCase {
return null;
}
}
- ).when(mQSTileHost).createTile(anyString());
+ ).when(mQSHost).createTile(anyString());
FakeSystemClock clock = new FakeSystemClock();
mMainExecutor = new FakeExecutor(clock);
mBgExecutor = new FakeExecutor(clock);
@@ -147,7 +147,7 @@ public class TileQueryHelperTest extends SysuiTestCase {
@Test
public void testIsFinished_trueAfterQuerying() {
- mTileQueryHelper.queryTiles(mQSTileHost);
+ mTileQueryHelper.queryTiles(mQSHost);
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
@@ -156,7 +156,7 @@ public class TileQueryHelperTest extends SysuiTestCase {
@Test
public void testQueryTiles_callsListenerTwice() {
- mTileQueryHelper.queryTiles(mQSTileHost);
+ mTileQueryHelper.queryTiles(mQSHost);
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
@@ -170,7 +170,7 @@ public class TileQueryHelperTest extends SysuiTestCase {
return null;
}).when(mListener).onTilesChanged(any());
- mTileQueryHelper.queryTiles(mQSTileHost);
+ mTileQueryHelper.queryTiles(mQSHost);
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
@@ -184,7 +184,7 @@ public class TileQueryHelperTest extends SysuiTestCase {
mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock,
STOCK_TILES);
- mTileQueryHelper.queryTiles(mQSTileHost);
+ mTileQueryHelper.queryTiles(mQSHost);
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
@@ -204,7 +204,7 @@ public class TileQueryHelperTest extends SysuiTestCase {
mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock,
STOCK_TILES);
- mTileQueryHelper.queryTiles(mQSTileHost);
+ mTileQueryHelper.queryTiles(mQSHost);
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
@@ -224,7 +224,7 @@ public class TileQueryHelperTest extends SysuiTestCase {
mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock,
STOCK_TILES);
- mTileQueryHelper.queryTiles(mQSTileHost);
+ mTileQueryHelper.queryTiles(mQSHost);
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
@@ -240,9 +240,9 @@ public class TileQueryHelperTest extends SysuiTestCase {
public void testCustomTileNotCreated() {
Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.QS_TILES,
CUSTOM_TILE);
- mTileQueryHelper.queryTiles(mQSTileHost);
+ mTileQueryHelper.queryTiles(mQSHost);
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
- verify(mQSTileHost, never()).createTile(CUSTOM_TILE);
+ verify(mQSHost, never()).createTile(CUSTOM_TILE);
}
@Test
@@ -264,7 +264,7 @@ public class TileQueryHelperTest extends SysuiTestCase {
mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock,
"");
- mTileQueryHelper.queryTiles(mQSTileHost);
+ mTileQueryHelper.queryTiles(mQSHost);
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
verify(mListener, atLeastOnce()).onTilesChanged(mCaptor.capture());
@@ -278,7 +278,7 @@ public class TileQueryHelperTest extends SysuiTestCase {
Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.QS_TILES, null);
mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock,
STOCK_TILES);
- mTileQueryHelper.queryTiles(mQSTileHost);
+ mTileQueryHelper.queryTiles(mQSHost);
}
@Test
@@ -286,12 +286,12 @@ public class TileQueryHelperTest extends SysuiTestCase {
Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.QS_TILES, null);
QSTile t = mock(QSTile.class);
- when(mQSTileHost.createTile("hotspot")).thenReturn(t);
+ when(mQSHost.createTile("hotspot")).thenReturn(t);
mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock,
"hotspot");
- mTileQueryHelper.queryTiles(mQSTileHost);
+ mTileQueryHelper.queryTiles(mQSHost);
FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
InOrder verifier = inOrder(t);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTest.java
index 8aa625a7ea20..46af89e00db4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTest.java
@@ -39,7 +39,7 @@ import android.test.suitebuilder.annotation.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.settings.UserTracker;
import org.junit.After;
@@ -61,7 +61,7 @@ public class TileServiceManagerTest extends SysuiTestCase {
@Mock
private UserTracker mUserTracker;
@Mock
- private QSTileHost mQSTileHost;
+ private QSHost mQSHost;
@Mock
private Context mMockContext;
@@ -80,7 +80,7 @@ public class TileServiceManagerTest extends SysuiTestCase {
when(mUserTracker.getUserHandle()).thenReturn(UserHandle.SYSTEM);
when(mTileServices.getContext()).thenReturn(mMockContext);
- when(mTileServices.getHost()).thenReturn(mQSTileHost);
+ when(mTileServices.getHost()).thenReturn(mQSHost);
when(mTileLifecycle.getUserId()).thenAnswer(invocation -> mUserTracker.getUserId());
when(mTileLifecycle.isActiveTile()).thenReturn(false);
@@ -98,28 +98,28 @@ public class TileServiceManagerTest extends SysuiTestCase {
@Test
public void testSetTileAddedIfNotAdded() {
- when(mQSTileHost.isTileAdded(eq(mComponentName), anyInt())).thenReturn(false);
+ when(mQSHost.isTileAdded(eq(mComponentName), anyInt())).thenReturn(false);
mTileServiceManager.startLifecycleManagerAndAddTile();
- verify(mQSTileHost).setTileAdded(mComponentName, mUserTracker.getUserId(), true);
+ verify(mQSHost).setTileAdded(mComponentName, mUserTracker.getUserId(), true);
}
@Test
public void testNotSetTileAddedIfAdded() {
- when(mQSTileHost.isTileAdded(eq(mComponentName), anyInt())).thenReturn(true);
+ when(mQSHost.isTileAdded(eq(mComponentName), anyInt())).thenReturn(true);
mTileServiceManager.startLifecycleManagerAndAddTile();
- verify(mQSTileHost, never()).setTileAdded(eq(mComponentName), anyInt(), eq(true));
+ verify(mQSHost, never()).setTileAdded(eq(mComponentName), anyInt(), eq(true));
}
@Test
public void testSetTileAddedCorrectUser() {
int user = 10;
when(mUserTracker.getUserId()).thenReturn(user);
- when(mQSTileHost.isTileAdded(eq(mComponentName), anyInt())).thenReturn(false);
+ when(mQSHost.isTileAdded(eq(mComponentName), anyInt())).thenReturn(false);
mTileServiceManager.startLifecycleManagerAndAddTile();
- verify(mQSTileHost).setTileAdded(mComponentName, user, true);
+ verify(mQSHost).setTileAdded(mComponentName, user, true);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceRequestControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceRequestControllerTest.kt
index bdfbca47e569..ccfb5cf8959a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceRequestControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceRequestControllerTest.kt
@@ -27,27 +27,27 @@ import com.android.internal.logging.InstanceId
import com.android.internal.statusbar.IAddTileResultCallback
import com.android.systemui.InstanceIdSequenceFake
import com.android.systemui.SysuiTestCase
-import com.android.systemui.qs.QSTileHost
+import com.android.systemui.qs.QSHost
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.commandline.CommandRegistry
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
import com.google.common.truth.Truth.assertThat
+import java.util.function.Consumer
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.Mock
-import org.mockito.Mockito.`when`
import org.mockito.Mockito.anyBoolean
import org.mockito.Mockito.anyInt
import org.mockito.Mockito.anyString
import org.mockito.Mockito.atLeastOnce
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
-import java.util.function.Consumer
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -62,7 +62,7 @@ class TileServiceRequestControllerTest : SysuiTestCase() {
@Mock
private lateinit var tileRequestDialog: TileRequestDialog
@Mock
- private lateinit var qsTileHost: QSTileHost
+ private lateinit var qsHost: QSHost
@Mock
private lateinit var commandRegistry: CommandRegistry
@Mock
@@ -82,10 +82,10 @@ class TileServiceRequestControllerTest : SysuiTestCase() {
`when`(logger.newInstanceId()).thenReturn(instanceIdSequence.newInstanceId())
// Tile not present by default
- `when`(qsTileHost.indexOf(anyString())).thenReturn(-1)
+ `when`(qsHost.indexOf(anyString())).thenReturn(-1)
controller = TileServiceRequestController(
- qsTileHost,
+ qsHost,
commandQueue,
commandRegistry,
logger
@@ -107,18 +107,18 @@ class TileServiceRequestControllerTest : SysuiTestCase() {
@Test
fun tileAlreadyAdded_correctResult() {
- `when`(qsTileHost.indexOf(CustomTile.toSpec(TEST_COMPONENT))).thenReturn(2)
+ `when`(qsHost.indexOf(CustomTile.toSpec(TEST_COMPONENT))).thenReturn(2)
val callback = Callback()
controller.requestTileAdd(TEST_COMPONENT, TEST_APP_NAME, TEST_LABEL, icon, callback)
assertThat(callback.lastAccepted).isEqualTo(TileServiceRequestController.TILE_ALREADY_ADDED)
- verify(qsTileHost, never()).addTile(any(ComponentName::class.java), anyBoolean())
+ verify(qsHost, never()).addTile(any(ComponentName::class.java), anyBoolean())
}
@Test
fun tileAlreadyAdded_logged() {
- `when`(qsTileHost.indexOf(CustomTile.toSpec(TEST_COMPONENT))).thenReturn(2)
+ `when`(qsHost.indexOf(CustomTile.toSpec(TEST_COMPONENT))).thenReturn(2)
controller.requestTileAdd(TEST_COMPONENT, TEST_APP_NAME, TEST_LABEL, icon) {}
@@ -157,7 +157,7 @@ class TileServiceRequestControllerTest : SysuiTestCase() {
cancelListenerCaptor.value.onCancel(tileRequestDialog)
assertThat(callback.lastAccepted).isEqualTo(TileServiceRequestController.DISMISSED)
- verify(qsTileHost, never()).addTile(any(ComponentName::class.java), anyBoolean())
+ verify(qsHost, never()).addTile(any(ComponentName::class.java), anyBoolean())
}
@Test
@@ -191,7 +191,7 @@ class TileServiceRequestControllerTest : SysuiTestCase() {
clickListenerCaptor.value.onClick(tileRequestDialog, DialogInterface.BUTTON_POSITIVE)
assertThat(callback.lastAccepted).isEqualTo(TileServiceRequestController.ADD_TILE)
- verify(qsTileHost).addTile(TEST_COMPONENT, /* end */ true)
+ verify(qsHost).addTile(TEST_COMPONENT, /* end */ true)
}
@Test
@@ -225,7 +225,7 @@ class TileServiceRequestControllerTest : SysuiTestCase() {
clickListenerCaptor.value.onClick(tileRequestDialog, DialogInterface.BUTTON_NEGATIVE)
assertThat(callback.lastAccepted).isEqualTo(TileServiceRequestController.DONT_ADD_TILE)
- verify(qsTileHost, never()).addTile(any(ComponentName::class.java), anyBoolean())
+ verify(qsHost, never()).addTile(any(ComponentName::class.java), anyBoolean())
}
@Test
@@ -266,7 +266,7 @@ class TileServiceRequestControllerTest : SysuiTestCase() {
@Test
fun commandQueueCallback_callbackCalled() {
- `when`(qsTileHost.indexOf(CustomTile.toSpec(TEST_COMPONENT))).thenReturn(2)
+ `when`(qsHost.indexOf(CustomTile.toSpec(TEST_COMPONENT))).thenReturn(2)
val captor = ArgumentCaptor.forClass(CommandQueue.Callbacks::class.java)
verify(commandQueue, atLeastOnce()).addCallback(capture(captor))
val c = Callback()
@@ -365,4 +365,4 @@ class TileServiceRequestControllerTest : SysuiTestCase() {
accept(r)
}
}
-} \ No newline at end of file
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
index 172c87f0c50b..64e9a3e58bd6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
@@ -30,7 +30,6 @@ import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Intent;
import android.os.Handler;
-import android.os.HandlerExecutor;
import android.os.RemoteException;
import android.os.UserHandle;
import android.service.quicksettings.IQSTileService;
@@ -39,24 +38,13 @@ import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
-import com.android.internal.logging.UiEventLogger;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dump.DumpManager;
-import com.android.systemui.plugins.PluginManager;
-import com.android.systemui.qs.QSTileHost;
-import com.android.systemui.qs.logging.QSLogger;
-import com.android.systemui.qs.tileimpl.QSFactoryImpl;
-import com.android.systemui.settings.UserFileManager;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.phone.AutoTileManager;
-import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.phone.StatusBarIconController;
-import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.tuner.TunerService;
-import com.android.systemui.util.settings.SecureSettings;
import org.junit.After;
import org.junit.Assert;
@@ -68,8 +56,6 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
-import java.util.Optional;
-import java.util.concurrent.Executor;
import javax.inject.Provider;
@@ -92,26 +78,8 @@ public class TileServicesTest extends SysuiTestCase {
@Mock
private StatusBarIconController mStatusBarIconController;
@Mock
- private QSFactoryImpl mQSFactory;
- @Mock
- private PluginManager mPluginManager;
- @Mock
- private TunerService mTunerService;
- @Mock
- private AutoTileManager mAutoTileManager;
- @Mock
- private DumpManager mDumpManager;
- @Mock
- private CentralSurfaces mCentralSurfaces;
- @Mock
- private QSLogger mQSLogger;
- @Mock
- private UiEventLogger mUiEventLogger;
- @Mock
private UserTracker mUserTracker;
@Mock
- private SecureSettings mSecureSettings;
- @Mock
private TileServiceRequestController.Builder mTileServiceRequestControllerBuilder;
@Mock
private TileServiceRequestController mTileServiceRequestController;
@@ -122,12 +90,11 @@ public class TileServicesTest extends SysuiTestCase {
@Mock
private TileLifecycleManager mTileLifecycleManager;
@Mock
- private UserFileManager mUserFileManager;
+ private QSHost mQSHost;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- mDependency.injectMockDependency(BluetoothController.class);
mManagers = new ArrayList<>();
mTestableLooper = TestableLooper.get(this);
@@ -135,34 +102,16 @@ public class TileServicesTest extends SysuiTestCase {
.thenReturn(mTileServiceRequestController);
when(mTileLifecycleManagerFactory.create(any(Intent.class), any(UserHandle.class)))
.thenReturn(mTileLifecycleManager);
+ when(mQSHost.getContext()).thenReturn(mContext);
Provider<Handler> provider = () -> new Handler(mTestableLooper.getLooper());
- Executor executor = new HandlerExecutor(provider.get());
-
- QSTileHost host = new QSTileHost(mContext,
- mStatusBarIconController,
- mQSFactory,
- executor,
- mPluginManager,
- mTunerService,
- () -> mAutoTileManager,
- mDumpManager,
- Optional.of(mCentralSurfaces),
- mQSLogger,
- mUiEventLogger,
- mUserTracker,
- mSecureSettings,
- mock(CustomTileStatePersister.class),
- mTileServiceRequestControllerBuilder,
- mTileLifecycleManagerFactory,
- mUserFileManager);
- mTileService = new TestTileServices(host, provider, mBroadcastDispatcher,
- mUserTracker, mKeyguardStateController, mCommandQueue);
+
+ mTileService = new TestTileServices(mQSHost, provider, mBroadcastDispatcher,
+ mUserTracker, mKeyguardStateController, mCommandQueue, mStatusBarIconController);
}
@After
public void tearDown() throws Exception {
- mTileService.getHost().destroy();
mTileService.destroy();
TestableLooper.get(this).processAllMessages();
}
@@ -274,11 +223,12 @@ public class TileServicesTest extends SysuiTestCase {
}
private class TestTileServices extends TileServices {
- TestTileServices(QSTileHost host, Provider<Handler> handlerProvider,
+ TestTileServices(QSHost host, Provider<Handler> handlerProvider,
BroadcastDispatcher broadcastDispatcher, UserTracker userTracker,
- KeyguardStateController keyguardStateController, CommandQueue commandQueue) {
+ KeyguardStateController keyguardStateController, CommandQueue commandQueue,
+ StatusBarIconController statusBarIconController) {
super(host, handlerProvider, broadcastDispatcher, userTracker, keyguardStateController,
- commandQueue);
+ commandQueue, statusBarIconController);
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
index ba49f3fa66ee..36549fb826ec 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
@@ -69,7 +69,6 @@ import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.QSEvent;
import com.android.systemui.qs.QSHost;
-import com.android.systemui.qs.QSTileHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.statusbar.StatusBarState;
@@ -97,7 +96,7 @@ public class QSTileImplTest extends SysuiTestCase {
private TestableLooper mTestableLooper;
private TileImpl mTile;
@Mock
- private QSTileHost mHost;
+ private QSHost mHost;
@Mock
private MetricsLogger mMetricsLogger;
private final FalsingManagerFake mFalsingManager = new FalsingManagerFake();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt
index 030c59faa696..5e0190b65a12 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt
@@ -38,6 +38,7 @@ import com.android.systemui.settings.UserTracker
import com.android.systemui.util.settings.GlobalSettings
import com.google.common.truth.Truth.assertThat
import dagger.Lazy
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -94,6 +95,12 @@ class AirplaneModeTileTest : SysuiTestCase() {
mUserTracker)
}
+ @After
+ fun tearDown() {
+ mTile.destroy()
+ mTestableLooper.processAllMessages()
+ }
+
@Test
fun testIcon_whenDisabled_showsOffState() {
val state = QSTile.BooleanState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt
index b4a662974d22..f1e3e8a71398 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt
@@ -21,6 +21,7 @@ import com.android.systemui.statusbar.policy.NextAlarmController
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -88,6 +89,12 @@ class AlarmTileTest : SysuiTestCase() {
testableLooper.processAllMessages()
}
+ @After
+ fun tearDown() {
+ tile.destroy()
+ testableLooper.processAllMessages()
+ }
+
@Test
fun testAvailable() {
assertThat(tile.isAvailable).isTrue()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt
index 95e7ad9fad4d..a5c0004afe02 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt
@@ -37,6 +37,7 @@ import com.android.systemui.statusbar.policy.BatteryController
import com.android.systemui.util.settings.FakeSettings
import com.android.systemui.util.settings.SecureSettings
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
@@ -103,6 +104,12 @@ class BatterySaverTileTest : SysuiTestCase() {
testableLooper.processAllMessages()
}
+ @After
+ fun tearDown() {
+ tile.destroy()
+ testableLooper.processAllMessages()
+ }
+
@Test
fun testSettingWithCorrectUser() {
assertEquals(USER, tile.mSetting.currentUser)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt
index d65901777a73..75fd0000e0e1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt
@@ -17,11 +17,12 @@ import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.plugins.qs.QSTile
import com.android.systemui.plugins.statusbar.StatusBarStateController
-import com.android.systemui.qs.QSTileHost
+import com.android.systemui.qs.QSHost
import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.statusbar.policy.BluetoothController
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -40,7 +41,7 @@ class BluetoothTileTest : SysuiTestCase() {
@Mock
private lateinit var qsLogger: QSLogger
@Mock
- private lateinit var qsHost: QSTileHost
+ private lateinit var qsHost: QSHost
@Mock
private lateinit var metricsLogger: MetricsLogger
private val falsingManager = FalsingManagerFake()
@@ -79,6 +80,12 @@ class BluetoothTileTest : SysuiTestCase() {
testableLooper.processAllMessages()
}
+ @After
+ fun tearDown() {
+ tile.destroy()
+ testableLooper.processAllMessages()
+ }
+
@Test
fun testRestrictionChecked() {
tile.refreshState()
@@ -135,7 +142,7 @@ class BluetoothTileTest : SysuiTestCase() {
}
private class FakeBluetoothTile(
- qsTileHost: QSTileHost,
+ qsHost: QSHost,
backgroundLooper: Looper,
mainHandler: Handler,
falsingManager: FalsingManager,
@@ -145,7 +152,7 @@ class BluetoothTileTest : SysuiTestCase() {
qsLogger: QSLogger,
bluetoothController: BluetoothController
) : BluetoothTile(
- qsTileHost,
+ qsHost,
backgroundLooper,
mainHandler,
falsingManager,
@@ -187,4 +194,4 @@ class BluetoothTileTest : SysuiTestCase() {
`when`(bluetoothController.isBluetoothConnected).thenReturn(false)
`when`(bluetoothController.isBluetoothConnecting).thenReturn(true)
}
-} \ No newline at end of file
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CameraToggleTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CameraToggleTileTest.kt
index cfbb82f5f338..41938541124a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CameraToggleTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CameraToggleTileTest.kt
@@ -35,6 +35,7 @@ import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -90,6 +91,12 @@ class CameraToggleTileTest : SysuiTestCase() {
keyguardStateController)
}
+ @After
+ fun tearDown() {
+ tile.destroy()
+ testableLooper.processAllMessages()
+ }
+
@Test
fun testIcon_whenCameraAccessEnabled_isOnState() {
val state = QSTile.BooleanState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java
index b40a20c27820..64fd09d5f5d9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java
@@ -42,7 +42,7 @@ import com.android.systemui.animation.DialogLaunchAnimator;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.statusbar.connectivity.IconState;
import com.android.systemui.statusbar.connectivity.NetworkController;
@@ -53,6 +53,7 @@ import com.android.systemui.statusbar.policy.CastController.CastDevice;
import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -78,7 +79,7 @@ public class CastTileTest extends SysuiTestCase {
@Mock
private NetworkController mNetworkController;
@Mock
- private QSTileHost mHost;
+ private QSHost mHost;
@Mock
SignalCallback mSignalCallback;
@Mock
@@ -141,6 +142,12 @@ public class CastTileTest extends SysuiTestCase {
mHotspotCallback = hotspotCallbackArgumentCaptor.getValue();
}
+ @After
+ public void tearDown() {
+ mCastTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
// -------------------------------------------------
// All these tests for enabled/disabled wifi have hotspot not enabled
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorCorrectionTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorCorrectionTileTest.java
index debe41c756bd..13c30e9ea9ab 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorCorrectionTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorCorrectionTileTest.java
@@ -37,12 +37,13 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.util.settings.FakeSettings;
import com.android.systemui.util.settings.SecureSettings;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -56,7 +57,7 @@ import org.mockito.MockitoAnnotations;
public class ColorCorrectionTileTest extends SysuiTestCase {
@Mock
- private QSTileHost mHost;
+ private QSHost mHost;
@Mock
private MetricsLogger mMetricsLogger;
@Mock
@@ -101,6 +102,12 @@ public class ColorCorrectionTileTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
}
+ @After
+ public void tearDown() {
+ mTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void longClick_expectedAction() {
final ArgumentCaptor<Intent> IntentCaptor = ArgumentCaptor.forClass(Intent.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java
index 3fd25019e2a5..ff27e0255aa3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java
@@ -39,13 +39,14 @@ import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.util.settings.FakeSettings;
import com.android.systemui.util.settings.SecureSettings;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -61,7 +62,7 @@ public class ColorInversionTileTest extends SysuiTestCase {
private static final Integer COLOR_INVERSION_ENABLED = 1;
@Mock
- private QSTileHost mHost;
+ private QSHost mHost;
@Mock
private MetricsLogger mMetricsLogger;
@Mock
@@ -106,6 +107,12 @@ public class ColorInversionTileTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
}
+ @After
+ public void tearDown() {
+ mTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void longClick_expectedAction() {
final ArgumentCaptor<Intent> IntentCaptor = ArgumentCaptor.forClass(Intent.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt
index ce62f2d1cf36..b048643aba84 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt
@@ -34,6 +34,7 @@ import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.statusbar.policy.DataSaverController
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -84,6 +85,12 @@ class DataSaverTileTest : SysuiTestCase() {
)
}
+ @After
+ fun tearDown() {
+ tile.destroy()
+ testableLooper.processAllMessages()
+ }
+
@Test
fun testIcon_whenDataSaverEnabled_isOnState() {
val state = QSTile.BooleanState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
index e0b3125fd62a..b51c378f6b6b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
@@ -67,6 +67,7 @@ import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyZeroInteractions
import java.util.Optional
+import org.junit.After
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -129,6 +130,12 @@ class DeviceControlsTileTest : SysuiTestCase() {
tile = createTile()
}
+ @After
+ fun tearDown() {
+ tile.destroy()
+ testableLooper.processAllMessages()
+ }
+
private fun setupControlsComponent() {
`when`(controlsComponent.getControlsController()).thenAnswer {
if (featureEnabled) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
index ce5edb147d87..6c0904eb9bfd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
@@ -136,7 +136,8 @@ class DndTileTest : SysuiTestCase() {
@After
fun tearDown() {
- tile.handleSetListening(false)
+ tile.destroy()
+ testableLooper.processAllMessages()
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DreamTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DreamTileTest.java
index 15545a41ca10..7d41aa6c3548 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DreamTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DreamTileTest.java
@@ -47,13 +47,14 @@ import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.util.settings.FakeSettings;
import com.android.systemui.util.settings.SecureSettings;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -69,7 +70,7 @@ public class DreamTileTest extends SysuiTestCase {
@Mock
private ActivityStarter mActivityStarter;
@Mock
- private QSTileHost mHost;
+ private QSHost mHost;
@Mock
private MetricsLogger mMetricsLogger;
@Mock
@@ -112,6 +113,12 @@ public class DreamTileTest extends SysuiTestCase {
mTile.initialize();
}
+ @After
+ public void tearDown() {
+ mTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void testNotAvailable() throws RemoteException {
// Should not be available if screensaver is disabled
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FlashlightTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FlashlightTileTest.kt
index d0f851bded75..692a64422a7d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FlashlightTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FlashlightTileTest.kt
@@ -13,11 +13,12 @@ import com.android.systemui.classifier.FalsingManagerFake
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.qs.QSTile
import com.android.systemui.plugins.statusbar.StatusBarStateController
-import com.android.systemui.qs.QSTileHost
+import com.android.systemui.qs.QSHost
import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.statusbar.policy.FlashlightController
import com.google.common.truth.Truth
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -34,7 +35,7 @@ class FlashlightTileTest : SysuiTestCase() {
@Mock private lateinit var qsLogger: QSLogger
- @Mock private lateinit var qsHost: QSTileHost
+ @Mock private lateinit var qsHost: QSHost
@Mock private lateinit var metricsLogger: MetricsLogger
@@ -71,6 +72,12 @@ class FlashlightTileTest : SysuiTestCase() {
)
}
+ @After
+ fun tearDown() {
+ tile.destroy()
+ testableLooper.processAllMessages()
+ }
+
@Test
fun testIcon_whenFlashlightEnabled_isOnState() {
Mockito.`when`(flashlightController.isAvailable).thenReturn(true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt
index 257d42a83ba4..bd99cd482859 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt
@@ -15,7 +15,9 @@
*/
package com.android.systemui.qs.tiles
+import android.content.Intent
import android.os.Handler
+import android.provider.Settings
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.view.View
@@ -36,6 +38,7 @@ import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.nullable
import com.android.systemui.util.settings.FakeSettings
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -87,6 +90,12 @@ class FontScalingTileTest : SysuiTestCase() {
testableLooper.processAllMessages()
}
+ @After
+ fun tearDown() {
+ fontScalingTile.destroy()
+ testableLooper.processAllMessages()
+ }
+
@Test
fun isAvailable_whenFlagIsFalse_returnsFalse() {
featureFlags.set(Flags.ENABLE_FONT_SCALING_TILE, false)
@@ -113,4 +122,11 @@ class FontScalingTileTest : SysuiTestCase() {
verify(dialogLaunchAnimator).showFromView(any(), eq(view), nullable(), anyBoolean())
}
+
+ @Test
+ fun getLongClickIntent_getExpectedIntent() {
+ val intent: Intent? = fontScalingTile.getLongClickIntent()
+
+ assertThat(intent!!.action).isEqualTo(Settings.ACTION_TEXT_READING_SETTINGS)
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HotspotTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HotspotTileTest.java
index 451e9119f297..959e750ac5f4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HotspotTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HotspotTileTest.java
@@ -37,12 +37,13 @@ import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.policy.DataSaverController;
import com.android.systemui.statusbar.policy.HotspotController;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -60,7 +61,7 @@ public class HotspotTileTest extends SysuiTestCase {
@Rule
public MockitoRule mRule = MockitoJUnit.rule();
@Mock
- private QSTileHost mHost;
+ private QSHost mHost;
@Mock
private HotspotController mHotspotController;
@Mock
@@ -94,6 +95,12 @@ public class HotspotTileTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
}
+ @After
+ public void tearDown() {
+ mTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void handleUpdateState_wifiTetheringIsAllowed_stateIsNotUnavailable() {
MockitoSession mockitoSession = ExtendedMockito.mockitoSession()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java
index addca9d28d1a..adfd7f71e8f8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java
@@ -21,7 +21,6 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-
import android.os.Handler;
import android.service.quicksettings.Tile;
import android.testing.AndroidTestingRunner;
@@ -35,7 +34,7 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.qs.tiles.dialog.InternetDialogFactory;
@@ -44,6 +43,7 @@ import com.android.systemui.statusbar.connectivity.IconState;
import com.android.systemui.statusbar.connectivity.NetworkController;
import com.android.systemui.statusbar.connectivity.WifiIndicators;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -56,7 +56,7 @@ import org.mockito.MockitoAnnotations;
public class InternetTileTest extends SysuiTestCase {
@Mock
- private QSTileHost mHost;
+ private QSHost mHost;
@Mock
private NetworkController mNetworkController;
@Mock
@@ -92,6 +92,12 @@ public class InternetTileTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
}
+ @After
+ public void tearDown() {
+ mTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void setConnectivityStatus_defaultNetworkNotExists_updateTile() {
mTile.mSignalCallback.setConnectivityStatus(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt
index d2bbc8cfac39..33921c7c84b1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt
@@ -29,12 +29,13 @@ import com.android.systemui.classifier.FalsingManagerFake
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.qs.QSTile
import com.android.systemui.plugins.statusbar.StatusBarStateController
-import com.android.systemui.qs.QSTileHost
+import com.android.systemui.qs.QSHost
import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.statusbar.policy.LocationController
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -52,7 +53,7 @@ class LocationTileTest : SysuiTestCase() {
@Mock
private lateinit var qsLogger: QSLogger
@Mock
- private lateinit var qsHost: QSTileHost
+ private lateinit var qsHost: QSHost
@Mock
private lateinit var metricsLogger: MetricsLogger
private val falsingManager = FalsingManagerFake()
@@ -88,6 +89,12 @@ class LocationTileTest : SysuiTestCase() {
keyguardStateController)
}
+ @After
+ fun tearDown() {
+ tile.destroy()
+ testableLooper.processAllMessages()
+ }
+
@Test
fun testIcon_whenDisabled_isOffState() {
val state = QSTile.BooleanState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt
index 1ab601ce3ebe..e2f64b2cc226 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt
@@ -35,6 +35,7 @@ import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -90,6 +91,12 @@ class MicrophoneToggleTileTest : SysuiTestCase() {
keyguardStateController)
}
+ @After
+ fun tearDown() {
+ tile.destroy()
+ testableLooper.processAllMessages()
+ }
+
@Test
fun testIcon_whenMicrophoneAccessEnabled_isOnState() {
val state = QSTile.BooleanState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NfcTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NfcTileTest.java
index cfd37358dcff..c7dae83e2056 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NfcTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NfcTileTest.java
@@ -36,9 +36,10 @@ import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -60,7 +61,7 @@ public class NfcTileTest extends SysuiTestCase {
@Mock
private ActivityStarter mActivityStarter;
@Mock
- private QSTileHost mHost;
+ private QSHost mHost;
@Mock
private MetricsLogger mMetricsLogger;
@Mock
@@ -97,6 +98,12 @@ public class NfcTileTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
}
+ @After
+ public void tearDown() {
+ mNfcTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void testIsAvailable_stockWithoutNfc_returnsFalse() {
when(mMockContext.getString(R.string.quick_settings_tiles_stock)).thenReturn(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt
index 188c3a3d9e42..04af69c84cf8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt
@@ -37,6 +37,7 @@ import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.statusbar.policy.LocationController
import com.google.common.truth.Truth
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -49,32 +50,23 @@ import org.mockito.MockitoAnnotations
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@SmallTest
class NightDisplayTileTest : SysuiTestCase() {
- @Mock
- private lateinit var mHost: QSHost
+ @Mock private lateinit var mHost: QSHost
- @Mock
- private lateinit var mMetricsLogger: MetricsLogger
+ @Mock private lateinit var mMetricsLogger: MetricsLogger
- @Mock
- private lateinit var mStatusBarStateController: StatusBarStateController
+ @Mock private lateinit var mStatusBarStateController: StatusBarStateController
- @Mock
- private lateinit var mActivityStarter: ActivityStarter
+ @Mock private lateinit var mActivityStarter: ActivityStarter
- @Mock
- private lateinit var mQsLogger: QSLogger
+ @Mock private lateinit var mQsLogger: QSLogger
- @Mock
- private lateinit var mLocationController: LocationController
+ @Mock private lateinit var mLocationController: LocationController
- @Mock
- private lateinit var mColorDisplayManager: ColorDisplayManager
+ @Mock private lateinit var mColorDisplayManager: ColorDisplayManager
- @Mock
- private lateinit var mNightDisplayListenerBuilder: NightDisplayListenerModule.Builder
+ @Mock private lateinit var mNightDisplayListenerBuilder: NightDisplayListenerModule.Builder
- @Mock
- private lateinit var mNightDisplayListener: NightDisplayListener
+ @Mock private lateinit var mNightDisplayListener: NightDisplayListener
private lateinit var mTestableLooper: TestableLooper
private lateinit var mTile: NightDisplayTile
@@ -88,24 +80,30 @@ class NightDisplayTileTest : SysuiTestCase() {
whenever(mHost.context).thenReturn(mContext)
whenever(mHost.uiEventLogger).thenReturn(mUiEventLogger)
whenever(mHost.userContext).thenReturn(mContext)
- whenever(mNightDisplayListenerBuilder.setUser(anyInt())).thenReturn(
- mNightDisplayListenerBuilder
- )
+ whenever(mNightDisplayListenerBuilder.setUser(anyInt()))
+ .thenReturn(mNightDisplayListenerBuilder)
whenever(mNightDisplayListenerBuilder.build()).thenReturn(mNightDisplayListener)
- mTile = NightDisplayTile(
- mHost,
- mTestableLooper.looper,
- Handler(mTestableLooper.looper),
- FalsingManagerFake(),
- mMetricsLogger,
- mStatusBarStateController,
- mActivityStarter,
- mQsLogger,
- mLocationController,
- mColorDisplayManager,
- mNightDisplayListenerBuilder
- )
+ mTile =
+ NightDisplayTile(
+ mHost,
+ mTestableLooper.looper,
+ Handler(mTestableLooper.looper),
+ FalsingManagerFake(),
+ mMetricsLogger,
+ mStatusBarStateController,
+ mActivityStarter,
+ mQsLogger,
+ mLocationController,
+ mColorDisplayManager,
+ mNightDisplayListenerBuilder
+ )
+ }
+
+ @After
+ fun tearDown() {
+ mTile.destroy()
+ mTestableLooper.processAllMessages()
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/OneHandedModeTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/OneHandedModeTileTest.java
index 803187545a18..652c138f6478 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/OneHandedModeTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/OneHandedModeTileTest.java
@@ -32,11 +32,12 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.util.settings.SecureSettings;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -53,7 +54,7 @@ public class OneHandedModeTileTest extends SysuiTestCase {
@Mock
private ActivityStarter mActivityStarter;
@Mock
- private QSTileHost mHost;
+ private QSHost mHost;
@Mock
private MetricsLogger mMetricsLogger;
@Mock
@@ -91,6 +92,12 @@ public class OneHandedModeTileTest extends SysuiTestCase {
mTile.initialize();
}
+ @After
+ public void tearDown() {
+ mTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void testIsAvailable_unsupportOneHandedProperty_shouldReturnsFalse() {
when(mTile.isSupportOneHandedMode()).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java
index a1be2f3ac8de..3125d455acfb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java
@@ -39,10 +39,11 @@ import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qrcodescanner.controller.QRCodeScannerController;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -54,7 +55,7 @@ import org.mockito.MockitoAnnotations;
@SmallTest
public class QRCodeScannerTileTest extends SysuiTestCase {
@Mock
- private QSTileHost mHost;
+ private QSHost mHost;
@Mock
private MetricsLogger mMetricsLogger;
@Mock
@@ -91,6 +92,12 @@ public class QRCodeScannerTileTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
}
+ @After
+ public void tearDown() {
+ mTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void testNewTile() {
assertFalse(mTile.newTileState().handlesLongClick);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
index 4f6475f0148b..596df7856ee1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
@@ -66,13 +66,14 @@ import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.wallet.controller.QuickAccessWalletController;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -99,7 +100,7 @@ public class QuickAccessWalletTileTest extends SysuiTestCase {
.setComponent(new ComponentName(mContext.getPackageName(), "WalletActivity"));
@Mock
- private QSTileHost mHost;
+ private QSHost mHost;
@Mock
private MetricsLogger mMetricsLogger;
@Mock
@@ -161,6 +162,12 @@ public class QuickAccessWalletTileTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
}
+ @After
+ public void tearDown() {
+ mTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void testNewTile() {
assertFalse(mTile.newTileState().handlesLongClick);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java
index 04b372c4a361..7913628c5693 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java
@@ -38,14 +38,14 @@ import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.ReduceBrightColorsController;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.settings.UserTracker;
+import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -54,10 +54,9 @@ import org.mockito.MockitoAnnotations;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@SmallTest
-@Ignore("b/269171747")
public class ReduceBrightColorsTileTest extends SysuiTestCase {
@Mock
- private QSTileHost mHost;
+ private QSHost mHost;
@Mock
private MetricsLogger mMetricsLogger;
@Mock
@@ -99,6 +98,12 @@ public class ReduceBrightColorsTileTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
}
+ @After
+ public void tearDown() {
+ mTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void testNotActive() {
when(mReduceBrightColorsController.isReduceBrightColorsActivated()).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java
index e9dfd3ed182b..5b94cfedaedf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java
@@ -38,7 +38,7 @@ import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.policy.BatteryController;
@@ -48,6 +48,7 @@ import com.android.systemui.statusbar.policy.RotationLockControllerImpl;
import com.android.systemui.util.settings.FakeSettings;
import com.android.systemui.util.wrapper.RotationPolicyWrapper;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -71,7 +72,7 @@ public class RotationLockTileTest extends SysuiTestCase {
@Mock
private ActivityStarter mActivityStarter;
@Mock
- private QSTileHost mHost;
+ private QSHost mHost;
@Mock
private MetricsLogger mMetricsLogger;
@Mock
@@ -139,6 +140,12 @@ public class RotationLockTileTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
}
+ @After
+ public void tearDown() {
+ mLockTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
@Test
public void testSecondaryString_cameraRotateOn_returnsFaceBased() {
assertEquals(mContext.getString(R.string.rotation_lock_camera_rotation_on),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
index 30debdf4b744..5aef75832fac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
@@ -43,13 +43,14 @@ import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.screenrecord.RecordingController;
import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -65,7 +66,7 @@ public class ScreenRecordTileTest extends SysuiTestCase {
@Mock
private RecordingController mController;
@Mock
- private QSTileHost mHost;
+ private QSHost mHost;
@Mock
private KeyguardDismissUtil mKeyguardDismissUtil;
@Mock
@@ -114,6 +115,12 @@ public class ScreenRecordTileTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
}
+ @After
+ public void tearDown() {
+ mTile.destroy();
+ mTestableLooper.processAllMessages();
+ }
+
// Test that the tile is inactive and labeled correctly when the controller is neither starting
// or recording, and that clicking on the tile in this state brings up the record prompt
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UiModeNightTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UiModeNightTileTest.kt
index 0c070da1fcb9..b55657163382 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UiModeNightTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UiModeNightTileTest.kt
@@ -32,13 +32,14 @@ import com.android.systemui.classifier.FalsingManagerFake
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.qs.QSTile
import com.android.systemui.plugins.statusbar.StatusBarStateController
-import com.android.systemui.qs.QSTileHost
+import com.android.systemui.qs.QSHost
import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.statusbar.policy.BatteryController
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.LocationController
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -55,7 +56,7 @@ class UiModeNightTileTest : SysuiTestCase() {
@Mock private lateinit var uiModeManager: UiModeManager
@Mock private lateinit var resources: Resources
@Mock private lateinit var qsLogger: QSLogger
- @Mock private lateinit var qsHost: QSTileHost
+ @Mock private lateinit var qsHost: QSHost
@Mock private lateinit var metricsLogger: MetricsLogger
@Mock private lateinit var statusBarStateController: StatusBarStateController
@Mock private lateinit var activityStarter: ActivityStarter
@@ -98,6 +99,12 @@ class UiModeNightTileTest : SysuiTestCase() {
)
}
+ @After
+ fun tearDown() {
+ tile.destroy()
+ testableLooper.processAllMessages()
+ }
+
@Test
fun testIcon_whenNightModeOn_isOnState() {
val state = QSTile.BooleanState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsActivityTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsActivityTest.java
index d828e510999a..515e1ee172ed 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsActivityTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsActivityTest.java
@@ -57,6 +57,7 @@ import com.android.systemui.settings.UserTracker;
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -65,7 +66,6 @@ import org.mockito.MockitoAnnotations;
import java.util.function.BiConsumer;
-
@RunWith(AndroidTestingRunner.class)
public final class AppClipsActivityTest extends SysuiTestCase {
@@ -140,6 +140,7 @@ public final class AppClipsActivityTest extends SysuiTestCase {
mActivityRule.finishActivity();
}
+ @Ignore("b/269403503")
@Test
public void appClipsLaunched_screenshotDisplayed() {
launchActivity();
@@ -147,6 +148,7 @@ public final class AppClipsActivityTest extends SysuiTestCase {
assertThat(((ImageView) mActivity.findViewById(R.id.preview)).getDrawable()).isNotNull();
}
+ @Ignore("b/269403503")
@Test
public void screenshotDisplayed_userConsented_screenshotExportedSuccessfully() {
ResultReceiver resultReceiver = createResultReceiver((resultCode, data) -> {
@@ -166,6 +168,7 @@ public final class AppClipsActivityTest extends SysuiTestCase {
verify(mUiEventLogger).log(SCREENSHOT_FOR_NOTE_ACCEPTED, TEST_UID, TEST_CALLING_PACKAGE);
}
+ @Ignore("b/269403503")
@Test
public void screenshotDisplayed_userDeclined() {
ResultReceiver resultReceiver = createResultReceiver((resultCode, data) -> {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerTest.kt
deleted file mode 100644
index e684007cb7c1..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerTest.kt
+++ /dev/null
@@ -1,319 +0,0 @@
-package com.android.systemui.shade
-
-import android.animation.Animator
-import android.app.StatusBarManager
-import android.content.Context
-import android.testing.AndroidTestingRunner
-import android.view.View
-import android.view.ViewPropertyAnimator
-import android.widget.TextView
-import androidx.test.filters.SmallTest
-import com.android.systemui.R
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.animation.Interpolators
-import com.android.systemui.animation.ShadeInterpolation
-import com.android.systemui.battery.BatteryMeterView
-import com.android.systemui.battery.BatteryMeterViewController
-import com.android.systemui.demomode.DemoMode
-import com.android.systemui.demomode.DemoModeController
-import com.android.systemui.dump.DumpManager
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
-import com.android.systemui.qs.HeaderPrivacyIconsController
-import com.android.systemui.qs.carrier.QSCarrierGroup
-import com.android.systemui.qs.carrier.QSCarrierGroupController
-import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
-import com.android.systemui.statusbar.phone.StatusBarIconController
-import com.android.systemui.statusbar.phone.StatusIconContainer
-import com.android.systemui.statusbar.policy.Clock
-import com.android.systemui.statusbar.policy.FakeConfigurationController
-import com.android.systemui.statusbar.policy.VariableDateViewController
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.argumentCaptor
-import com.android.systemui.util.mockito.capture
-import com.android.systemui.util.mockito.mock
-import com.google.common.truth.Truth.assertThat
-import org.junit.After
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Answers
-import org.mockito.ArgumentMatchers.anyFloat
-import org.mockito.ArgumentMatchers.anyInt
-import org.mockito.Mock
-import org.mockito.Mockito.mock
-import org.mockito.Mockito.reset
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.verifyZeroInteractions
-import org.mockito.junit.MockitoJUnit
-import org.mockito.Mockito.`when` as whenever
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
-class LargeScreenShadeHeaderControllerTest : SysuiTestCase() {
-
- @Mock private lateinit var view: View
- @Mock private lateinit var statusIcons: StatusIconContainer
- @Mock private lateinit var statusBarIconController: StatusBarIconController
- @Mock private lateinit var iconManagerFactory: StatusBarIconController.TintedIconManager.Factory
- @Mock private lateinit var iconManager: StatusBarIconController.TintedIconManager
- @Mock private lateinit var qsCarrierGroupController: QSCarrierGroupController
- @Mock private lateinit var qsCarrierGroupControllerBuilder: QSCarrierGroupController.Builder
- @Mock private lateinit var featureFlags: FeatureFlags
- @Mock private lateinit var clock: Clock
- @Mock private lateinit var date: TextView
- @Mock private lateinit var carrierGroup: QSCarrierGroup
- @Mock private lateinit var batteryMeterView: BatteryMeterView
- @Mock private lateinit var batteryMeterViewController: BatteryMeterViewController
- @Mock private lateinit var privacyIconsController: HeaderPrivacyIconsController
- @Mock private lateinit var insetsProvider: StatusBarContentInsetsProvider
- @Mock private lateinit var variableDateViewControllerFactory: VariableDateViewController.Factory
- @Mock private lateinit var variableDateViewController: VariableDateViewController
- @Mock private lateinit var dumpManager: DumpManager
- @Mock private lateinit var combinedShadeHeadersConstraintManager:
- CombinedShadeHeadersConstraintManager
-
- @Mock private lateinit var mockedContext: Context
- @Mock private lateinit var demoModeController: DemoModeController
- @Mock private lateinit var qsBatteryModeController: QsBatteryModeController
-
- @JvmField @Rule val mockitoRule = MockitoJUnit.rule()
- var viewVisibility = View.GONE
- var viewAlpha = 1f
-
- private lateinit var mLargeScreenShadeHeaderController: LargeScreenShadeHeaderController
- private lateinit var carrierIconSlots: List<String>
- private val configurationController = FakeConfigurationController()
-
- @Before
- fun setup() {
- whenever<Clock>(view.findViewById(R.id.clock)).thenReturn(clock)
- whenever(clock.context).thenReturn(mockedContext)
- whenever<TextView>(view.findViewById(R.id.date)).thenReturn(date)
- whenever(date.context).thenReturn(mockedContext)
- whenever<QSCarrierGroup>(view.findViewById(R.id.carrier_group)).thenReturn(carrierGroup)
- whenever<BatteryMeterView>(view.findViewById(R.id.batteryRemainingIcon))
- .thenReturn(batteryMeterView)
- whenever<StatusIconContainer>(view.findViewById(R.id.statusIcons)).thenReturn(statusIcons)
- whenever(view.context).thenReturn(context)
- whenever(view.resources).thenReturn(context.resources)
- whenever(statusIcons.context).thenReturn(context)
- whenever(qsCarrierGroupControllerBuilder.setQSCarrierGroup(any()))
- .thenReturn(qsCarrierGroupControllerBuilder)
- whenever(qsCarrierGroupControllerBuilder.build()).thenReturn(qsCarrierGroupController)
- whenever(view.setVisibility(anyInt())).then {
- viewVisibility = it.arguments[0] as Int
- null
- }
- whenever(view.visibility).thenAnswer { _ -> viewVisibility }
-
- whenever(view.setAlpha(anyFloat())).then {
- viewAlpha = it.arguments[0] as Float
- null
- }
- whenever(view.alpha).thenAnswer { _ -> viewAlpha }
-
- whenever(variableDateViewControllerFactory.create(any()))
- .thenReturn(variableDateViewController)
- whenever(iconManagerFactory.create(any(), any())).thenReturn(iconManager)
- whenever(featureFlags.isEnabled(Flags.COMBINED_QS_HEADERS)).thenReturn(false)
- mLargeScreenShadeHeaderController = LargeScreenShadeHeaderController(
- view,
- statusBarIconController,
- iconManagerFactory,
- privacyIconsController,
- insetsProvider,
- configurationController,
- variableDateViewControllerFactory,
- batteryMeterViewController,
- dumpManager,
- featureFlags,
- qsCarrierGroupControllerBuilder,
- combinedShadeHeadersConstraintManager,
- demoModeController,
- qsBatteryModeController,
- )
- whenever(view.isAttachedToWindow).thenReturn(true)
- mLargeScreenShadeHeaderController.init()
- carrierIconSlots = listOf(
- context.getString(com.android.internal.R.string.status_bar_mobile))
- }
-
- @After
- fun verifyEveryTest() {
- verifyZeroInteractions(combinedShadeHeadersConstraintManager)
- }
-
- @Test
- fun setVisible_onlyWhenActive() {
- makeShadeVisible()
- assertThat(viewVisibility).isEqualTo(View.VISIBLE)
-
- mLargeScreenShadeHeaderController.largeScreenActive = false
- assertThat(viewVisibility).isEqualTo(View.GONE)
- }
-
- @Test
- fun updateListeners_registersWhenVisible() {
- makeShadeVisible()
- verify(qsCarrierGroupController).setListening(true)
- }
-
- @Test
- fun statusIconsAddedWhenAttached() {
- verify(statusBarIconController).addIconGroup(any())
- }
-
- @Test
- fun statusIconsRemovedWhenDettached() {
- mLargeScreenShadeHeaderController.simulateViewDetached()
- verify(statusBarIconController).removeIconGroup(any())
- }
-
- @Test
- fun shadeExpandedFraction_updatesAlpha() {
- makeShadeVisible()
- mLargeScreenShadeHeaderController.shadeExpandedFraction = 0.5f
- verify(view).setAlpha(ShadeInterpolation.getContentAlpha(0.5f))
- }
-
- @Test
- fun singleCarrier_enablesCarrierIconsInStatusIcons() {
- whenever(qsCarrierGroupController.isSingleCarrier).thenReturn(true)
-
- makeShadeVisible()
-
- verify(statusIcons).removeIgnoredSlots(carrierIconSlots)
- }
-
- @Test
- fun dualCarrier_disablesCarrierIconsInStatusIcons() {
- whenever(qsCarrierGroupController.isSingleCarrier).thenReturn(false)
-
- makeShadeVisible()
-
- verify(statusIcons).addIgnoredSlots(carrierIconSlots)
- }
-
- @Test
- fun disableQS_notDisabled_visible() {
- makeShadeVisible()
- mLargeScreenShadeHeaderController.disable(0, 0, false)
-
- assertThat(viewVisibility).isEqualTo(View.VISIBLE)
- }
-
- @Test
- fun disableQS_disabled_gone() {
- makeShadeVisible()
- mLargeScreenShadeHeaderController.disable(0, StatusBarManager.DISABLE2_QUICK_SETTINGS,
- false)
-
- assertThat(viewVisibility).isEqualTo(View.GONE)
- }
-
- private fun makeShadeVisible() {
- mLargeScreenShadeHeaderController.largeScreenActive = true
- mLargeScreenShadeHeaderController.qsVisible = true
- }
-
- @Test
- fun updateConfig_changesFontStyle() {
- configurationController.notifyDensityOrFontScaleChanged()
-
- verify(clock).setTextAppearance(R.style.TextAppearance_QS_Status)
- verify(date).setTextAppearance(R.style.TextAppearance_QS_Status)
- verify(carrierGroup).updateTextAppearance(R.style.TextAppearance_QS_Status_Carriers)
- }
-
- @Test
- fun alarmIconIgnored() {
- verify(statusIcons).addIgnoredSlot(
- context.getString(com.android.internal.R.string.status_bar_alarm_clock)
- )
- }
-
- @Test
- fun animateOutOnStartCustomizing() {
- val animator = mock(ViewPropertyAnimator::class.java, Answers.RETURNS_SELF)
- val duration = 1000L
- whenever(view.animate()).thenReturn(animator)
-
- mLargeScreenShadeHeaderController.startCustomizingAnimation(show = true, duration)
-
- verify(animator).setDuration(duration)
- verify(animator).alpha(0f)
- verify(animator).setInterpolator(Interpolators.ALPHA_OUT)
- verify(animator).start()
- }
-
- @Test
- fun animateInOnEndCustomizing() {
- val animator = mock(ViewPropertyAnimator::class.java, Answers.RETURNS_SELF)
- val duration = 1000L
- whenever(view.animate()).thenReturn(animator)
-
- mLargeScreenShadeHeaderController.startCustomizingAnimation(show = false, duration)
-
- verify(animator).setDuration(duration)
- verify(animator).alpha(1f)
- verify(animator).setInterpolator(Interpolators.ALPHA_IN)
- verify(animator).start()
- }
-
- @Test
- fun customizerAnimatorChangesViewVisibility() {
- makeShadeVisible()
-
- val animator = mock(ViewPropertyAnimator::class.java, Answers.RETURNS_SELF)
- val duration = 1000L
- whenever(view.animate()).thenReturn(animator)
- val listenerCaptor = argumentCaptor<Animator.AnimatorListener>()
-
- mLargeScreenShadeHeaderController.startCustomizingAnimation(show = true, duration)
- verify(animator).setListener(capture(listenerCaptor))
- // Start and end the animation
- listenerCaptor.value.onAnimationStart(mock())
- listenerCaptor.value.onAnimationEnd(mock())
- assertThat(viewVisibility).isEqualTo(View.INVISIBLE)
-
- reset(animator)
- mLargeScreenShadeHeaderController.startCustomizingAnimation(show = false, duration)
- verify(animator).setListener(capture(listenerCaptor))
- // Start and end the animation
- listenerCaptor.value.onAnimationStart(mock())
- listenerCaptor.value.onAnimationEnd(mock())
- assertThat(viewVisibility).isEqualTo(View.VISIBLE)
- }
-
- @Test
- fun animatorListenerClearedAtEnd() {
- val animator = mock(ViewPropertyAnimator::class.java, Answers.RETURNS_SELF)
- whenever(view.animate()).thenReturn(animator)
-
- mLargeScreenShadeHeaderController.startCustomizingAnimation(show = true, 0L)
- val listenerCaptor = argumentCaptor<Animator.AnimatorListener>()
- verify(animator).setListener(capture(listenerCaptor))
-
- listenerCaptor.value.onAnimationEnd(mock())
- verify(animator).setListener(null)
- }
-
- @Test
- fun demoMode_attachDemoMode() {
- val cb = argumentCaptor<DemoMode>()
- verify(demoModeController).addCallback(capture(cb))
- cb.value.onDemoModeStarted()
- verify(clock).onDemoModeStarted()
- }
-
- @Test
- fun demoMode_detachDemoMode() {
- mLargeScreenShadeHeaderController.simulateViewDetached()
- val cb = argumentCaptor<DemoMode>()
- verify(demoModeController).removeCallback(capture(cb))
- cb.value.onDemoModeFinished()
- verify(clock).onDemoModeFinished()
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
new file mode 100644
index 000000000000..4f469f753bdf
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
@@ -0,0 +1,754 @@
+/*
+ * Copyright (C) 2023 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.shade;
+
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+
+import static com.android.keyguard.KeyguardClockSwitch.LARGE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.annotation.IdRes;
+import android.content.ContentResolver;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.database.ContentObserver;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.PowerManager;
+import android.os.UserManager;
+import android.util.DisplayMetrics;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.view.ViewPropertyAnimator;
+import android.view.ViewStub;
+import android.view.ViewTreeObserver;
+import android.view.accessibility.AccessibilityManager;
+
+import androidx.constraintlayout.widget.ConstraintSet;
+
+import com.android.internal.jank.InteractionJankMonitor;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.logging.testing.UiEventLoggerFake;
+import com.android.internal.util.LatencyTracker;
+import com.android.keyguard.KeyguardClockSwitch;
+import com.android.keyguard.KeyguardClockSwitchController;
+import com.android.keyguard.KeyguardStatusView;
+import com.android.keyguard.KeyguardStatusViewController;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.LockIconViewController;
+import com.android.keyguard.dagger.KeyguardQsUserSwitchComponent;
+import com.android.keyguard.dagger.KeyguardStatusBarViewComponent;
+import com.android.keyguard.dagger.KeyguardStatusViewComponent;
+import com.android.keyguard.dagger.KeyguardUserSwitcherComponent;
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.biometrics.AuthController;
+import com.android.systemui.classifier.FalsingCollectorFake;
+import com.android.systemui.classifier.FalsingManagerFake;
+import com.android.systemui.common.ui.view.LongPressHandlingView;
+import com.android.systemui.doze.DozeLog;
+import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.fragments.FragmentHostManager;
+import com.android.systemui.fragments.FragmentService;
+import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
+import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository;
+import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository;
+import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
+import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor;
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
+import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
+import com.android.systemui.keyguard.ui.viewmodel.GoneToDreamingTransitionViewModel;
+import com.android.systemui.keyguard.ui.viewmodel.KeyguardBottomAreaViewModel;
+import com.android.systemui.keyguard.ui.viewmodel.KeyguardLongPressViewModel;
+import com.android.systemui.keyguard.ui.viewmodel.LockscreenToDreamingTransitionViewModel;
+import com.android.systemui.keyguard.ui.viewmodel.LockscreenToOccludedTransitionViewModel;
+import com.android.systemui.keyguard.ui.viewmodel.OccludedToLockscreenTransitionViewModel;
+import com.android.systemui.media.controls.pipeline.MediaDataManager;
+import com.android.systemui.media.controls.ui.KeyguardMediaController;
+import com.android.systemui.media.controls.ui.MediaHierarchyManager;
+import com.android.systemui.model.SysUiState;
+import com.android.systemui.navigationbar.NavigationBarController;
+import com.android.systemui.navigationbar.NavigationModeController;
+import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.plugins.qs.QS;
+import com.android.systemui.qs.QSFragment;
+import com.android.systemui.screenrecord.RecordingController;
+import com.android.systemui.shade.transition.ShadeTransitionController;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.KeyguardIndicationController;
+import com.android.systemui.statusbar.LockscreenShadeTransitionController;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationShadeDepthController;
+import com.android.systemui.statusbar.NotificationShadeWindowController;
+import com.android.systemui.statusbar.NotificationShelfController;
+import com.android.systemui.statusbar.PulseExpansionHandler;
+import com.android.systemui.statusbar.QsFrameTranslateController;
+import com.android.systemui.statusbar.StatusBarStateControllerImpl;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.VibratorHelper;
+import com.android.systemui.statusbar.notification.ConversationNotificationManager;
+import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinatorLogger;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
+import com.android.systemui.statusbar.notification.stack.AmbientState;
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
+import com.android.systemui.statusbar.notification.stack.NotificationRoundnessManager;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
+import com.android.systemui.statusbar.notification.stack.NotificationStackSizeCalculator;
+import com.android.systemui.statusbar.phone.CentralSurfaces;
+import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
+import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
+import com.android.systemui.statusbar.phone.HeadsUpTouchHelper;
+import com.android.systemui.statusbar.phone.KeyguardBottomAreaView;
+import com.android.systemui.statusbar.phone.KeyguardBottomAreaViewController;
+import com.android.systemui.statusbar.phone.KeyguardBypassController;
+import com.android.systemui.statusbar.phone.KeyguardStatusBarView;
+import com.android.systemui.statusbar.phone.KeyguardStatusBarViewController;
+import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
+import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
+import com.android.systemui.statusbar.phone.ScrimController;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager;
+import com.android.systemui.statusbar.phone.TapAgainViewController;
+import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.KeyguardQsUserSwitchController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.KeyguardUserSwitcherController;
+import com.android.systemui.statusbar.policy.KeyguardUserSwitcherView;
+import com.android.systemui.statusbar.window.StatusBarWindowStateController;
+import com.android.systemui.unfold.SysUIUnfoldComponent;
+import com.android.systemui.util.time.FakeSystemClock;
+import com.android.systemui.util.time.SystemClock;
+import com.android.wm.shell.animation.FlingAnimationUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.stubbing.Answer;
+
+import java.util.List;
+import java.util.Optional;
+
+import dagger.Lazy;
+import kotlinx.coroutines.CoroutineDispatcher;
+
+public class NotificationPanelViewControllerBaseTest extends SysuiTestCase {
+
+ protected static final int SPLIT_SHADE_FULL_TRANSITION_DISTANCE = 400;
+ protected static final int NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE = 50;
+ protected static final int PANEL_WIDTH = 500; // Random value just for the test.
+
+ @Mock protected CentralSurfaces mCentralSurfaces;
+ @Mock protected NotificationStackScrollLayout mNotificationStackScrollLayout;
+ @Mock protected KeyguardBottomAreaView mKeyguardBottomArea;
+ @Mock protected KeyguardBottomAreaViewController mKeyguardBottomAreaViewController;
+ @Mock protected KeyguardBottomAreaView mQsFrame;
+ @Mock protected HeadsUpManagerPhone mHeadsUpManager;
+ @Mock protected NotificationShelfController mNotificationShelfController;
+ @Mock protected NotificationGutsManager mGutsManager;
+ @Mock protected KeyguardStatusBarView mKeyguardStatusBar;
+ @Mock protected KeyguardUserSwitcherView mUserSwitcherView;
+ @Mock protected ViewStub mUserSwitcherStubView;
+ @Mock protected HeadsUpTouchHelper.Callback mHeadsUpCallback;
+ @Mock protected KeyguardUpdateMonitor mUpdateMonitor;
+ @Mock protected KeyguardBypassController mKeyguardBypassController;
+ @Mock protected DozeParameters mDozeParameters;
+ @Mock protected ScreenOffAnimationController mScreenOffAnimationController;
+ @Mock protected NotificationPanelView mView;
+ @Mock protected LayoutInflater mLayoutInflater;
+ @Mock protected FeatureFlags mFeatureFlags;
+ @Mock protected DynamicPrivacyController mDynamicPrivacyController;
+ @Mock protected StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
+ @Mock protected KeyguardStateController mKeyguardStateController;
+ @Mock protected DozeLog mDozeLog;
+ @Mock protected ShadeLogger mShadeLog;
+ @Mock protected ShadeHeightLogger mShadeHeightLogger;
+ @Mock protected CommandQueue mCommandQueue;
+ @Mock protected VibratorHelper mVibratorHelper;
+ @Mock protected LatencyTracker mLatencyTracker;
+ @Mock protected PowerManager mPowerManager;
+ @Mock protected AccessibilityManager mAccessibilityManager;
+ @Mock protected MetricsLogger mMetricsLogger;
+ @Mock protected Resources mResources;
+ @Mock protected Configuration mConfiguration;
+ @Mock protected KeyguardClockSwitch mKeyguardClockSwitch;
+ @Mock protected MediaHierarchyManager mMediaHierarchyManager;
+ @Mock protected ConversationNotificationManager mConversationNotificationManager;
+ @Mock protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+ @Mock protected KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory;
+ @Mock protected KeyguardQsUserSwitchComponent.Factory mKeyguardQsUserSwitchComponentFactory;
+ @Mock protected KeyguardQsUserSwitchComponent mKeyguardQsUserSwitchComponent;
+ @Mock protected KeyguardQsUserSwitchController mKeyguardQsUserSwitchController;
+ @Mock protected KeyguardUserSwitcherComponent.Factory mKeyguardUserSwitcherComponentFactory;
+ @Mock protected KeyguardUserSwitcherComponent mKeyguardUserSwitcherComponent;
+ @Mock protected KeyguardUserSwitcherController mKeyguardUserSwitcherController;
+ @Mock protected KeyguardStatusViewComponent mKeyguardStatusViewComponent;
+ @Mock protected KeyguardStatusBarViewComponent.Factory mKeyguardStatusBarViewComponentFactory;
+ @Mock protected KeyguardStatusBarViewComponent mKeyguardStatusBarViewComponent;
+ @Mock protected KeyguardClockSwitchController mKeyguardClockSwitchController;
+ @Mock protected KeyguardStatusViewController mKeyguardStatusViewController;
+ @Mock protected KeyguardStatusBarViewController mKeyguardStatusBarViewController;
+ @Mock protected NotificationStackScrollLayoutController
+ mNotificationStackScrollLayoutController;
+ @Mock protected NotificationShadeDepthController mNotificationShadeDepthController;
+ @Mock protected LockscreenShadeTransitionController mLockscreenShadeTransitionController;
+ @Mock protected AuthController mAuthController;
+ @Mock protected ScrimController mScrimController;
+ @Mock protected MediaDataManager mMediaDataManager;
+ @Mock protected AmbientState mAmbientState;
+ @Mock protected UserManager mUserManager;
+ @Mock protected UiEventLogger mUiEventLogger;
+ @Mock protected LockIconViewController mLockIconViewController;
+ @Mock protected KeyguardMediaController mKeyguardMediaController;
+ @Mock protected NavigationModeController mNavigationModeController;
+ @Mock protected NavigationBarController mNavigationBarController;
+ @Mock protected QuickSettingsController mQsController;
+ @Mock protected ShadeHeaderController mShadeHeaderController;
+ @Mock protected ContentResolver mContentResolver;
+ @Mock protected TapAgainViewController mTapAgainViewController;
+ @Mock protected KeyguardIndicationController mKeyguardIndicationController;
+ @Mock protected FragmentService mFragmentService;
+ @Mock protected FragmentHostManager mFragmentHostManager;
+ @Mock protected NotificationRemoteInputManager mNotificationRemoteInputManager;
+ @Mock protected RecordingController mRecordingController;
+ @Mock protected LockscreenGestureLogger mLockscreenGestureLogger;
+ @Mock protected DumpManager mDumpManager;
+ @Mock protected InteractionJankMonitor mInteractionJankMonitor;
+ @Mock protected NotificationsQSContainerController mNotificationsQSContainerController;
+ @Mock protected QsFrameTranslateController mQsFrameTranslateController;
+ @Mock protected StatusBarWindowStateController mStatusBarWindowStateController;
+ @Mock protected KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
+ @Mock protected NotificationShadeWindowController mNotificationShadeWindowController;
+ @Mock protected SysUiState mSysUiState;
+ @Mock protected NotificationListContainer mNotificationListContainer;
+ @Mock protected NotificationStackSizeCalculator mNotificationStackSizeCalculator;
+ @Mock protected UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
+ @Mock protected ShadeTransitionController mShadeTransitionController;
+ @Mock protected QS mQs;
+ @Mock protected QSFragment mQSFragment;
+ @Mock protected ViewGroup mQsHeader;
+ @Mock protected ViewParent mViewParent;
+ @Mock protected ViewTreeObserver mViewTreeObserver;
+ @Mock protected KeyguardBottomAreaViewModel mKeyguardBottomAreaViewModel;
+ @Mock protected DreamingToLockscreenTransitionViewModel
+ mDreamingToLockscreenTransitionViewModel;
+ @Mock protected OccludedToLockscreenTransitionViewModel
+ mOccludedToLockscreenTransitionViewModel;
+ @Mock protected LockscreenToDreamingTransitionViewModel
+ mLockscreenToDreamingTransitionViewModel;
+ @Mock protected LockscreenToOccludedTransitionViewModel
+ mLockscreenToOccludedTransitionViewModel;
+ @Mock protected GoneToDreamingTransitionViewModel mGoneToDreamingTransitionViewModel;
+
+ @Mock protected KeyguardTransitionInteractor mKeyguardTransitionInteractor;
+ @Mock protected KeyguardLongPressViewModel mKeyuardLongPressViewModel;
+ @Mock protected AlternateBouncerInteractor mAlternateBouncerInteractor;
+ @Mock protected MotionEvent mDownMotionEvent;
+ @Mock protected CoroutineDispatcher mMainDispatcher;
+ @Captor
+ protected ArgumentCaptor<NotificationStackScrollLayout.OnEmptySpaceClickListener>
+ mEmptySpaceClickListenerCaptor;
+
+ protected KeyguardBottomAreaInteractor mKeyguardBottomAreaInteractor;
+ protected KeyguardInteractor mKeyguardInteractor;
+ protected NotificationPanelViewController.TouchHandler mTouchHandler;
+ protected ConfigurationController mConfigurationController;
+ protected SysuiStatusBarStateController mStatusBarStateController;
+ protected NotificationPanelViewController mNotificationPanelViewController;
+ protected View.AccessibilityDelegate mAccessibilityDelegate;
+ protected NotificationsQuickSettingsContainer mNotificationContainerParent;
+ protected List<View.OnAttachStateChangeListener> mOnAttachStateChangeListeners;
+ protected Handler mMainHandler;
+ protected View.OnLayoutChangeListener mLayoutChangeListener;
+
+ protected final FalsingManagerFake mFalsingManager = new FalsingManagerFake();
+ protected final Optional<SysUIUnfoldComponent> mSysUIUnfoldComponent = Optional.empty();
+ protected final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
+ protected final ShadeExpansionStateManager mShadeExpansionStateManager =
+ new ShadeExpansionStateManager();
+
+ protected QuickSettingsController mQuickSettingsController;
+ @Mock protected Lazy<NotificationPanelViewController> mNotificationPanelViewControllerLazy;
+
+ protected FragmentHostManager.FragmentListener mFragmentListener;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mMainDispatcher = getMainDispatcher();
+ mKeyguardBottomAreaInteractor = new KeyguardBottomAreaInteractor(
+ new FakeKeyguardRepository());
+ mKeyguardInteractor = new KeyguardInteractor(new FakeKeyguardRepository(), mCommandQueue,
+ mFeatureFlags, new FakeKeyguardBouncerRepository());
+ SystemClock systemClock = new FakeSystemClock();
+ mStatusBarStateController = new StatusBarStateControllerImpl(mUiEventLogger, mDumpManager,
+ mInteractionJankMonitor, mShadeExpansionStateManager);
+
+ KeyguardStatusView keyguardStatusView = new KeyguardStatusView(mContext);
+ keyguardStatusView.setId(R.id.keyguard_status_view);
+
+ when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(false);
+ when(mHeadsUpCallback.getContext()).thenReturn(mContext);
+ when(mView.getResources()).thenReturn(mResources);
+ when(mView.getWidth()).thenReturn(PANEL_WIDTH);
+ when(mResources.getConfiguration()).thenReturn(mConfiguration);
+ mConfiguration.orientation = ORIENTATION_PORTRAIT;
+ when(mResources.getDisplayMetrics()).thenReturn(mDisplayMetrics);
+ mDisplayMetrics.density = 100;
+ when(mResources.getBoolean(R.bool.config_enableNotificationShadeDrag)).thenReturn(true);
+ when(mResources.getDimensionPixelSize(R.dimen.notifications_top_padding_split_shade))
+ .thenReturn(NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE);
+ when(mResources.getDimensionPixelSize(R.dimen.notification_panel_margin_horizontal))
+ .thenReturn(10);
+ when(mResources.getDimensionPixelSize(R.dimen.split_shade_full_transition_distance))
+ .thenReturn(SPLIT_SHADE_FULL_TRANSITION_DISTANCE);
+ when(mView.getContext()).thenReturn(getContext());
+ when(mView.findViewById(R.id.keyguard_header)).thenReturn(mKeyguardStatusBar);
+ when(mView.findViewById(R.id.keyguard_user_switcher_view)).thenReturn(mUserSwitcherView);
+ when(mView.findViewById(R.id.keyguard_user_switcher_stub)).thenReturn(
+ mUserSwitcherStubView);
+ when(mView.findViewById(R.id.keyguard_clock_container)).thenReturn(mKeyguardClockSwitch);
+ when(mView.findViewById(R.id.notification_stack_scroller))
+ .thenReturn(mNotificationStackScrollLayout);
+ when(mNotificationStackScrollLayoutController.getHeight()).thenReturn(1000);
+ when(mNotificationStackScrollLayoutController.getHeadsUpCallback())
+ .thenReturn(mHeadsUpCallback);
+ when(mKeyguardBottomAreaViewController.getView()).thenReturn(mKeyguardBottomArea);
+ when(mView.findViewById(R.id.keyguard_bottom_area)).thenReturn(mKeyguardBottomArea);
+ when(mKeyguardBottomArea.animate()).thenReturn(mock(ViewPropertyAnimator.class));
+ when(mView.findViewById(R.id.qs_frame)).thenReturn(mQsFrame);
+ when(mView.findViewById(R.id.keyguard_status_view))
+ .thenReturn(mock(KeyguardStatusView.class));
+ mNotificationContainerParent = new NotificationsQuickSettingsContainer(getContext(), null);
+ mNotificationContainerParent.addView(keyguardStatusView);
+ mNotificationContainerParent.onFinishInflate();
+ when(mView.findViewById(R.id.notification_container_parent))
+ .thenReturn(mNotificationContainerParent);
+ when(mFragmentService.getFragmentHostManager(mView)).thenReturn(mFragmentHostManager);
+ FlingAnimationUtils.Builder flingAnimationUtilsBuilder = new FlingAnimationUtils.Builder(
+ mDisplayMetrics);
+ when(mKeyguardQsUserSwitchComponentFactory.build(any()))
+ .thenReturn(mKeyguardQsUserSwitchComponent);
+ when(mKeyguardQsUserSwitchComponent.getKeyguardQsUserSwitchController())
+ .thenReturn(mKeyguardQsUserSwitchController);
+ when(mKeyguardUserSwitcherComponentFactory.build(any()))
+ .thenReturn(mKeyguardUserSwitcherComponent);
+ when(mKeyguardUserSwitcherComponent.getKeyguardUserSwitcherController())
+ .thenReturn(mKeyguardUserSwitcherController);
+ when(mScreenOffAnimationController.shouldAnimateClockChange()).thenReturn(true);
+ when(mQs.getView()).thenReturn(mView);
+ when(mQSFragment.getView()).thenReturn(mView);
+ doAnswer(invocation -> {
+ mFragmentListener = invocation.getArgument(1);
+ return null;
+ }).when(mFragmentHostManager).addTagListener(eq(QS.TAG), any());
+ doAnswer((Answer<Void>) invocation -> {
+ mTouchHandler = invocation.getArgument(0);
+ return null;
+ }).when(mView).setOnTouchListener(any(NotificationPanelViewController.TouchHandler.class));
+
+ // Dreaming->Lockscreen
+ when(mKeyguardTransitionInteractor.getDreamingToLockscreenTransition())
+ .thenReturn(emptyFlow());
+ when(mDreamingToLockscreenTransitionViewModel.getLockscreenAlpha())
+ .thenReturn(emptyFlow());
+ when(mDreamingToLockscreenTransitionViewModel.lockscreenTranslationY(anyInt()))
+ .thenReturn(emptyFlow());
+
+ // Occluded->Lockscreen
+ when(mKeyguardTransitionInteractor.getOccludedToLockscreenTransition())
+ .thenReturn(emptyFlow());
+ when(mOccludedToLockscreenTransitionViewModel.getLockscreenAlpha())
+ .thenReturn(emptyFlow());
+ when(mOccludedToLockscreenTransitionViewModel.lockscreenTranslationY(anyInt()))
+ .thenReturn(emptyFlow());
+
+ // Lockscreen->Dreaming
+ when(mKeyguardTransitionInteractor.getLockscreenToDreamingTransition())
+ .thenReturn(emptyFlow());
+ when(mLockscreenToDreamingTransitionViewModel.getLockscreenAlpha())
+ .thenReturn(emptyFlow());
+ when(mLockscreenToDreamingTransitionViewModel.lockscreenTranslationY(anyInt()))
+ .thenReturn(emptyFlow());
+
+ // Gone->Dreaming
+ when(mKeyguardTransitionInteractor.getGoneToDreamingTransition())
+ .thenReturn(emptyFlow());
+ when(mGoneToDreamingTransitionViewModel.getLockscreenAlpha())
+ .thenReturn(emptyFlow());
+ when(mGoneToDreamingTransitionViewModel.lockscreenTranslationY(anyInt()))
+ .thenReturn(emptyFlow());
+
+ // Lockscreen->Occluded
+ when(mKeyguardTransitionInteractor.getLockscreenToOccludedTransition())
+ .thenReturn(emptyFlow());
+ when(mLockscreenToOccludedTransitionViewModel.getLockscreenAlpha())
+ .thenReturn(emptyFlow());
+ when(mLockscreenToOccludedTransitionViewModel.lockscreenTranslationY(anyInt()))
+ .thenReturn(emptyFlow());
+
+ NotificationWakeUpCoordinator coordinator =
+ new NotificationWakeUpCoordinator(
+ mDumpManager,
+ mock(HeadsUpManagerPhone.class),
+ new StatusBarStateControllerImpl(new UiEventLoggerFake(), mDumpManager,
+ mInteractionJankMonitor, mShadeExpansionStateManager),
+ mKeyguardBypassController,
+ mDozeParameters,
+ mScreenOffAnimationController,
+ mock(NotificationWakeUpCoordinatorLogger.class));
+ mConfigurationController = new ConfigurationControllerImpl(mContext);
+ PulseExpansionHandler expansionHandler = new PulseExpansionHandler(
+ mContext,
+ coordinator,
+ mKeyguardBypassController, mHeadsUpManager,
+ mock(NotificationRoundnessManager.class),
+ mConfigurationController,
+ mStatusBarStateController,
+ mFalsingManager,
+ mShadeExpansionStateManager,
+ mLockscreenShadeTransitionController,
+ new FalsingCollectorFake(),
+ mDumpManager);
+ when(mKeyguardStatusViewComponentFactory.build(any()))
+ .thenReturn(mKeyguardStatusViewComponent);
+ when(mKeyguardStatusViewComponent.getKeyguardClockSwitchController())
+ .thenReturn(mKeyguardClockSwitchController);
+ when(mKeyguardStatusViewComponent.getKeyguardStatusViewController())
+ .thenReturn(mKeyguardStatusViewController);
+ when(mKeyguardStatusBarViewComponentFactory.build(any(), any()))
+ .thenReturn(mKeyguardStatusBarViewComponent);
+ when(mKeyguardStatusBarViewComponent.getKeyguardStatusBarViewController())
+ .thenReturn(mKeyguardStatusBarViewController);
+ when(mLayoutInflater.inflate(eq(R.layout.keyguard_status_view), any(), anyBoolean()))
+ .thenReturn(keyguardStatusView);
+ when(mLayoutInflater.inflate(eq(R.layout.keyguard_user_switcher), any(), anyBoolean()))
+ .thenReturn(mUserSwitcherView);
+ when(mLayoutInflater.inflate(eq(R.layout.keyguard_bottom_area), any(), anyBoolean()))
+ .thenReturn(mKeyguardBottomArea);
+ when(mNotificationRemoteInputManager.isRemoteInputActive())
+ .thenReturn(false);
+ when(mInteractionJankMonitor.begin(any(), anyInt()))
+ .thenReturn(true);
+ when(mInteractionJankMonitor.end(anyInt()))
+ .thenReturn(true);
+ doAnswer(invocation -> {
+ ((Runnable) invocation.getArgument(0)).run();
+ return null;
+ }).when(mNotificationShadeWindowController).batchApplyWindowLayoutParams(any());
+ doAnswer(invocation -> {
+ mLayoutChangeListener = invocation.getArgument(0);
+ return null;
+ }).when(mView).addOnLayoutChangeListener(any());
+
+ when(mView.getViewTreeObserver()).thenReturn(mViewTreeObserver);
+ when(mView.getParent()).thenReturn(mViewParent);
+ when(mQs.getHeader()).thenReturn(mQsHeader);
+ when(mDownMotionEvent.getAction()).thenReturn(MotionEvent.ACTION_DOWN);
+ when(mSysUiState.setFlag(anyInt(), anyBoolean())).thenReturn(mSysUiState);
+
+ mMainHandler = new Handler(Looper.getMainLooper());
+
+ when(mView.requireViewById(R.id.keyguard_long_press))
+ .thenReturn(mock(LongPressHandlingView.class));
+
+ mNotificationPanelViewController = new NotificationPanelViewController(
+ mView,
+ mMainHandler,
+ mLayoutInflater,
+ mFeatureFlags,
+ coordinator, expansionHandler, mDynamicPrivacyController, mKeyguardBypassController,
+ mFalsingManager, new FalsingCollectorFake(),
+ mKeyguardStateController,
+ mStatusBarStateController,
+ mStatusBarWindowStateController,
+ mNotificationShadeWindowController,
+ mDozeLog, mDozeParameters, mCommandQueue, mVibratorHelper,
+ mLatencyTracker, mPowerManager, mAccessibilityManager, 0, mUpdateMonitor,
+ mMetricsLogger,
+ mShadeLog,
+ mShadeHeightLogger,
+ mConfigurationController,
+ () -> flingAnimationUtilsBuilder, mStatusBarTouchableRegionManager,
+ mConversationNotificationManager, mMediaHierarchyManager,
+ mStatusBarKeyguardViewManager,
+ mGutsManager,
+ mNotificationsQSContainerController,
+ mNotificationStackScrollLayoutController,
+ mKeyguardStatusViewComponentFactory,
+ mKeyguardQsUserSwitchComponentFactory,
+ mKeyguardUserSwitcherComponentFactory,
+ mKeyguardStatusBarViewComponentFactory,
+ mLockscreenShadeTransitionController,
+ mAuthController,
+ mScrimController,
+ mUserManager,
+ mMediaDataManager,
+ mNotificationShadeDepthController,
+ mAmbientState,
+ mLockIconViewController,
+ mKeyguardMediaController,
+ mTapAgainViewController,
+ mNavigationModeController,
+ mNavigationBarController,
+ mQsController,
+ mFragmentService,
+ mContentResolver,
+ mRecordingController,
+ mShadeHeaderController,
+ mScreenOffAnimationController,
+ mLockscreenGestureLogger,
+ mShadeExpansionStateManager,
+ mNotificationRemoteInputManager,
+ mSysUIUnfoldComponent,
+ mSysUiState,
+ () -> mKeyguardBottomAreaViewController,
+ mKeyguardUnlockAnimationController,
+ mKeyguardIndicationController,
+ mNotificationListContainer,
+ mNotificationStackSizeCalculator,
+ mUnlockedScreenOffAnimationController,
+ mShadeTransitionController,
+ mInteractionJankMonitor,
+ systemClock,
+ mKeyguardBottomAreaViewModel,
+ mKeyguardBottomAreaInteractor,
+ mAlternateBouncerInteractor,
+ mDreamingToLockscreenTransitionViewModel,
+ mOccludedToLockscreenTransitionViewModel,
+ mLockscreenToDreamingTransitionViewModel,
+ mGoneToDreamingTransitionViewModel,
+ mLockscreenToOccludedTransitionViewModel,
+ mMainDispatcher,
+ mKeyguardTransitionInteractor,
+ mDumpManager,
+ mKeyuardLongPressViewModel,
+ mKeyguardInteractor);
+ mNotificationPanelViewController.initDependencies(
+ mCentralSurfaces,
+ null,
+ () -> {},
+ mNotificationShelfController);
+ mNotificationPanelViewController.setTrackingStartedListener(() -> {});
+ mNotificationPanelViewController.setOpenCloseListener(
+ new NotificationPanelViewController.OpenCloseListener() {
+ @Override
+ public void onClosingFinished() {}
+
+ @Override
+ public void onOpenStarted() {}
+ });
+ mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager);
+ ArgumentCaptor<View.OnAttachStateChangeListener> onAttachStateChangeListenerArgumentCaptor =
+ ArgumentCaptor.forClass(View.OnAttachStateChangeListener.class);
+ verify(mView, atLeast(1)).addOnAttachStateChangeListener(
+ onAttachStateChangeListenerArgumentCaptor.capture());
+ mOnAttachStateChangeListeners = onAttachStateChangeListenerArgumentCaptor.getAllValues();
+
+ ArgumentCaptor<View.AccessibilityDelegate> accessibilityDelegateArgumentCaptor =
+ ArgumentCaptor.forClass(View.AccessibilityDelegate.class);
+ verify(mView).setAccessibilityDelegate(accessibilityDelegateArgumentCaptor.capture());
+ mAccessibilityDelegate = accessibilityDelegateArgumentCaptor.getValue();
+ mNotificationPanelViewController.getStatusBarStateController()
+ .addCallback(mNotificationPanelViewController.getStatusBarStateListener());
+ mNotificationPanelViewController
+ .setHeadsUpAppearanceController(mock(HeadsUpAppearanceController.class));
+ verify(mNotificationStackScrollLayoutController)
+ .setOnEmptySpaceClickListener(mEmptySpaceClickListenerCaptor.capture());
+ verify(mKeyguardStatusViewController).displayClock(LARGE, /* animate */ true);
+ reset(mKeyguardStatusViewController);
+
+ when(mNotificationPanelViewControllerLazy.get())
+ .thenReturn(mNotificationPanelViewController);
+ mQuickSettingsController = new QuickSettingsController(
+ mNotificationPanelViewControllerLazy,
+ mView,
+ mQsFrameTranslateController,
+ mShadeTransitionController,
+ expansionHandler,
+ mNotificationRemoteInputManager,
+ mShadeExpansionStateManager,
+ mStatusBarKeyguardViewManager,
+ mNotificationStackScrollLayoutController,
+ mLockscreenShadeTransitionController,
+ mNotificationShadeDepthController,
+ mShadeHeaderController,
+ mStatusBarTouchableRegionManager,
+ mKeyguardStateController,
+ mKeyguardBypassController,
+ mUpdateMonitor,
+ mScrimController,
+ mMediaDataManager,
+ mMediaHierarchyManager,
+ mAmbientState,
+ mRecordingController,
+ mFalsingManager,
+ new FalsingCollectorFake(),
+ mAccessibilityManager,
+ mLockscreenGestureLogger,
+ mMetricsLogger,
+ mFeatureFlags,
+ mInteractionJankMonitor,
+ mShadeLog
+ );
+ }
+
+ @After
+ public void tearDown() {
+ mNotificationPanelViewController.mBottomAreaShadeAlphaAnimator.cancel();
+ mNotificationPanelViewController.cancelHeightAnimator();
+ mMainHandler.removeCallbacksAndMessages(null);
+ }
+
+ protected void setBottomPadding(int stackBottom, int lockIconPadding, int indicationPadding,
+ int ambientPadding) {
+
+ when(mNotificationStackScrollLayoutController.getTop()).thenReturn(0);
+ when(mNotificationStackScrollLayoutController.getHeight()).thenReturn(stackBottom);
+ when(mNotificationStackScrollLayoutController.getBottom()).thenReturn(stackBottom);
+ when(mLockIconViewController.getTop()).thenReturn((float) (stackBottom - lockIconPadding));
+
+ when(mResources.getDimensionPixelSize(R.dimen.keyguard_indication_bottom_padding))
+ .thenReturn(indicationPadding);
+ mNotificationPanelViewController.loadDimens();
+
+ mNotificationPanelViewController.setAmbientIndicationTop(
+ /* ambientIndicationTop= */ stackBottom - ambientPadding,
+ /* ambientTextVisible= */ true);
+ }
+
+ protected void triggerPositionClockAndNotifications() {
+ mNotificationPanelViewController.onQsSetExpansionHeightCalled(false);
+ }
+
+ protected FalsingManager.FalsingTapListener getFalsingTapListener() {
+ for (View.OnAttachStateChangeListener listener : mOnAttachStateChangeListeners) {
+ listener.onViewAttachedToWindow(mView);
+ }
+ assertThat(mFalsingManager.getTapListeners().size()).isEqualTo(1);
+ return mFalsingManager.getTapListeners().get(0);
+ }
+
+ protected void givenViewAttached() {
+ for (View.OnAttachStateChangeListener listener : mOnAttachStateChangeListeners) {
+ listener.onViewAttachedToWindow(mView);
+ }
+ }
+
+ protected ConstraintSet.Layout getConstraintSetLayout(@IdRes int id) {
+ ConstraintSet constraintSet = new ConstraintSet();
+ constraintSet.clone(mNotificationContainerParent);
+ return constraintSet.getConstraint(id).layout;
+ }
+
+ protected void enableSplitShade(boolean enabled) {
+ when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(enabled);
+ mNotificationPanelViewController.updateResources();
+ }
+
+ protected void updateMultiUserSetting(boolean enabled) {
+ when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
+ when(mUserManager.isUserSwitcherEnabled(false)).thenReturn(enabled);
+ final ArgumentCaptor<ContentObserver> observerCaptor =
+ ArgumentCaptor.forClass(ContentObserver.class);
+ verify(mContentResolver)
+ .registerContentObserver(any(), anyBoolean(), observerCaptor.capture());
+ observerCaptor.getValue().onChange(/* selfChange */ false);
+ }
+
+ protected void updateSmallestScreenWidth(int smallestScreenWidthDp) {
+ Configuration configuration = new Configuration();
+ configuration.smallestScreenWidthDp = smallestScreenWidthDp;
+ mConfigurationController.onConfigurationChanged(configuration);
+ }
+
+ protected void onTouchEvent(MotionEvent ev) {
+ mTouchHandler.onTouch(mView, ev);
+ }
+
+ protected void setDozing(boolean dozing, boolean dozingAlwaysOn) {
+ when(mDozeParameters.getAlwaysOn()).thenReturn(dozingAlwaysOn);
+ mNotificationPanelViewController.setDozing(
+ /* dozing= */ dozing,
+ /* animate= */ false
+ );
+ }
+
+ protected void assertKeyguardStatusViewCentered() {
+ mNotificationPanelViewController.updateResources();
+ assertThat(getConstraintSetLayout(R.id.keyguard_status_view).endToEnd).isAnyOf(
+ ConstraintSet.PARENT_ID, ConstraintSet.UNSET);
+ }
+
+ protected void assertKeyguardStatusViewNotCentered() {
+ mNotificationPanelViewController.updateResources();
+ assertThat(getConstraintSetLayout(R.id.keyguard_status_view).endToEnd).isEqualTo(
+ R.id.qs_edge_guideline);
+ }
+
+ protected void setIsFullWidth(boolean fullWidth) {
+ float nsslWidth = fullWidth ? PANEL_WIDTH : PANEL_WIDTH / 2f;
+ when(mNotificationStackScrollLayoutController.getWidth()).thenReturn(nsslWidth);
+ triggerLayoutChange();
+ }
+
+ protected void triggerLayoutChange() {
+ mLayoutChangeListener.onLayoutChange(
+ mView,
+ /* left= */ 0,
+ /* top= */ 0,
+ /* right= */ 0,
+ /* bottom= */ 0,
+ /* oldLeft= */ 0,
+ /* oldTop= */ 0,
+ /* oldRight= */ 0,
+ /* oldBottom= */ 0
+ );
+ }
+
+ protected CoroutineDispatcher getMainDispatcher() {
+ return mMainDispatcher;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
index b46082fdfdd4..d86ff671a222 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
@@ -16,8 +16,6 @@
package com.android.systemui.shade;
-import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
-
import static com.android.keyguard.FaceAuthApiRequestReason.NOTIFICATION_PANEL_CLICKED;
import static com.android.keyguard.KeyguardClockSwitch.LARGE;
import static com.android.keyguard.KeyguardClockSwitch.SMALL;
@@ -31,592 +29,72 @@ import static com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.atLeast;
-import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
-import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.annotation.IdRes;
-import android.content.ContentResolver;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.database.ContentObserver;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.PowerManager;
-import android.os.UserManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
-import android.util.DisplayMetrics;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewParent;
-import android.view.ViewPropertyAnimator;
-import android.view.ViewStub;
-import android.view.ViewTreeObserver;
-import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import androidx.constraintlayout.widget.ConstraintSet;
import androidx.test.filters.SmallTest;
-import com.android.internal.jank.InteractionJankMonitor;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.UiEventLogger;
-import com.android.internal.logging.testing.UiEventLoggerFake;
-import com.android.internal.util.CollectionUtils;
-import com.android.internal.util.LatencyTracker;
import com.android.keyguard.FaceAuthApiRequestReason;
-import com.android.keyguard.KeyguardClockSwitch;
-import com.android.keyguard.KeyguardClockSwitchController;
-import com.android.keyguard.KeyguardStatusView;
-import com.android.keyguard.KeyguardStatusViewController;
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.keyguard.LockIconViewController;
-import com.android.keyguard.dagger.KeyguardQsUserSwitchComponent;
-import com.android.keyguard.dagger.KeyguardStatusBarViewComponent;
-import com.android.keyguard.dagger.KeyguardStatusViewComponent;
-import com.android.keyguard.dagger.KeyguardUserSwitcherComponent;
import com.android.systemui.DejankUtils;
import com.android.systemui.R;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.biometrics.AuthController;
-import com.android.systemui.classifier.FalsingCollectorFake;
-import com.android.systemui.classifier.FalsingManagerFake;
-import com.android.systemui.common.ui.view.LongPressHandlingView;
-import com.android.systemui.doze.DozeLog;
-import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.fragments.FragmentHostManager;
-import com.android.systemui.fragments.FragmentService;
-import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
-import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
-import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor;
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
-import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.GoneToDreamingTransitionViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.KeyguardBottomAreaViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.KeyguardLongPressViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.LockscreenToDreamingTransitionViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.LockscreenToOccludedTransitionViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.OccludedToLockscreenTransitionViewModel;
-import com.android.systemui.media.controls.pipeline.MediaDataManager;
-import com.android.systemui.media.controls.ui.KeyguardMediaController;
-import com.android.systemui.media.controls.ui.MediaHierarchyManager;
-import com.android.systemui.model.SysUiState;
-import com.android.systemui.navigationbar.NavigationBarController;
-import com.android.systemui.navigationbar.NavigationModeController;
-import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.QSFragment;
-import com.android.systemui.screenrecord.RecordingController;
-import com.android.systemui.shade.transition.ShadeTransitionController;
-import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.KeyguardIndicationController;
-import com.android.systemui.statusbar.LockscreenShadeTransitionController;
-import com.android.systemui.statusbar.NotificationRemoteInputManager;
-import com.android.systemui.statusbar.NotificationShadeDepthController;
-import com.android.systemui.statusbar.NotificationShadeWindowController;
-import com.android.systemui.statusbar.NotificationShelfController;
-import com.android.systemui.statusbar.PulseExpansionHandler;
-import com.android.systemui.statusbar.QsFrameTranslateController;
-import com.android.systemui.statusbar.StatusBarStateControllerImpl;
-import com.android.systemui.statusbar.SysuiStatusBarStateController;
-import com.android.systemui.statusbar.VibratorHelper;
-import com.android.systemui.statusbar.notification.ConversationNotificationManager;
-import com.android.systemui.statusbar.notification.DynamicPrivacyController;
-import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
-import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinatorLogger;
import com.android.systemui.statusbar.notification.row.ExpandableView;
import com.android.systemui.statusbar.notification.row.ExpandableView.OnHeightChangedListener;
-import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.stack.AmbientState;
-import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
-import com.android.systemui.statusbar.notification.stack.NotificationRoundnessManager;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
-import com.android.systemui.statusbar.notification.stack.NotificationStackSizeCalculator;
-import com.android.systemui.statusbar.phone.CentralSurfaces;
-import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
-import com.android.systemui.statusbar.phone.DozeParameters;
-import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
-import com.android.systemui.statusbar.phone.HeadsUpTouchHelper;
-import com.android.systemui.statusbar.phone.KeyguardBottomAreaView;
-import com.android.systemui.statusbar.phone.KeyguardBottomAreaViewController;
-import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.KeyguardStatusBarView;
-import com.android.systemui.statusbar.phone.KeyguardStatusBarViewController;
-import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
-import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
-import com.android.systemui.statusbar.phone.ScrimController;
-import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
-import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager;
-import com.android.systemui.statusbar.phone.TapAgainViewController;
-import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
-import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.statusbar.policy.KeyguardQsUserSwitchController;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.statusbar.policy.KeyguardUserSwitcherController;
-import com.android.systemui.statusbar.policy.KeyguardUserSwitcherView;
-import com.android.systemui.statusbar.window.StatusBarWindowStateController;
-import com.android.systemui.unfold.SysUIUnfoldComponent;
-import com.android.systemui.util.time.FakeSystemClock;
-import com.android.systemui.util.time.SystemClock;
-import com.android.wm.shell.animation.FlingAnimationUtils;
-
-import org.junit.After;
+
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
import org.mockito.InOrder;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.mockito.stubbing.Answer;
import java.util.List;
-import java.util.Optional;
-
-import dagger.Lazy;
-import kotlinx.coroutines.CoroutineDispatcher;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
-public class NotificationPanelViewControllerTest extends SysuiTestCase {
-
- private static final int SPLIT_SHADE_FULL_TRANSITION_DISTANCE = 400;
- private static final int NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE = 50;
- private static final int PANEL_WIDTH = 500; // Random value just for the test.
-
- @Mock private CentralSurfaces mCentralSurfaces;
- @Mock private NotificationStackScrollLayout mNotificationStackScrollLayout;
- @Mock private KeyguardBottomAreaView mKeyguardBottomArea;
- @Mock private KeyguardBottomAreaViewController mKeyguardBottomAreaViewController;
- @Mock private KeyguardBottomAreaView mQsFrame;
- @Mock private HeadsUpManagerPhone mHeadsUpManager;
- @Mock private NotificationShelfController mNotificationShelfController;
- @Mock private NotificationGutsManager mGutsManager;
- @Mock private KeyguardStatusBarView mKeyguardStatusBar;
- @Mock private KeyguardUserSwitcherView mUserSwitcherView;
- @Mock private ViewStub mUserSwitcherStubView;
- @Mock private HeadsUpTouchHelper.Callback mHeadsUpCallback;
- @Mock private KeyguardUpdateMonitor mUpdateMonitor;
- @Mock private KeyguardBypassController mKeyguardBypassController;
- @Mock private DozeParameters mDozeParameters;
- @Mock private ScreenOffAnimationController mScreenOffAnimationController;
- @Mock private NotificationPanelView mView;
- @Mock private LayoutInflater mLayoutInflater;
- @Mock private FeatureFlags mFeatureFlags;
- @Mock private DynamicPrivacyController mDynamicPrivacyController;
- @Mock private StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
- @Mock private KeyguardStateController mKeyguardStateController;
- @Mock private DozeLog mDozeLog;
- @Mock private ShadeLogger mShadeLog;
- @Mock private ShadeHeightLogger mShadeHeightLogger;
- @Mock private CommandQueue mCommandQueue;
- @Mock private VibratorHelper mVibratorHelper;
- @Mock private LatencyTracker mLatencyTracker;
- @Mock private PowerManager mPowerManager;
- @Mock private AccessibilityManager mAccessibilityManager;
- @Mock private MetricsLogger mMetricsLogger;
- @Mock private Resources mResources;
- @Mock private Configuration mConfiguration;
- @Mock private KeyguardClockSwitch mKeyguardClockSwitch;
- @Mock private MediaHierarchyManager mMediaHierarchyManager;
- @Mock private ConversationNotificationManager mConversationNotificationManager;
- @Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
- @Mock private KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory;
- @Mock private KeyguardQsUserSwitchComponent.Factory mKeyguardQsUserSwitchComponentFactory;
- @Mock private KeyguardQsUserSwitchComponent mKeyguardQsUserSwitchComponent;
- @Mock private KeyguardQsUserSwitchController mKeyguardQsUserSwitchController;
- @Mock private KeyguardUserSwitcherComponent.Factory mKeyguardUserSwitcherComponentFactory;
- @Mock private KeyguardUserSwitcherComponent mKeyguardUserSwitcherComponent;
- @Mock private KeyguardUserSwitcherController mKeyguardUserSwitcherController;
- @Mock private KeyguardStatusViewComponent mKeyguardStatusViewComponent;
- @Mock private KeyguardStatusBarViewComponent.Factory mKeyguardStatusBarViewComponentFactory;
- @Mock private KeyguardStatusBarViewComponent mKeyguardStatusBarViewComponent;
- @Mock private KeyguardClockSwitchController mKeyguardClockSwitchController;
- @Mock private KeyguardStatusViewController mKeyguardStatusViewController;
- @Mock private KeyguardStatusBarViewController mKeyguardStatusBarViewController;
- @Mock private NotificationStackScrollLayoutController mNotificationStackScrollLayoutController;
- @Mock private NotificationShadeDepthController mNotificationShadeDepthController;
- @Mock private LockscreenShadeTransitionController mLockscreenShadeTransitionController;
- @Mock private AuthController mAuthController;
- @Mock private ScrimController mScrimController;
- @Mock private MediaDataManager mMediaDataManager;
- @Mock private AmbientState mAmbientState;
- @Mock private UserManager mUserManager;
- @Mock private UiEventLogger mUiEventLogger;
- @Mock private LockIconViewController mLockIconViewController;
- @Mock private KeyguardMediaController mKeyguardMediaController;
- @Mock private NavigationModeController mNavigationModeController;
- @Mock private NavigationBarController mNavigationBarController;
- @Mock private QuickSettingsController mQsController;
- @Mock private LargeScreenShadeHeaderController mLargeScreenShadeHeaderController;
- @Mock private ContentResolver mContentResolver;
- @Mock private TapAgainViewController mTapAgainViewController;
- @Mock private KeyguardIndicationController mKeyguardIndicationController;
- @Mock private FragmentService mFragmentService;
- @Mock private FragmentHostManager mFragmentHostManager;
- @Mock private NotificationRemoteInputManager mNotificationRemoteInputManager;
- @Mock private RecordingController mRecordingController;
- @Mock private LockscreenGestureLogger mLockscreenGestureLogger;
- @Mock private DumpManager mDumpManager;
- @Mock private InteractionJankMonitor mInteractionJankMonitor;
- @Mock private NotificationsQSContainerController mNotificationsQSContainerController;
- @Mock private QsFrameTranslateController mQsFrameTranslateController;
- @Mock private StatusBarWindowStateController mStatusBarWindowStateController;
- @Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
- @Mock private NotificationShadeWindowController mNotificationShadeWindowController;
- @Mock private SysUiState mSysUiState;
- @Mock private NotificationListContainer mNotificationListContainer;
- @Mock private NotificationStackSizeCalculator mNotificationStackSizeCalculator;
- @Mock private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
- @Mock private ShadeTransitionController mShadeTransitionController;
- @Mock private QS mQs;
- @Mock private QSFragment mQSFragment;
- @Mock private ViewGroup mQsHeader;
- @Mock private ViewParent mViewParent;
- @Mock private ViewTreeObserver mViewTreeObserver;
- @Mock private KeyguardBottomAreaViewModel mKeyguardBottomAreaViewModel;
- @Mock private KeyguardBottomAreaInteractor mKeyguardBottomAreaInteractor;
- @Mock private AlternateBouncerInteractor mAlternateBouncerInteractor;
- @Mock private DreamingToLockscreenTransitionViewModel mDreamingToLockscreenTransitionViewModel;
- @Mock private OccludedToLockscreenTransitionViewModel mOccludedToLockscreenTransitionViewModel;
- @Mock private LockscreenToDreamingTransitionViewModel mLockscreenToDreamingTransitionViewModel;
- @Mock private LockscreenToOccludedTransitionViewModel mLockscreenToOccludedTransitionViewModel;
- @Mock private GoneToDreamingTransitionViewModel mGoneToDreamingTransitionViewModel;
-
- @Mock private KeyguardTransitionInteractor mKeyguardTransitionInteractor;
- @Mock private KeyguardInteractor mKeyguardInteractor;
- @Mock private KeyguardLongPressViewModel mKeyuardLongPressViewModel;
- @Mock private CoroutineDispatcher mMainDispatcher;
- @Mock private MotionEvent mDownMotionEvent;
- @Captor
- private ArgumentCaptor<NotificationStackScrollLayout.OnEmptySpaceClickListener>
- mEmptySpaceClickListenerCaptor;
-
- private NotificationPanelViewController.TouchHandler mTouchHandler;
- private ConfigurationController mConfigurationController;
- private SysuiStatusBarStateController mStatusBarStateController;
- private NotificationPanelViewController mNotificationPanelViewController;
- private View.AccessibilityDelegate mAccessibilityDelegate;
- private NotificationsQuickSettingsContainer mNotificationContainerParent;
- private List<View.OnAttachStateChangeListener> mOnAttachStateChangeListeners;
- private Handler mMainHandler;
- private View.OnLayoutChangeListener mLayoutChangeListener;
-
- private final FalsingManagerFake mFalsingManager = new FalsingManagerFake();
- private final Optional<SysUIUnfoldComponent> mSysUIUnfoldComponent = Optional.empty();
- private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
- private final ShadeExpansionStateManager mShadeExpansionStateManager =
- new ShadeExpansionStateManager();
-
- private QuickSettingsController mQuickSettingsController;
- @Mock private Lazy<NotificationPanelViewController> mNotificationPanelViewControllerLazy;
-
- private FragmentHostManager.FragmentListener mFragmentListener;
+public class NotificationPanelViewControllerTest extends NotificationPanelViewControllerBaseTest {
@Before
- public void setup() {
- MockitoAnnotations.initMocks(this);
- SystemClock systemClock = new FakeSystemClock();
- mStatusBarStateController = new StatusBarStateControllerImpl(mUiEventLogger, mDumpManager,
- mInteractionJankMonitor, mShadeExpansionStateManager);
-
- KeyguardStatusView keyguardStatusView = new KeyguardStatusView(mContext);
- keyguardStatusView.setId(R.id.keyguard_status_view);
+ public void before() {
DejankUtils.setImmediate(true);
+ }
- when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(false);
- when(mHeadsUpCallback.getContext()).thenReturn(mContext);
- when(mView.getResources()).thenReturn(mResources);
- when(mView.getWidth()).thenReturn(PANEL_WIDTH);
- when(mResources.getConfiguration()).thenReturn(mConfiguration);
- mConfiguration.orientation = ORIENTATION_PORTRAIT;
- when(mResources.getDisplayMetrics()).thenReturn(mDisplayMetrics);
- mDisplayMetrics.density = 100;
- when(mResources.getBoolean(R.bool.config_enableNotificationShadeDrag)).thenReturn(true);
- when(mResources.getDimensionPixelSize(R.dimen.notifications_top_padding_split_shade))
- .thenReturn(NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE);
- when(mResources.getDimensionPixelSize(R.dimen.notification_panel_margin_horizontal))
- .thenReturn(10);
- when(mResources.getDimensionPixelSize(R.dimen.split_shade_full_transition_distance))
- .thenReturn(SPLIT_SHADE_FULL_TRANSITION_DISTANCE);
- when(mView.getContext()).thenReturn(getContext());
- when(mView.findViewById(R.id.keyguard_header)).thenReturn(mKeyguardStatusBar);
- when(mView.findViewById(R.id.keyguard_user_switcher_view)).thenReturn(mUserSwitcherView);
- when(mView.findViewById(R.id.keyguard_user_switcher_stub)).thenReturn(
- mUserSwitcherStubView);
- when(mView.findViewById(R.id.keyguard_clock_container)).thenReturn(mKeyguardClockSwitch);
- when(mView.findViewById(R.id.notification_stack_scroller))
- .thenReturn(mNotificationStackScrollLayout);
- when(mNotificationStackScrollLayoutController.getHeight()).thenReturn(1000);
- when(mNotificationStackScrollLayoutController.getHeadsUpCallback())
- .thenReturn(mHeadsUpCallback);
- when(mKeyguardBottomAreaViewController.getView()).thenReturn(mKeyguardBottomArea);
- when(mView.findViewById(R.id.keyguard_bottom_area)).thenReturn(mKeyguardBottomArea);
- when(mKeyguardBottomArea.animate()).thenReturn(mock(ViewPropertyAnimator.class));
- when(mView.findViewById(R.id.qs_frame)).thenReturn(mQsFrame);
- when(mView.findViewById(R.id.keyguard_status_view))
- .thenReturn(mock(KeyguardStatusView.class));
- mNotificationContainerParent = new NotificationsQuickSettingsContainer(getContext(), null);
- mNotificationContainerParent.addView(keyguardStatusView);
- mNotificationContainerParent.onFinishInflate();
- when(mView.findViewById(R.id.notification_container_parent))
- .thenReturn(mNotificationContainerParent);
- when(mFragmentService.getFragmentHostManager(mView)).thenReturn(mFragmentHostManager);
- FlingAnimationUtils.Builder flingAnimationUtilsBuilder = new FlingAnimationUtils.Builder(
- mDisplayMetrics);
- when(mKeyguardQsUserSwitchComponentFactory.build(any()))
- .thenReturn(mKeyguardQsUserSwitchComponent);
- when(mKeyguardQsUserSwitchComponent.getKeyguardQsUserSwitchController())
- .thenReturn(mKeyguardQsUserSwitchController);
- when(mKeyguardUserSwitcherComponentFactory.build(any()))
- .thenReturn(mKeyguardUserSwitcherComponent);
- when(mKeyguardUserSwitcherComponent.getKeyguardUserSwitcherController())
- .thenReturn(mKeyguardUserSwitcherController);
- when(mScreenOffAnimationController.shouldAnimateClockChange()).thenReturn(true);
- when(mQs.getView()).thenReturn(mView);
- when(mQSFragment.getView()).thenReturn(mView);
- doAnswer(invocation -> {
- mFragmentListener = invocation.getArgument(1);
- return null;
- }).when(mFragmentHostManager).addTagListener(eq(QS.TAG), any());
- doAnswer((Answer<Void>) invocation -> {
- mTouchHandler = invocation.getArgument(0);
- return null;
- }).when(mView).setOnTouchListener(any(NotificationPanelViewController.TouchHandler.class));
-
- NotificationWakeUpCoordinator coordinator =
- new NotificationWakeUpCoordinator(
- mDumpManager,
- mock(HeadsUpManagerPhone.class),
- new StatusBarStateControllerImpl(new UiEventLoggerFake(), mDumpManager,
- mInteractionJankMonitor, mShadeExpansionStateManager),
- mKeyguardBypassController,
- mDozeParameters,
- mScreenOffAnimationController,
- mock(NotificationWakeUpCoordinatorLogger.class));
- mConfigurationController = new ConfigurationControllerImpl(mContext);
- PulseExpansionHandler expansionHandler = new PulseExpansionHandler(
- mContext,
- coordinator,
- mKeyguardBypassController, mHeadsUpManager,
- mock(NotificationRoundnessManager.class),
- mConfigurationController,
- mStatusBarStateController,
- mFalsingManager,
- mShadeExpansionStateManager,
- mLockscreenShadeTransitionController,
- new FalsingCollectorFake(),
- mDumpManager);
- when(mKeyguardStatusViewComponentFactory.build(any()))
- .thenReturn(mKeyguardStatusViewComponent);
- when(mKeyguardStatusViewComponent.getKeyguardClockSwitchController())
- .thenReturn(mKeyguardClockSwitchController);
- when(mKeyguardStatusViewComponent.getKeyguardStatusViewController())
- .thenReturn(mKeyguardStatusViewController);
- when(mKeyguardStatusBarViewComponentFactory.build(any(), any()))
- .thenReturn(mKeyguardStatusBarViewComponent);
- when(mKeyguardStatusBarViewComponent.getKeyguardStatusBarViewController())
- .thenReturn(mKeyguardStatusBarViewController);
- when(mLayoutInflater.inflate(eq(R.layout.keyguard_status_view), any(), anyBoolean()))
- .thenReturn(keyguardStatusView);
- when(mLayoutInflater.inflate(eq(R.layout.keyguard_user_switcher), any(), anyBoolean()))
- .thenReturn(mUserSwitcherView);
- when(mLayoutInflater.inflate(eq(R.layout.keyguard_bottom_area), any(), anyBoolean()))
- .thenReturn(mKeyguardBottomArea);
- when(mNotificationRemoteInputManager.isRemoteInputActive())
- .thenReturn(false);
- when(mInteractionJankMonitor.begin(any(), anyInt()))
- .thenReturn(true);
- when(mInteractionJankMonitor.end(anyInt()))
- .thenReturn(true);
- doAnswer(invocation -> {
- ((Runnable) invocation.getArgument(0)).run();
- return null;
- }).when(mNotificationShadeWindowController).batchApplyWindowLayoutParams(any());
- doAnswer(invocation -> {
- mLayoutChangeListener = invocation.getArgument(0);
- return null;
- }).when(mView).addOnLayoutChangeListener(any());
-
- when(mView.getViewTreeObserver()).thenReturn(mViewTreeObserver);
- when(mView.getParent()).thenReturn(mViewParent);
- when(mQs.getHeader()).thenReturn(mQsHeader);
- when(mDownMotionEvent.getAction()).thenReturn(MotionEvent.ACTION_DOWN);
- when(mSysUiState.setFlag(anyInt(), anyBoolean())).thenReturn(mSysUiState);
-
- mMainHandler = new Handler(Looper.getMainLooper());
-
- when(mView.requireViewById(R.id.keyguard_long_press))
- .thenReturn(mock(LongPressHandlingView.class));
-
- mNotificationPanelViewController = new NotificationPanelViewController(
- mView,
- mMainHandler,
- mLayoutInflater,
- mFeatureFlags,
- coordinator, expansionHandler, mDynamicPrivacyController, mKeyguardBypassController,
- mFalsingManager, new FalsingCollectorFake(),
- mKeyguardStateController,
- mStatusBarStateController,
- mStatusBarWindowStateController,
- mNotificationShadeWindowController,
- mDozeLog, mDozeParameters, mCommandQueue, mVibratorHelper,
- mLatencyTracker, mPowerManager, mAccessibilityManager, 0, mUpdateMonitor,
- mMetricsLogger,
- mShadeLog,
- mShadeHeightLogger,
- mConfigurationController,
- () -> flingAnimationUtilsBuilder, mStatusBarTouchableRegionManager,
- mConversationNotificationManager, mMediaHierarchyManager,
- mStatusBarKeyguardViewManager,
- mGutsManager,
- mNotificationsQSContainerController,
- mNotificationStackScrollLayoutController,
- mKeyguardStatusViewComponentFactory,
- mKeyguardQsUserSwitchComponentFactory,
- mKeyguardUserSwitcherComponentFactory,
- mKeyguardStatusBarViewComponentFactory,
- mLockscreenShadeTransitionController,
- mAuthController,
- mScrimController,
- mUserManager,
- mMediaDataManager,
- mNotificationShadeDepthController,
- mAmbientState,
- mLockIconViewController,
- mKeyguardMediaController,
- mTapAgainViewController,
- mNavigationModeController,
- mNavigationBarController,
- mQsController,
- mFragmentService,
- mContentResolver,
- mRecordingController,
- mLargeScreenShadeHeaderController,
- mScreenOffAnimationController,
- mLockscreenGestureLogger,
- mShadeExpansionStateManager,
- mNotificationRemoteInputManager,
- mSysUIUnfoldComponent,
- mSysUiState,
- () -> mKeyguardBottomAreaViewController,
- mKeyguardUnlockAnimationController,
- mKeyguardIndicationController,
- mNotificationListContainer,
- mNotificationStackSizeCalculator,
- mUnlockedScreenOffAnimationController,
- mShadeTransitionController,
- systemClock,
- mKeyguardBottomAreaViewModel,
- mKeyguardBottomAreaInteractor,
- mAlternateBouncerInteractor,
- mDreamingToLockscreenTransitionViewModel,
- mOccludedToLockscreenTransitionViewModel,
- mLockscreenToDreamingTransitionViewModel,
- mGoneToDreamingTransitionViewModel,
- mLockscreenToOccludedTransitionViewModel,
- mMainDispatcher,
- mKeyguardTransitionInteractor,
- mDumpManager,
- mKeyuardLongPressViewModel,
- mKeyguardInteractor);
- mNotificationPanelViewController.initDependencies(
- mCentralSurfaces,
- null,
- () -> {},
- mNotificationShelfController);
- mNotificationPanelViewController.setTrackingStartedListener(() -> {});
- mNotificationPanelViewController.setOpenCloseListener(
- new NotificationPanelViewController.OpenCloseListener() {
- @Override
- public void onClosingFinished() {}
-
- @Override
- public void onOpenStarted() {}
- });
- mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager);
- ArgumentCaptor<View.OnAttachStateChangeListener> onAttachStateChangeListenerArgumentCaptor =
- ArgumentCaptor.forClass(View.OnAttachStateChangeListener.class);
- verify(mView, atLeast(1)).addOnAttachStateChangeListener(
- onAttachStateChangeListenerArgumentCaptor.capture());
- mOnAttachStateChangeListeners = onAttachStateChangeListenerArgumentCaptor.getAllValues();
-
- ArgumentCaptor<View.AccessibilityDelegate> accessibilityDelegateArgumentCaptor =
- ArgumentCaptor.forClass(View.AccessibilityDelegate.class);
- verify(mView).setAccessibilityDelegate(accessibilityDelegateArgumentCaptor.capture());
- mAccessibilityDelegate = accessibilityDelegateArgumentCaptor.getValue();
- mNotificationPanelViewController.getStatusBarStateController()
- .addCallback(mNotificationPanelViewController.getStatusBarStateListener());
- mNotificationPanelViewController
- .setHeadsUpAppearanceController(mock(HeadsUpAppearanceController.class));
- verify(mNotificationStackScrollLayoutController)
- .setOnEmptySpaceClickListener(mEmptySpaceClickListenerCaptor.capture());
- verify(mKeyguardStatusViewController).displayClock(LARGE, /* animate */ true);
- reset(mKeyguardStatusViewController);
-
- when(mNotificationPanelViewControllerLazy.get())
- .thenReturn(mNotificationPanelViewController);
- mQuickSettingsController = new QuickSettingsController(
- mNotificationPanelViewControllerLazy,
- mView,
- mQsFrameTranslateController,
- mShadeTransitionController,
- expansionHandler,
- mNotificationRemoteInputManager,
- mShadeExpansionStateManager,
- mStatusBarKeyguardViewManager,
- mNotificationStackScrollLayoutController,
- mLockscreenShadeTransitionController,
- mNotificationShadeDepthController,
- mLargeScreenShadeHeaderController,
- mStatusBarTouchableRegionManager,
- mKeyguardStateController,
- mKeyguardBypassController,
- mUpdateMonitor,
- mScrimController,
- mMediaDataManager,
- mMediaHierarchyManager,
- mAmbientState,
- mRecordingController,
- mFalsingManager,
- new FalsingCollectorFake(),
- mAccessibilityManager,
- mLockscreenGestureLogger,
- mMetricsLogger,
- mFeatureFlags,
- mInteractionJankMonitor,
- mShadeLog
- );
+ /**
+ * When the Back gesture starts (progress 0%), the scrim will stay at 100% scale (1.0f).
+ */
+ @Test
+ public void testBackGesture_min_scrimAtMaxScale() {
+ mNotificationPanelViewController.onBackProgressed(0.0f);
+ verify(mScrimController).applyBackScaling(1.0f);
}
- @After
- public void tearDown() {
- mNotificationPanelViewController.cancelHeightAnimator();
- mMainHandler.removeCallbacksAndMessages(null);
+ /**
+ * When the Back gesture is at max (progress 100%), the scrim will be scaled to its minimum.
+ */
+ @Test
+ public void testBackGesture_max_scrimAtMinScale() {
+ mNotificationPanelViewController.onBackProgressed(1.0f);
+ verify(mScrimController).applyBackScaling(
+ NotificationPanelViewController.SHADE_BACK_ANIM_MIN_SCALE);
}
@Test
@@ -671,23 +149,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
.isNotEqualTo(-1);
}
- private void setBottomPadding(int stackBottom, int lockIconPadding, int indicationPadding,
- int ambientPadding) {
-
- when(mNotificationStackScrollLayoutController.getTop()).thenReturn(0);
- when(mNotificationStackScrollLayoutController.getHeight()).thenReturn(stackBottom);
- when(mNotificationStackScrollLayoutController.getBottom()).thenReturn(stackBottom);
- when(mLockIconViewController.getTop()).thenReturn((float) (stackBottom - lockIconPadding));
-
- when(mResources.getDimensionPixelSize(R.dimen.keyguard_indication_bottom_padding))
- .thenReturn(indicationPadding);
- mNotificationPanelViewController.loadDimens();
-
- mNotificationPanelViewController.setAmbientIndicationTop(
- /* ambientIndicationTop= */ stackBottom - ambientPadding,
- /* ambientTextVisible= */ true);
- }
-
@Test
@Ignore("b/261472011 - Test appears inconsistent across environments")
public void getVerticalSpaceForLockscreenNotifications_useLockIconBottomPadding_returnsSpaceAvailable() {
@@ -992,68 +453,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
}
@Test
- public void testDisableUserSwitcherAfterEnabling_returnsViewStubToTheViewHierarchy() {
- givenViewAttached();
- when(mResources.getBoolean(
- com.android.internal.R.bool.config_keyguardUserSwitcher)).thenReturn(true);
- updateMultiUserSetting(true);
- clearInvocations(mView);
-
- updateMultiUserSetting(false);
-
- ArgumentCaptor<View> captor = ArgumentCaptor.forClass(View.class);
- verify(mView, atLeastOnce()).addView(captor.capture(), anyInt());
- final View userSwitcherStub = CollectionUtils.find(captor.getAllValues(),
- view -> view.getId() == R.id.keyguard_user_switcher_stub);
- assertThat(userSwitcherStub).isNotNull();
- assertThat(userSwitcherStub).isInstanceOf(ViewStub.class);
- }
-
- @Test
- public void testChangeSmallestScreenWidthAndUserSwitchEnabled_inflatesUserSwitchView() {
- givenViewAttached();
- when(mView.findViewById(R.id.keyguard_user_switcher_view)).thenReturn(null);
- updateSmallestScreenWidth(300);
- when(mResources.getBoolean(
- com.android.internal.R.bool.config_keyguardUserSwitcher)).thenReturn(true);
- when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
- when(mUserManager.isUserSwitcherEnabled(false)).thenReturn(true);
-
- updateSmallestScreenWidth(800);
-
- verify(mUserSwitcherStubView).inflate();
- }
-
- @Test
- public void testFinishInflate_userSwitcherDisabled_doNotInflateUserSwitchView_initClock() {
- givenViewAttached();
- when(mResources.getBoolean(
- com.android.internal.R.bool.config_keyguardUserSwitcher)).thenReturn(true);
- when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
- when(mUserManager.isUserSwitcherEnabled(false /* showEvenIfNotActionable */))
- .thenReturn(false);
-
- mNotificationPanelViewController.onFinishInflate();
-
- verify(mUserSwitcherStubView, never()).inflate();
- verify(mKeyguardStatusViewController, times(3)).displayClock(LARGE, /* animate */ true);
- }
-
- @Test
- public void testReInflateViews_userSwitcherDisabled_doNotInflateUserSwitchView() {
- givenViewAttached();
- when(mResources.getBoolean(
- com.android.internal.R.bool.config_keyguardUserSwitcher)).thenReturn(true);
- when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
- when(mUserManager.isUserSwitcherEnabled(false /* showEvenIfNotActionable */))
- .thenReturn(false);
-
- mNotificationPanelViewController.reInflateViews();
-
- verify(mUserSwitcherStubView, never()).inflate();
- }
-
- @Test
public void testCanCollapsePanelOnTouch_trueForKeyGuard() {
mStatusBarStateController.setState(KEYGUARD);
@@ -1129,26 +528,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
}
@Test
- public void testDoubleTapRequired_Keyguard() {
- FalsingManager.FalsingTapListener listener = getFalsingTapListener();
- mStatusBarStateController.setState(KEYGUARD);
-
- listener.onAdditionalTapRequired();
-
- verify(mKeyguardIndicationController).showTransientIndication(anyInt());
- }
-
- @Test
- public void testDoubleTapRequired_ShadeLocked() {
- FalsingManager.FalsingTapListener listener = getFalsingTapListener();
- mStatusBarStateController.setState(SHADE_LOCKED);
-
- listener.onAdditionalTapRequired();
-
- verify(mTapAgainViewController).show();
- }
-
- @Test
public void testRotatingToSplitShadeWithQsExpanded_transitionsToShadeLocked() {
mStatusBarStateController.setState(KEYGUARD);
when(mQsController.getExpanded()).thenReturn(true);
@@ -1423,19 +802,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
}
@Test
- public void testOnAttachRefreshStatusBarState() {
- mStatusBarStateController.setState(KEYGUARD);
- when(mKeyguardStateController.isKeyguardFadingAway()).thenReturn(false);
- for (View.OnAttachStateChangeListener listener : mOnAttachStateChangeListeners) {
- listener.onViewAttachedToWindow(mView);
- }
- verify(mKeyguardStatusViewController).setKeyguardStatusViewVisibility(
- KEYGUARD/*statusBarState*/,
- false/*keyguardFadingAway*/,
- false/*goingToFullShade*/, SHADE/*oldStatusBarState*/);
- }
-
- @Test
public void getMaxPanelTransitionDistance_expanding_inSplitShade_returnsSplitShadeFullTransitionDistance() {
enableSplitShade(true);
mNotificationPanelViewController.expandWithQs();
@@ -1635,98 +1001,4 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
mStatusBarStateController.setState(SHADE_LOCKED);
assertThat(mNotificationPanelViewController.isShadeFullyOpen()).isTrue();
}
-
- private static MotionEvent createMotionEvent(int x, int y, int action) {
- return MotionEvent.obtain(
- /* downTime= */ 0, /* eventTime= */ 0, action, x, y, /* metaState= */ 0);
- }
-
- private void triggerPositionClockAndNotifications() {
- mNotificationPanelViewController.onQsSetExpansionHeightCalled(false);
- }
-
- private FalsingManager.FalsingTapListener getFalsingTapListener() {
- for (View.OnAttachStateChangeListener listener : mOnAttachStateChangeListeners) {
- listener.onViewAttachedToWindow(mView);
- }
- assertThat(mFalsingManager.getTapListeners().size()).isEqualTo(1);
- return mFalsingManager.getTapListeners().get(0);
- }
-
- private void givenViewAttached() {
- for (View.OnAttachStateChangeListener listener : mOnAttachStateChangeListeners) {
- listener.onViewAttachedToWindow(mView);
- }
- }
-
- private ConstraintSet.Layout getConstraintSetLayout(@IdRes int id) {
- ConstraintSet constraintSet = new ConstraintSet();
- constraintSet.clone(mNotificationContainerParent);
- return constraintSet.getConstraint(id).layout;
- }
-
- private void enableSplitShade(boolean enabled) {
- when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(enabled);
- mNotificationPanelViewController.updateResources();
- }
-
- private void updateMultiUserSetting(boolean enabled) {
- when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
- when(mUserManager.isUserSwitcherEnabled(false)).thenReturn(enabled);
- final ArgumentCaptor<ContentObserver> observerCaptor =
- ArgumentCaptor.forClass(ContentObserver.class);
- verify(mContentResolver)
- .registerContentObserver(any(), anyBoolean(), observerCaptor.capture());
- observerCaptor.getValue().onChange(/* selfChange */ false);
- }
-
- private void updateSmallestScreenWidth(int smallestScreenWidthDp) {
- Configuration configuration = new Configuration();
- configuration.smallestScreenWidthDp = smallestScreenWidthDp;
- mConfigurationController.onConfigurationChanged(configuration);
- }
-
- private void onTouchEvent(MotionEvent ev) {
- mTouchHandler.onTouch(mView, ev);
- }
-
- private void setDozing(boolean dozing, boolean dozingAlwaysOn) {
- when(mDozeParameters.getAlwaysOn()).thenReturn(dozingAlwaysOn);
- mNotificationPanelViewController.setDozing(
- /* dozing= */ dozing,
- /* animate= */ false
- );
- }
-
- private void assertKeyguardStatusViewCentered() {
- mNotificationPanelViewController.updateResources();
- assertThat(getConstraintSetLayout(R.id.keyguard_status_view).endToEnd).isAnyOf(
- ConstraintSet.PARENT_ID, ConstraintSet.UNSET);
- }
-
- private void assertKeyguardStatusViewNotCentered() {
- mNotificationPanelViewController.updateResources();
- assertThat(getConstraintSetLayout(R.id.keyguard_status_view).endToEnd).isEqualTo(
- R.id.qs_edge_guideline);
- }
-
- private void setIsFullWidth(boolean fullWidth) {
- float nsslWidth = fullWidth ? PANEL_WIDTH : PANEL_WIDTH / 2f;
- when(mNotificationStackScrollLayoutController.getWidth()).thenReturn(nsslWidth);
- triggerLayoutChange();
- }
-
- private void triggerLayoutChange() {
- mLayoutChangeListener.onLayoutChange(
- mView,
- /* left= */ 0,
- /* top= */ 0,
- /* right= */ 0,
- /* bottom= */ 0,
- /* oldLeft= */ 0,
- /* oldTop= */ 0,
- /* oldRight= */ 0,
- /* oldBottom= */ 0
- );
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerWithCoroutinesTest.kt
new file mode 100644
index 000000000000..0c046e93ee20
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerWithCoroutinesTest.kt
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2023 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.shade
+
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.view.View
+import android.view.ViewStub
+import androidx.test.filters.SmallTest
+import com.android.internal.util.CollectionUtils
+import com.android.keyguard.KeyguardClockSwitch.LARGE
+import com.android.systemui.R
+import com.android.systemui.statusbar.StatusBarState.KEYGUARD
+import com.android.systemui.statusbar.StatusBarState.SHADE
+import com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.cancelChildren
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.advanceUntilIdle
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Captor
+import org.mockito.Mockito.atLeastOnce
+import org.mockito.Mockito.clearInvocations
+import org.mockito.Mockito.never
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+@SmallTest
+class NotificationPanelViewControllerWithCoroutinesTest :
+ NotificationPanelViewControllerBaseTest() {
+
+ @Captor private lateinit var viewCaptor: ArgumentCaptor<View>
+
+ override fun getMainDispatcher() = Dispatchers.Main.immediate
+
+ @Test
+ fun testDisableUserSwitcherAfterEnabling_returnsViewStubToTheViewHierarchy() = runTest {
+ launch(Dispatchers.Main.immediate) { givenViewAttached() }
+ advanceUntilIdle()
+
+ whenever(mResources.getBoolean(com.android.internal.R.bool.config_keyguardUserSwitcher))
+ .thenReturn(true)
+ updateMultiUserSetting(true)
+ clearInvocations(mView)
+
+ updateMultiUserSetting(false)
+
+ verify(mView, atLeastOnce()).addView(viewCaptor.capture(), anyInt())
+ val userSwitcherStub =
+ CollectionUtils.find(
+ viewCaptor.getAllValues(),
+ { view -> view.getId() == R.id.keyguard_user_switcher_stub }
+ )
+ assertThat(userSwitcherStub).isNotNull()
+ assertThat(userSwitcherStub).isInstanceOf(ViewStub::class.java)
+ }
+
+ @Test
+ fun testChangeSmallestScreenWidthAndUserSwitchEnabled_inflatesUserSwitchView() = runTest {
+ launch(Dispatchers.Main.immediate) { givenViewAttached() }
+ advanceUntilIdle()
+
+ whenever(mView.findViewById<View>(R.id.keyguard_user_switcher_view)).thenReturn(null)
+ updateSmallestScreenWidth(300)
+ whenever(mResources.getBoolean(com.android.internal.R.bool.config_keyguardUserSwitcher))
+ .thenReturn(true)
+ whenever(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user))
+ .thenReturn(false)
+ whenever(mUserManager.isUserSwitcherEnabled(false)).thenReturn(true)
+
+ updateSmallestScreenWidth(800)
+
+ verify(mUserSwitcherStubView).inflate()
+ }
+
+ @Test
+ fun testFinishInflate_userSwitcherDisabled_doNotInflateUserSwitchView_initClock() = runTest {
+ launch(Dispatchers.Main.immediate) { givenViewAttached() }
+ advanceUntilIdle()
+
+ whenever(mResources.getBoolean(com.android.internal.R.bool.config_keyguardUserSwitcher))
+ .thenReturn(true)
+ whenever(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user))
+ .thenReturn(false)
+ whenever(mUserManager.isUserSwitcherEnabled(false /* showEvenIfNotActionable */))
+ .thenReturn(false)
+
+ mNotificationPanelViewController.onFinishInflate()
+
+ verify(mUserSwitcherStubView, never()).inflate()
+ verify(mKeyguardStatusViewController, times(3)).displayClock(LARGE, /* animate */ true)
+
+ coroutineContext.cancelChildren()
+ }
+
+ @Test
+ fun testReInflateViews_userSwitcherDisabled_doNotInflateUserSwitchView() = runTest {
+ launch(Dispatchers.Main.immediate) { givenViewAttached() }
+ advanceUntilIdle()
+
+ whenever(mResources.getBoolean(com.android.internal.R.bool.config_keyguardUserSwitcher))
+ .thenReturn(true)
+ whenever(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user))
+ .thenReturn(false)
+ whenever(mUserManager.isUserSwitcherEnabled(false /* showEvenIfNotActionable */))
+ .thenReturn(false)
+
+ mNotificationPanelViewController.reInflateViews()
+
+ verify(mUserSwitcherStubView, never()).inflate()
+
+ coroutineContext.cancelChildren()
+ }
+
+ @Test
+ fun testDoubleTapRequired_Keyguard() = runTest {
+ launch(Dispatchers.Main.immediate) {
+ val listener = getFalsingTapListener()
+ mStatusBarStateController.setState(KEYGUARD)
+
+ listener.onAdditionalTapRequired()
+
+ verify(mKeyguardIndicationController).showTransientIndication(anyInt())
+ }
+ advanceUntilIdle()
+ }
+
+ @Test
+ fun testDoubleTapRequired_ShadeLocked() = runTest {
+ launch(Dispatchers.Main.immediate) {
+ val listener = getFalsingTapListener()
+ mStatusBarStateController.setState(SHADE_LOCKED)
+
+ listener.onAdditionalTapRequired()
+
+ verify(mTapAgainViewController).show()
+ }
+ advanceUntilIdle()
+ }
+
+ @Test
+ fun testOnAttachRefreshStatusBarState() = runTest {
+ launch(Dispatchers.Main.immediate) {
+ mStatusBarStateController.setState(KEYGUARD)
+ whenever(mKeyguardStateController.isKeyguardFadingAway()).thenReturn(false)
+ mOnAttachStateChangeListeners.forEach { it.onViewAttachedToWindow(mView) }
+ verify(mKeyguardStatusViewController)
+ .setKeyguardStatusViewVisibility(
+ KEYGUARD /*statusBarState*/,
+ false /*keyguardFadingAway*/,
+ false /*goingToFullShade*/,
+ SHADE /*oldStatusBarState*/
+ )
+ }
+ advanceUntilIdle()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationQSContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationQSContainerControllerTest.kt
index c915502ad42e..dfb1bce20ff8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationQSContainerControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationQSContainerControllerTest.kt
@@ -12,7 +12,6 @@ import androidx.constraintlayout.widget.ConstraintSet
import androidx.test.filters.SmallTest
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
-import com.android.systemui.flags.FeatureFlags
import com.android.systemui.fragments.FragmentHostManager
import com.android.systemui.fragments.FragmentService
import com.android.systemui.navigationbar.NavigationModeController
@@ -40,8 +39,8 @@ import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.reset
import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when` as whenever
import org.mockito.MockitoAnnotations
+import org.mockito.Mockito.`when` as whenever
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -68,12 +67,10 @@ class NotificationQSContainerControllerTest : SysuiTestCase() {
@Mock
private lateinit var notificationsQSContainer: NotificationsQuickSettingsContainer
@Mock
- private lateinit var largeScreenShadeHeaderController: LargeScreenShadeHeaderController
+ private lateinit var mShadeHeaderController: ShadeHeaderController
@Mock
private lateinit var shadeExpansionStateManager: ShadeExpansionStateManager
@Mock
- private lateinit var featureFlags: FeatureFlags
- @Mock
private lateinit var fragmentService: FragmentService
@Mock
private lateinit var fragmentHostManager: FragmentHostManager
@@ -109,9 +106,8 @@ class NotificationQSContainerControllerTest : SysuiTestCase() {
notificationsQSContainer,
navigationModeController,
overviewProxyService,
- largeScreenShadeHeaderController,
+ mShadeHeaderController,
shadeExpansionStateManager,
- featureFlags,
fragmentService,
delayableExecutor
)
@@ -396,9 +392,8 @@ class NotificationQSContainerControllerTest : SysuiTestCase() {
container,
navigationModeController,
overviewProxyService,
- largeScreenShadeHeaderController,
+ mShadeHeaderController,
shadeExpansionStateManager,
- featureFlags,
fragmentService,
delayableExecutor
)
@@ -429,16 +424,16 @@ class NotificationQSContainerControllerTest : SysuiTestCase() {
@Test
fun testStartCustomizingWithDuration() {
controller.setCustomizerShowing(true, 100L)
- verify(largeScreenShadeHeaderController).startCustomizingAnimation(true, 100L)
+ verify(mShadeHeaderController).startCustomizingAnimation(true, 100L)
}
@Test
fun testEndCustomizingWithDuration() {
controller.setCustomizerShowing(true, 0L) // Only tracks changes
- reset(largeScreenShadeHeaderController)
+ reset(mShadeHeaderController)
controller.setCustomizerShowing(false, 100L)
- verify(largeScreenShadeHeaderController).startCustomizingAnimation(false, 100L)
+ verify(mShadeHeaderController).startCustomizingAnimation(false, 100L)
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
index d229a08ad7c4..0a401b09b6cf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
@@ -28,10 +28,10 @@ import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.FalsingCollectorFake
import com.android.systemui.dock.DockManager
-import com.android.systemui.flags.FeatureFlags
import com.android.systemui.keyguard.KeyguardUnlockAnimationController
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
import com.android.systemui.shade.NotificationShadeWindowView.InteractionEventHandler
import com.android.systemui.statusbar.LockscreenShadeTransitionController
@@ -47,6 +47,7 @@ import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
import com.android.systemui.statusbar.window.StatusBarWindowStateController
import com.android.systemui.util.mockito.any
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.flow.emptyFlow
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -81,8 +82,6 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
@Mock
private lateinit var keyguardUnlockAnimationController: KeyguardUnlockAnimationController
@Mock
- private lateinit var featureFlags: FeatureFlags
- @Mock
private lateinit var ambientState: AmbientState
@Mock
private lateinit var keyguardBouncerViewModel: KeyguardBouncerViewModel
@@ -124,6 +123,8 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
.thenReturn(keyguardBouncerComponent)
whenever(keyguardBouncerComponent.securityContainerController)
.thenReturn(keyguardSecurityContainerController)
+ whenever(keyguardTransitionInteractor.lockscreenToDreamingTransition)
+ .thenReturn(emptyFlow<TransitionStep>())
underTest = NotificationShadeWindowViewController(
lockscreenShadeTransitionController,
FalsingCollectorFake(),
@@ -143,7 +144,6 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
notificationInsetsController,
ambientState,
pulsingGestureListener,
- featureFlags,
keyguardBouncerViewModel,
keyguardBouncerComponentFactory,
alternateBouncerInteractor,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java
index 5e9c2199897d..5d719790386a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java
@@ -25,6 +25,8 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
+
import android.os.SystemClock;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -40,7 +42,6 @@ import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.classifier.FalsingCollectorFake;
import com.android.systemui.dock.DockManager;
-import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
@@ -93,7 +94,6 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase {
@Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
@Mock private AmbientState mAmbientState;
@Mock private PulsingGestureListener mPulsingGestureListener;
- @Mock private FeatureFlags mFeatureFlags;
@Mock private KeyguardBouncerViewModel mKeyguardBouncerViewModel;
@Mock private KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;
@Mock private KeyguardBouncerComponent mKeyguardBouncerComponent;
@@ -125,6 +125,9 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase {
when(mDockManager.isDocked()).thenReturn(false);
+ when(mKeyguardTransitionInteractor.getLockscreenToDreamingTransition())
+ .thenReturn(emptyFlow());
+
mController = new NotificationShadeWindowViewController(
mLockscreenShadeTransitionController,
new FalsingCollectorFake(),
@@ -144,7 +147,6 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase {
mNotificationInsetsController,
mAmbientState,
mPulsingGestureListener,
- mFeatureFlags,
mKeyguardBouncerViewModel,
mKeyguardBouncerComponentFactory,
mAlternateBouncerInteractor,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerTest.java
index c2fca6f2120b..e3a3678fd91e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerTest.java
@@ -16,6 +16,13 @@
package com.android.systemui.shade;
+import static android.view.MotionEvent.ACTION_DOWN;
+import static android.view.MotionEvent.ACTION_MOVE;
+import static android.view.MotionEvent.ACTION_POINTER_DOWN;
+import static android.view.MotionEvent.ACTION_UP;
+import static android.view.MotionEvent.BUTTON_SECONDARY;
+import static android.view.MotionEvent.BUTTON_STYLUS_PRIMARY;
+
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
import static com.android.systemui.statusbar.StatusBarState.SHADE;
@@ -70,13 +77,11 @@ import com.android.systemui.statusbar.StatusBarStateControllerImpl;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.stack.AmbientState;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
-import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.KeyguardBottomAreaView;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.KeyguardStatusBarView;
import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
-import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager;
@@ -97,6 +102,11 @@ import dagger.Lazy;
public class QuickSettingsControllerTest extends SysuiTestCase {
private static final int SPLIT_SHADE_FULL_TRANSITION_DISTANCE = 400;
+ private static final float QS_FRAME_START_X = 0f;
+ private static final int QS_FRAME_WIDTH = 1000;
+ private static final int QS_FRAME_TOP = 0;
+ private static final int QS_FRAME_BOTTOM = 1000;
+
private QuickSettingsController mQsController;
@@ -119,7 +129,7 @@ public class QuickSettingsControllerTest extends SysuiTestCase {
@Mock private NotificationStackScrollLayoutController mNotificationStackScrollLayoutController;
@Mock private LockscreenShadeTransitionController mLockscreenShadeTransitionController;
@Mock private NotificationShadeDepthController mNotificationShadeDepthController;
- @Mock private LargeScreenShadeHeaderController mLargeScreenShadeHeaderController;
+ @Mock private ShadeHeaderController mShadeHeaderController;
@Mock private StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
@Mock private KeyguardStateController mKeyguardStateController;
@Mock private KeyguardBypassController mKeyguardBypassController;
@@ -139,8 +149,7 @@ public class QuickSettingsControllerTest extends SysuiTestCase {
@Mock private ShadeLogger mShadeLogger;
@Mock private DumpManager mDumpManager;
- @Mock private DozeParameters mDozeParameters;
- @Mock private ScreenOffAnimationController mScreenOffAnimationController;
+
@Mock private HeadsUpManagerPhone mHeadsUpManager;
@Mock private UiEventLogger mUiEventLogger;
@@ -169,6 +178,12 @@ public class QuickSettingsControllerTest extends SysuiTestCase {
when(mPanelView.findViewById(R.id.keyguard_header)).thenReturn(mKeyguardStatusBar);
when(mNotificationStackScrollLayoutController.getHeight()).thenReturn(1000);
when(mPanelView.findViewById(R.id.qs_frame)).thenReturn(mQsFrame);
+ when(mQsFrame.getX()).thenReturn(QS_FRAME_START_X);
+ when(mQsFrame.getWidth()).thenReturn(QS_FRAME_WIDTH);
+ when(mQsHeader.getTop()).thenReturn(QS_FRAME_TOP);
+ when(mQsHeader.getBottom()).thenReturn(QS_FRAME_BOTTOM);
+ when(mPanelView.getY()).thenReturn((float) QS_FRAME_TOP);
+ when(mPanelView.getHeight()).thenReturn(QS_FRAME_BOTTOM);
when(mPanelView.findViewById(R.id.keyguard_status_view))
.thenReturn(mock(KeyguardStatusView.class));
when(mQs.getView()).thenReturn(mPanelView);
@@ -204,7 +219,7 @@ public class QuickSettingsControllerTest extends SysuiTestCase {
mNotificationStackScrollLayoutController,
mLockscreenShadeTransitionController,
mNotificationShadeDepthController,
- mLargeScreenShadeHeaderController,
+ mShadeHeaderController,
mStatusBarTouchableRegionManager,
mKeyguardStateController,
mKeyguardBypassController,
@@ -229,21 +244,10 @@ public class QuickSettingsControllerTest extends SysuiTestCase {
@After
public void tearDown() {
- mNotificationPanelViewController.cancelHeightAnimator();
mMainHandler.removeCallbacksAndMessages(null);
}
@Test
- public void testOnTouchEvent_isConflictingExpansionGestureSet() {
- assertThat(mQsController.isConflictingExpansionGesture()).isFalse();
- mShadeExpansionStateManager.onPanelExpansionChanged(1f, true, false, 0f);
- mQsController.handleTouch(MotionEvent.obtain(0L /* downTime */,
- 0L /* eventTime */, MotionEvent.ACTION_DOWN, 0f /* x */, 0f /* y */,
- 0 /* metaState */), false, false);
- assertThat(mQsController.isConflictingExpansionGesture()).isTrue();
- }
-
- @Test
public void testCloseQsSideEffects() {
enableSplitShade(true);
mQsController.setExpandImmediate(true);
@@ -259,18 +263,18 @@ public class QuickSettingsControllerTest extends SysuiTestCase {
mStatusBarStateController.setState(SHADE);
when(mResources.getBoolean(R.bool.config_use_large_screen_shade_header)).thenReturn(true);
mQsController.updateResources();
- verify(mLargeScreenShadeHeaderController).setLargeScreenActive(true);
+ verify(mShadeHeaderController).setLargeScreenActive(true);
when(mResources.getBoolean(R.bool.config_use_large_screen_shade_header)).thenReturn(false);
mQsController.updateResources();
- verify(mLargeScreenShadeHeaderController).setLargeScreenActive(false);
+ verify(mShadeHeaderController).setLargeScreenActive(false);
}
@Test
public void testPanelStaysOpenWhenClosingQs() {
mShadeExpansionStateManager.onPanelExpansionChanged(/* fraction= */ 1,
/* expanded= */ true, /* tracking= */ false, /* dragDownPxAmount= */ 0);
- mNotificationPanelViewController.setExpandedFraction(1f);
+ mQsController.setShadeExpandedHeight(1);
float shadeExpandedHeight = mQsController.getShadeExpandedHeight();
mQsController.animateCloseQs(false);
@@ -281,16 +285,12 @@ public class QuickSettingsControllerTest extends SysuiTestCase {
@Test
public void interceptTouchEvent_withinQs_shadeExpanded_startsQsTracking() {
mQsController.setQs(mQs);
- when(mQsFrame.getX()).thenReturn(0f);
- when(mQsFrame.getWidth()).thenReturn(1000);
- when(mQsHeader.getTop()).thenReturn(0);
- when(mQsHeader.getBottom()).thenReturn(1000);
mQsController.setShadeExpandedHeight(1f);
mQsController.onIntercept(
- createMotionEvent(0, 0, MotionEvent.ACTION_DOWN));
+ createMotionEvent(0, 0, ACTION_DOWN));
mQsController.onIntercept(
- createMotionEvent(0, 500, MotionEvent.ACTION_MOVE));
+ createMotionEvent(0, 500, ACTION_MOVE));
assertThat(mQsController.isTracking()).isTrue();
}
@@ -299,21 +299,124 @@ public class QuickSettingsControllerTest extends SysuiTestCase {
public void interceptTouchEvent_withinQs_shadeExpanded_inSplitShade_doesNotStartQsTracking() {
enableSplitShade(true);
mQsController.setQs(mQs);
- when(mQsFrame.getX()).thenReturn(0f);
- when(mQsFrame.getWidth()).thenReturn(1000);
- when(mQsHeader.getTop()).thenReturn(0);
- when(mQsHeader.getBottom()).thenReturn(1000);
mQsController.setShadeExpandedHeight(1f);
mQsController.onIntercept(
- createMotionEvent(0, 0, MotionEvent.ACTION_DOWN));
+ createMotionEvent(0, 0, ACTION_DOWN));
mQsController.onIntercept(
- createMotionEvent(0, 500, MotionEvent.ACTION_MOVE));
+ createMotionEvent(0, 500, ACTION_MOVE));
+
+ assertThat(mQsController.isTracking()).isFalse();
+ }
+
+ @Test
+ public void interceptTouch_downBetweenFullyCollapsedAndExpanded() {
+ mQsController.setQs(mQs);
+ when(mQs.getDesiredHeight()).thenReturn(QS_FRAME_BOTTOM);
+ mQsController.onHeightChanged();
+ mQsController.setExpansionHeight(QS_FRAME_BOTTOM / 2f);
+
+ assertThat(mQsController.onIntercept(
+ createMotionEvent(0, QS_FRAME_BOTTOM / 2, ACTION_DOWN))).isTrue();
+ }
+
+ @Test
+ public void onTouch_moveActionSetsCorrectExpansionHeight() {
+ mQsController.setQs(mQs);
+ when(mQs.getDesiredHeight()).thenReturn(QS_FRAME_BOTTOM);
+ mQsController.onHeightChanged();
+ mQsController.setExpansionHeight(QS_FRAME_BOTTOM / 2f);
+ mQsController.handleTouch(
+ createMotionEvent(0, QS_FRAME_BOTTOM / 4, ACTION_DOWN), false, false);
+ assertThat(mQsController.isTracking()).isTrue();
+ mQsController.handleTouch(
+ createMotionEvent(0, QS_FRAME_BOTTOM / 4 + 1, ACTION_MOVE), false, false);
+ assertThat(mQsController.getExpansionHeight()).isEqualTo(QS_FRAME_BOTTOM / 2 + 1);
+ }
+
+ @Test
+ public void handleTouch_downActionInQsArea() {
+ mQsController.setQs(mQs);
+ mQsController.setBarState(SHADE);
+ mQsController.onPanelExpansionChanged(
+ new ShadeExpansionChangeEvent(
+ 0.5f,
+ true,
+ true,
+ 0
+ ));
+ MotionEvent event =
+ createMotionEvent(QS_FRAME_WIDTH / 2, QS_FRAME_BOTTOM / 2, ACTION_DOWN);
+ mQsController.handleTouch(event, false, false);
+
+ assertThat(mQsController.isTracking()).isTrue();
+ assertThat(mQsController.getInitialTouchY()).isEqualTo(QS_FRAME_BOTTOM / 2);
+ }
+
+ @Test
+ public void handleTouch_qsTouchedWhileCollapsingDisablesTracking() {
+ mQsController.handleTouch(
+ createMotionEvent(0, QS_FRAME_BOTTOM, ACTION_DOWN), false, false);
+ mQsController.setLastShadeFlingWasExpanding(false);
+ mQsController.handleTouch(
+ createMotionEvent(0, QS_FRAME_BOTTOM / 2, ACTION_MOVE), false, true);
+ MotionEvent secondTouch = createMotionEvent(0, QS_FRAME_TOP, ACTION_DOWN);
+ mQsController.handleTouch(secondTouch, false, true);
assertThat(mQsController.isTracking()).isFalse();
}
@Test
+ public void handleTouch_qsTouchedWhileExpanding() {
+ mQsController.setQs(mQs);
+ mQsController.handleTouch(
+ createMotionEvent(100, 100, ACTION_DOWN), false, false);
+ mQsController.handleTouch(
+ createMotionEvent(0, QS_FRAME_BOTTOM / 2, ACTION_MOVE), false, false);
+ mQsController.setLastShadeFlingWasExpanding(true);
+ mQsController.handleTouch(
+ createMotionEvent(0, QS_FRAME_TOP, ACTION_DOWN), false, false);
+ assertThat(mQsController.isTracking()).isTrue();
+ }
+
+ @Test
+ public void handleTouch_isConflictingExpansionGestureSet() {
+ assertThat(mQsController.isConflictingExpansionGesture()).isFalse();
+ mShadeExpansionStateManager.onPanelExpansionChanged(1f, true, false, 0f);
+ mQsController.handleTouch(MotionEvent.obtain(0L /* downTime */,
+ 0L /* eventTime */, ACTION_DOWN, 0f /* x */, 0f /* y */,
+ 0 /* metaState */), false, false);
+ assertThat(mQsController.isConflictingExpansionGesture()).isTrue();
+ }
+
+ @Test
+ public void handleTouch_isConflictingExpansionGestureSet_cancel() {
+ mShadeExpansionStateManager.onPanelExpansionChanged(1f, true, false, 0f);
+ mQsController.handleTouch(createMotionEvent(0, 0, ACTION_DOWN), false, false);
+ assertThat(mQsController.isConflictingExpansionGesture()).isTrue();
+ mQsController.handleTouch(createMotionEvent(0, 0, ACTION_UP), true, true);
+ assertThat(mQsController.isConflictingExpansionGesture()).isFalse();
+ }
+
+ @Test
+ public void handleTouch_twoFingerExpandPossibleConditions() {
+ assertThat(mQsController.isTwoFingerExpandPossible()).isFalse();
+ mQsController.handleTouch(createMotionEvent(0, 0, ACTION_DOWN), true, false);
+ assertThat(mQsController.isTwoFingerExpandPossible()).isTrue();
+ }
+
+ @Test
+ public void handleTouch_twoFingerDrag() {
+ mQsController.setQs(mQs);
+ mQsController.setStatusBarMinHeight(1);
+ mQsController.setTwoFingerExpandPossible(true);
+ mQsController.handleTouch(
+ createMultitouchMotionEvent(ACTION_POINTER_DOWN), false, false);
+ assertThat(mQsController.isExpandImmediate()).isTrue();
+ verify(mQs).setListening(true);
+ }
+
+ @Test
public void onQsFragmentAttached_fullWidth_setsFullWidthTrueOnQS() {
setIsFullWidth(true);
mFragmentListener.onFragmentViewCreated(QS.TAG, mQSFragment);
@@ -330,19 +433,6 @@ public class QuickSettingsControllerTest extends SysuiTestCase {
}
@Test
- public void getMaxPanelTransitionDistance_inSplitShade_withHeadsUp_returnsBiggerValue() {
- enableSplitShade(true);
- mNotificationPanelViewController.expandWithQs();
- when(mHeadsUpManager.isTrackingHeadsUp()).thenReturn(true);
-
- mNotificationPanelViewController.setHeadsUpDraggingStartingHeight(
- SPLIT_SHADE_FULL_TRANSITION_DISTANCE);
-
- assertThat(mQsController.calculatePanelHeightExpanded(0))
- .isGreaterThan(SPLIT_SHADE_FULL_TRANSITION_DISTANCE);
- }
-
- @Test
public void setQsExpansion_lockscreenShadeTransitionInProgress_usesLockscreenSquishiness() {
float squishinessFraction = 0.456f;
mQsController.setQs(mQs);
@@ -379,6 +469,21 @@ public class QuickSettingsControllerTest extends SysuiTestCase {
}
@Test
+ public void updateExpansion_expandImmediateOrAlreadyExpanded_usesFullSquishiness() {
+ mQsController.setQs(mQs);
+ when(mQs.getDesiredHeight()).thenReturn(100);
+ mQsController.onHeightChanged();
+
+ mQsController.setExpandImmediate(true);
+ mQsController.setExpanded(false);
+ mQsController.updateExpansion();
+ mQsController.setExpandImmediate(false);
+ mQsController.setExpanded(true);
+ mQsController.updateExpansion();
+ verify(mQs, times(2)).setQsExpansion(0, 0, 0, 1);
+ }
+
+ @Test
public void shadeExpanded_onKeyguard() {
mStatusBarStateController.setState(KEYGUARD);
// set maxQsExpansion in NPVC
@@ -393,9 +498,52 @@ public class QuickSettingsControllerTest extends SysuiTestCase {
assertThat(mQsController.computeExpansionFraction()).isEqualTo(1f);
}
+ @Test
+ public void handleTouch_splitShadeAndtouchXOutsideQs() {
+ enableSplitShade(true);
+
+ assertThat(mQsController.handleTouch(createMotionEvent(
+ QS_FRAME_WIDTH + 1, QS_FRAME_BOTTOM - 1, ACTION_DOWN),
+ false, false)).isFalse();
+ }
+
+ @Test
+ public void isOpenQsEvent_twoFingerDrag() {
+ assertThat(mQsController.isOpenQsEvent(
+ createMultitouchMotionEvent(ACTION_POINTER_DOWN))).isTrue();
+ }
+
+ @Test
+ public void isOpenQsEvent_stylusButtonClickDrag() {
+ MotionEvent event = createMotionEvent(0, 0, ACTION_DOWN);
+ event.setButtonState(BUTTON_STYLUS_PRIMARY);
+
+ assertThat(mQsController.isOpenQsEvent(event)).isTrue();
+ }
+
+ @Test
+ public void isOpenQsEvent_mouseButtonClickDrag() {
+ MotionEvent event = createMotionEvent(0, 0, ACTION_DOWN);
+ event.setButtonState(BUTTON_SECONDARY);
+
+ assertThat(mQsController.isOpenQsEvent(event)).isTrue();
+ }
+
private static MotionEvent createMotionEvent(int x, int y, int action) {
- return MotionEvent.obtain(
- /* downTime= */ 0, /* eventTime= */ 0, action, x, y, /* metaState= */ 0);
+ return MotionEvent.obtain(0, 0, action, x, y, 0);
+ }
+
+ // Creates an empty multitouch event for now
+ private static MotionEvent createMultitouchMotionEvent(int action) {
+ return MotionEvent.obtain(0, 0, action, 2,
+ new MotionEvent.PointerProperties[] {
+ new MotionEvent.PointerProperties(),
+ new MotionEvent.PointerProperties()
+ },
+ new MotionEvent.PointerCoords[] {
+ new MotionEvent.PointerCoords(),
+ new MotionEvent.PointerCoords()
+ }, 0, 0, 0, 0, 0, 0, 0, 0);
}
private void enableSplitShade(boolean enabled) {
@@ -412,4 +560,6 @@ public class QuickSettingsControllerTest extends SysuiTestCase {
int oldMaxHeight = mQsController.updateHeightsOnShadeLayoutChange();
mQsController.handleShadeLayoutChanged(oldMaxHeight);
}
+
+
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerCombinedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt
index ee5f61c835da..d5308298202d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerCombinedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt
@@ -13,9 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.android.systemui.shade
+import android.animation.Animator
+import android.app.StatusBarManager
import android.content.Context
import android.content.res.Resources
import android.content.res.XmlResourceParser
@@ -39,16 +40,13 @@ import com.android.systemui.battery.BatteryMeterViewController
import com.android.systemui.demomode.DemoMode
import com.android.systemui.demomode.DemoModeController
import com.android.systemui.dump.DumpManager
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
import com.android.systemui.qs.ChipVisibilityListener
import com.android.systemui.qs.HeaderPrivacyIconsController
import com.android.systemui.qs.carrier.QSCarrierGroup
import com.android.systemui.qs.carrier.QSCarrierGroupController
-import com.android.systemui.shade.LargeScreenShadeHeaderController.Companion.HEADER_TRANSITION_ID
-import com.android.systemui.shade.LargeScreenShadeHeaderController.Companion.LARGE_SCREEN_HEADER_CONSTRAINT
-import com.android.systemui.shade.LargeScreenShadeHeaderController.Companion.QQS_HEADER_CONSTRAINT
-import com.android.systemui.shade.LargeScreenShadeHeaderController.Companion.QS_HEADER_CONSTRAINT
+import com.android.systemui.shade.ShadeHeaderController.Companion.LARGE_SCREEN_HEADER_CONSTRAINT
+import com.android.systemui.shade.ShadeHeaderController.Companion.QQS_HEADER_CONSTRAINT
+import com.android.systemui.shade.ShadeHeaderController.Companion.QS_HEADER_CONSTRAINT
import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
import com.android.systemui.statusbar.phone.StatusBarIconController
import com.android.systemui.statusbar.phone.StatusIconContainer
@@ -68,136 +66,106 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Answers
import org.mockito.ArgumentCaptor
-import org.mockito.ArgumentMatchers
+import org.mockito.ArgumentMatchers.anyFloat
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito
-import org.mockito.Mockito.anyBoolean
-import org.mockito.Mockito.anyFloat
-import org.mockito.Mockito.anyInt
-import org.mockito.Mockito.clearInvocations
-import org.mockito.Mockito.inOrder
-import org.mockito.Mockito.never
+import org.mockito.Mockito.mock
import org.mockito.Mockito.reset
-import org.mockito.Mockito.same
-import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
-import org.mockito.junit.MockitoJUnit
import org.mockito.Mockito.`when` as whenever
+import org.mockito.junit.MockitoJUnit
private val EMPTY_CHANGES = ConstraintsChanges()
-/**
- * Tests for [LargeScreenShadeHeaderController] when [Flags.COMBINED_QS_HEADERS] is `true`.
- *
- * Once that flag is removed, this class will be combined with
- * [LargeScreenShadeHeaderControllerTest].
- */
@SmallTest
@RunWith(AndroidTestingRunner::class)
-class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
-
- @Mock
- private lateinit var statusIcons: StatusIconContainer
- @Mock
- private lateinit var statusBarIconController: StatusBarIconController
- @Mock
- private lateinit var iconManagerFactory: StatusBarIconController.TintedIconManager.Factory
- @Mock
- private lateinit var iconManager: StatusBarIconController.TintedIconManager
- @Mock
- private lateinit var qsCarrierGroupController: QSCarrierGroupController
- @Mock
- private lateinit var qsCarrierGroupControllerBuilder: QSCarrierGroupController.Builder
- @Mock
- private lateinit var featureFlags: FeatureFlags
- @Mock
- private lateinit var clock: Clock
- @Mock
- private lateinit var date: VariableDateView
- @Mock
- private lateinit var carrierGroup: QSCarrierGroup
- @Mock
- private lateinit var batteryMeterView: BatteryMeterView
- @Mock
- private lateinit var batteryMeterViewController: BatteryMeterViewController
- @Mock
- private lateinit var privacyIconsController: HeaderPrivacyIconsController
- @Mock
- private lateinit var insetsProvider: StatusBarContentInsetsProvider
- @Mock
- private lateinit var variableDateViewControllerFactory: VariableDateViewController.Factory
- @Mock
- private lateinit var variableDateViewController: VariableDateViewController
- @Mock
- private lateinit var dumpManager: DumpManager
+class ShadeHeaderControllerTest : SysuiTestCase() {
+
+ @Mock(answer = Answers.RETURNS_MOCKS) private lateinit var view: MotionLayout
+ @Mock private lateinit var statusIcons: StatusIconContainer
+ @Mock private lateinit var statusBarIconController: StatusBarIconController
+ @Mock private lateinit var iconManagerFactory: StatusBarIconController.TintedIconManager.Factory
+ @Mock private lateinit var iconManager: StatusBarIconController.TintedIconManager
+ @Mock private lateinit var qsCarrierGroupController: QSCarrierGroupController
+ @Mock private lateinit var qsCarrierGroupControllerBuilder: QSCarrierGroupController.Builder
+ @Mock private lateinit var clock: Clock
+ @Mock private lateinit var date: VariableDateView
+ @Mock private lateinit var carrierGroup: QSCarrierGroup
+ @Mock private lateinit var batteryMeterView: BatteryMeterView
+ @Mock private lateinit var batteryMeterViewController: BatteryMeterViewController
+ @Mock private lateinit var privacyIconsController: HeaderPrivacyIconsController
+ @Mock private lateinit var insetsProvider: StatusBarContentInsetsProvider
+ @Mock private lateinit var variableDateViewControllerFactory: VariableDateViewController.Factory
+ @Mock private lateinit var variableDateViewController: VariableDateViewController
+ @Mock private lateinit var dumpManager: DumpManager
@Mock
private lateinit var combinedShadeHeadersConstraintManager:
CombinedShadeHeadersConstraintManager
- @Mock
- private lateinit var mockedContext: Context
+ @Mock private lateinit var mockedContext: Context
private lateinit var viewContext: Context
- @Mock(answer = Answers.RETURNS_MOCKS)
- private lateinit var view: MotionLayout
- @Mock
- private lateinit var qqsConstraints: ConstraintSet
- @Mock
- private lateinit var qsConstraints: ConstraintSet
- @Mock
- private lateinit var largeScreenConstraints: ConstraintSet
+ @Mock private lateinit var qqsConstraints: ConstraintSet
+ @Mock private lateinit var qsConstraints: ConstraintSet
+ @Mock private lateinit var largeScreenConstraints: ConstraintSet
+
@Mock private lateinit var demoModeController: DemoModeController
@Mock private lateinit var qsBatteryModeController: QsBatteryModeController
- @JvmField @Rule
- val mockitoRule = MockitoJUnit.rule()
+ @JvmField @Rule val mockitoRule = MockitoJUnit.rule()
var viewVisibility = View.GONE
+ var viewAlpha = 1f
- private lateinit var controller: LargeScreenShadeHeaderController
+ private lateinit var shadeHeaderController: ShadeHeaderController
private lateinit var carrierIconSlots: List<String>
private val configurationController = FakeConfigurationController()
- private lateinit var demoModeControllerCapture: ArgumentCaptor<DemoMode>
+ @Captor private lateinit var demoModeControllerCapture: ArgumentCaptor<DemoMode>
@Before
- fun setUp() {
- demoModeControllerCapture = argumentCaptor<DemoMode>()
+ fun setup() {
whenever<Clock>(view.findViewById(R.id.clock)).thenReturn(clock)
whenever(clock.context).thenReturn(mockedContext)
whenever<TextView>(view.findViewById(R.id.date)).thenReturn(date)
whenever(date.context).thenReturn(mockedContext)
- whenever(variableDateViewControllerFactory.create(any()))
- .thenReturn(variableDateViewController)
whenever<QSCarrierGroup>(view.findViewById(R.id.carrier_group)).thenReturn(carrierGroup)
+
whenever<BatteryMeterView>(view.findViewById(R.id.batteryRemainingIcon))
.thenReturn(batteryMeterView)
whenever<StatusIconContainer>(view.findViewById(R.id.statusIcons)).thenReturn(statusIcons)
- whenever(statusIcons.context).thenReturn(context)
+ viewContext = Mockito.spy(context)
+ whenever(view.context).thenReturn(viewContext)
+ whenever(view.resources).thenReturn(context.resources)
+ whenever(statusIcons.context).thenReturn(context)
whenever(qsCarrierGroupControllerBuilder.setQSCarrierGroup(any()))
.thenReturn(qsCarrierGroupControllerBuilder)
whenever(qsCarrierGroupControllerBuilder.build()).thenReturn(qsCarrierGroupController)
-
- viewContext = spy(context)
- whenever(view.context).thenReturn(viewContext)
- whenever(view.resources).thenReturn(context.resources)
- whenever(view.setVisibility(ArgumentMatchers.anyInt())).then {
+ whenever(view.setVisibility(anyInt())).then {
viewVisibility = it.arguments[0] as Int
null
}
whenever(view.visibility).thenAnswer { _ -> viewVisibility }
- whenever(view.alpha).thenReturn(1f)
- whenever(iconManagerFactory.create(any(), any())).thenReturn(iconManager)
+ whenever(view.setAlpha(anyFloat())).then {
+ viewAlpha = it.arguments[0] as Float
+ null
+ }
+ whenever(view.alpha).thenAnswer { _ -> viewAlpha }
- whenever(featureFlags.isEnabled(Flags.COMBINED_QS_HEADERS)).thenReturn(true)
+ whenever(variableDateViewControllerFactory.create(any()))
+ .thenReturn(variableDateViewController)
+ whenever(iconManagerFactory.create(any(), any())).thenReturn(iconManager)
setUpDefaultInsets()
setUpMotionLayout(view)
- controller = LargeScreenShadeHeaderController(
+ shadeHeaderController =
+ ShadeHeaderController(
view,
statusBarIconController,
iconManagerFactory,
@@ -207,16 +175,171 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
variableDateViewControllerFactory,
batteryMeterViewController,
dumpManager,
- featureFlags,
qsCarrierGroupControllerBuilder,
combinedShadeHeadersConstraintManager,
demoModeController,
qsBatteryModeController,
- )
+ )
whenever(view.isAttachedToWindow).thenReturn(true)
- controller.init()
- carrierIconSlots = listOf(
- context.getString(com.android.internal.R.string.status_bar_mobile))
+ shadeHeaderController.init()
+ carrierIconSlots =
+ listOf(context.getString(com.android.internal.R.string.status_bar_mobile))
+ }
+
+ @Test
+ fun updateListeners_registersWhenVisible() {
+ makeShadeVisible()
+ verify(qsCarrierGroupController).setListening(true)
+ verify(statusBarIconController).addIconGroup(any())
+ }
+
+ @Test
+ fun statusIconsAddedWhenAttached() {
+ verify(statusBarIconController).addIconGroup(any())
+ }
+
+ @Test
+ fun statusIconsRemovedWhenDettached() {
+ shadeHeaderController.simulateViewDetached()
+ verify(statusBarIconController).removeIconGroup(any())
+ }
+
+ @Test
+ fun shadeExpandedFraction_updatesAlpha() {
+ makeShadeVisible()
+ shadeHeaderController.shadeExpandedFraction = 0.5f
+ verify(view).setAlpha(ShadeInterpolation.getContentAlpha(0.5f))
+ }
+
+ @Test
+ fun singleCarrier_enablesCarrierIconsInStatusIcons() {
+ whenever(qsCarrierGroupController.isSingleCarrier).thenReturn(true)
+
+ makeShadeVisible()
+
+ verify(statusIcons).removeIgnoredSlots(carrierIconSlots)
+ }
+
+ @Test
+ fun dualCarrier_disablesCarrierIconsInStatusIcons() {
+ whenever(qsCarrierGroupController.isSingleCarrier).thenReturn(false)
+
+ makeShadeVisible()
+
+ verify(statusIcons).addIgnoredSlots(carrierIconSlots)
+ }
+
+ @Test
+ fun disableQS_notDisabled_visible() {
+ makeShadeVisible()
+ shadeHeaderController.disable(0, 0, false)
+
+ assertThat(viewVisibility).isEqualTo(View.VISIBLE)
+ }
+
+ @Test
+ fun disableQS_disabled_gone() {
+ makeShadeVisible()
+ shadeHeaderController.disable(0, StatusBarManager.DISABLE2_QUICK_SETTINGS, false)
+
+ assertThat(viewVisibility).isEqualTo(View.GONE)
+ }
+
+ private fun makeShadeVisible() {
+ shadeHeaderController.largeScreenActive = true
+ shadeHeaderController.qsVisible = true
+ }
+
+ @Test
+ fun updateConfig_changesFontStyle() {
+ configurationController.notifyDensityOrFontScaleChanged()
+
+ verify(clock).setTextAppearance(R.style.TextAppearance_QS_Status)
+ verify(date).setTextAppearance(R.style.TextAppearance_QS_Status)
+ verify(carrierGroup).updateTextAppearance(R.style.TextAppearance_QS_Status_Carriers)
+ }
+
+ @Test
+ fun animateOutOnStartCustomizing() {
+ val animator = mock(ViewPropertyAnimator::class.java, Answers.RETURNS_SELF)
+ val duration = 1000L
+ whenever(view.animate()).thenReturn(animator)
+
+ shadeHeaderController.startCustomizingAnimation(show = true, duration)
+
+ verify(animator).setDuration(duration)
+ verify(animator).alpha(0f)
+ verify(animator).setInterpolator(Interpolators.ALPHA_OUT)
+ verify(animator).start()
+ }
+
+ @Test
+ fun animateInOnEndCustomizing() {
+ val animator = mock(ViewPropertyAnimator::class.java, Answers.RETURNS_SELF)
+ val duration = 1000L
+ whenever(view.animate()).thenReturn(animator)
+
+ shadeHeaderController.startCustomizingAnimation(show = false, duration)
+
+ verify(animator).setDuration(duration)
+ verify(animator).alpha(1f)
+ verify(animator).setInterpolator(Interpolators.ALPHA_IN)
+ verify(animator).start()
+ }
+
+ @Test
+ fun customizerAnimatorChangesViewVisibility() {
+ makeShadeVisible()
+
+ val animator = mock(ViewPropertyAnimator::class.java, Answers.RETURNS_SELF)
+ val duration = 1000L
+ whenever(view.animate()).thenReturn(animator)
+ val listenerCaptor = argumentCaptor<Animator.AnimatorListener>()
+
+ shadeHeaderController.startCustomizingAnimation(show = true, duration)
+ verify(animator).setListener(capture(listenerCaptor))
+ // Start and end the animation
+ listenerCaptor.value.onAnimationStart(mock())
+ listenerCaptor.value.onAnimationEnd(mock())
+ assertThat(viewVisibility).isEqualTo(View.INVISIBLE)
+
+ reset(animator)
+ shadeHeaderController.startCustomizingAnimation(show = false, duration)
+ verify(animator).setListener(capture(listenerCaptor))
+ // Start and end the animation
+ listenerCaptor.value.onAnimationStart(mock())
+ listenerCaptor.value.onAnimationEnd(mock())
+ assertThat(viewVisibility).isEqualTo(View.VISIBLE)
+ }
+
+ @Test
+ fun animatorListenersClearedAtEnd() {
+ val animator = mock(ViewPropertyAnimator::class.java, Answers.RETURNS_SELF)
+ whenever(view.animate()).thenReturn(animator)
+
+ shadeHeaderController.startCustomizingAnimation(show = true, 0L)
+ val listenerCaptor = argumentCaptor<Animator.AnimatorListener>()
+ verify(animator).setListener(capture(listenerCaptor))
+
+ listenerCaptor.value.onAnimationEnd(mock())
+ verify(animator).setListener(null)
+ }
+
+ @Test
+ fun demoMode_attachDemoMode() {
+ val cb = argumentCaptor<DemoMode>()
+ verify(demoModeController).addCallback(capture(cb))
+ cb.value.onDemoModeStarted()
+ verify(clock).onDemoModeStarted()
+ }
+
+ @Test
+ fun demoMode_detachDemoMode() {
+ shadeHeaderController.simulateViewDetached()
+ val cb = argumentCaptor<DemoMode>()
+ verify(demoModeController).removeCallback(capture(cb))
+ cb.value.onDemoModeFinished()
+ verify(clock).onDemoModeFinished()
}
@Test
@@ -226,23 +349,21 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
verify(batteryMeterViewController).init()
verify(batteryMeterViewController).ignoreTunerUpdates()
- val inOrder = inOrder(qsCarrierGroupControllerBuilder)
+ val inOrder = Mockito.inOrder(qsCarrierGroupControllerBuilder)
inOrder.verify(qsCarrierGroupControllerBuilder).setQSCarrierGroup(carrierGroup)
inOrder.verify(qsCarrierGroupControllerBuilder).build()
}
@Test
fun `battery mode controller called when qsExpandedFraction changes`() {
- whenever(qsBatteryModeController.getBatteryMode(same(null), eq(0f)))
- .thenReturn(BatteryMeterView.MODE_ON)
- whenever(qsBatteryModeController.getBatteryMode(same(null), eq(1f)))
- .thenReturn(BatteryMeterView.MODE_ESTIMATE)
- controller.qsVisible = true
+ whenever(qsBatteryModeController.getBatteryMode(Mockito.same(null), eq(0f)))
+ .thenReturn(BatteryMeterView.MODE_ON)
+ whenever(qsBatteryModeController.getBatteryMode(Mockito.same(null), eq(1f)))
+ .thenReturn(BatteryMeterView.MODE_ESTIMATE)
+ shadeHeaderController.qsVisible = true
val times = 10
- repeat(times) {
- controller.qsExpandedFraction = it / (times - 1).toFloat()
- }
+ repeat(times) { shadeHeaderController.qsExpandedFraction = it / (times - 1).toFloat() }
verify(batteryMeterView).setPercentShowMode(BatteryMeterView.MODE_ON)
verify(batteryMeterView).setPercentShowMode(BatteryMeterView.MODE_ESTIMATE)
@@ -277,89 +398,89 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
@Test
fun testShadeExpanded_true() {
// When shade is expanded, view should be visible regardless of largeScreenActive
- controller.largeScreenActive = false
- controller.qsVisible = true
+ shadeHeaderController.largeScreenActive = false
+ shadeHeaderController.qsVisible = true
assertThat(viewVisibility).isEqualTo(View.VISIBLE)
- controller.largeScreenActive = true
+ shadeHeaderController.largeScreenActive = true
assertThat(viewVisibility).isEqualTo(View.VISIBLE)
}
@Test
fun testShadeExpanded_false() {
// When shade is not expanded, view should be invisible regardless of largeScreenActive
- controller.largeScreenActive = false
- controller.qsVisible = false
+ shadeHeaderController.largeScreenActive = false
+ shadeHeaderController.qsVisible = false
assertThat(viewVisibility).isEqualTo(View.INVISIBLE)
- controller.largeScreenActive = true
+ shadeHeaderController.largeScreenActive = true
assertThat(viewVisibility).isEqualTo(View.INVISIBLE)
}
@Test
fun testLargeScreenActive_false() {
- controller.largeScreenActive = true // Make sure there's a change
- clearInvocations(view)
+ shadeHeaderController.largeScreenActive = true // Make sure there's a change
+ Mockito.clearInvocations(view)
- controller.largeScreenActive = false
+ shadeHeaderController.largeScreenActive = false
- verify(view).setTransition(HEADER_TRANSITION_ID)
+ verify(view).setTransition(ShadeHeaderController.HEADER_TRANSITION_ID)
}
@Test
fun testShadeExpandedFraction() {
// View needs to be visible for this to actually take effect
- controller.qsVisible = true
+ shadeHeaderController.qsVisible = true
- clearInvocations(view)
- controller.shadeExpandedFraction = 0.3f
+ Mockito.clearInvocations(view)
+ shadeHeaderController.shadeExpandedFraction = 0.3f
verify(view).alpha = ShadeInterpolation.getContentAlpha(0.3f)
- clearInvocations(view)
- controller.shadeExpandedFraction = 1f
+ Mockito.clearInvocations(view)
+ shadeHeaderController.shadeExpandedFraction = 1f
verify(view).alpha = ShadeInterpolation.getContentAlpha(1f)
- clearInvocations(view)
- controller.shadeExpandedFraction = 0f
+ Mockito.clearInvocations(view)
+ shadeHeaderController.shadeExpandedFraction = 0f
verify(view).alpha = ShadeInterpolation.getContentAlpha(0f)
}
@Test
fun testQsExpandedFraction_headerTransition() {
- controller.qsVisible = true
- controller.largeScreenActive = false
+ shadeHeaderController.qsVisible = true
+ shadeHeaderController.largeScreenActive = false
- clearInvocations(view)
- controller.qsExpandedFraction = 0.3f
+ Mockito.clearInvocations(view)
+ shadeHeaderController.qsExpandedFraction = 0.3f
verify(view).progress = 0.3f
}
@Test
fun testQsExpandedFraction_largeScreen() {
- controller.qsVisible = true
- controller.largeScreenActive = true
+ shadeHeaderController.qsVisible = true
+ shadeHeaderController.largeScreenActive = true
- clearInvocations(view)
- controller.qsExpandedFraction = 0.3f
- verify(view, never()).progress = anyFloat()
+ Mockito.clearInvocations(view)
+ shadeHeaderController.qsExpandedFraction = 0.3f
+ verify(view, Mockito.never()).progress = anyFloat()
}
@Test
fun testScrollY_headerTransition() {
- controller.largeScreenActive = false
+ shadeHeaderController.largeScreenActive = false
- clearInvocations(view)
- controller.qsScrollY = 20
+ Mockito.clearInvocations(view)
+ shadeHeaderController.qsScrollY = 20
verify(view).scrollY = 20
}
@Test
fun testScrollY_largeScreen() {
- controller.largeScreenActive = true
+ shadeHeaderController.largeScreenActive = true
- clearInvocations(view)
- controller.qsScrollY = 20
- verify(view, never()).scrollY = anyInt()
+ Mockito.clearInvocations(view)
+ shadeHeaderController.qsScrollY = 20
+ verify(view, Mockito.never()).scrollY = anyInt()
}
@Test
@@ -381,9 +502,9 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
verify(chipVisibleChanges.qsConstraintsChanges)!!.invoke(qsConstraints)
verify(chipVisibleChanges.largeScreenConstraintsChanges)!!.invoke(largeScreenConstraints)
- verify(chipNotVisibleChanges.qqsConstraintsChanges, never())!!.invoke(any())
- verify(chipNotVisibleChanges.qsConstraintsChanges, never())!!.invoke(any())
- verify(chipNotVisibleChanges.largeScreenConstraintsChanges, never())!!.invoke(any())
+ verify(chipNotVisibleChanges.qqsConstraintsChanges, Mockito.never())!!.invoke(any())
+ verify(chipNotVisibleChanges.qsConstraintsChanges, Mockito.never())!!.invoke(any())
+ verify(chipNotVisibleChanges.largeScreenConstraintsChanges, Mockito.never())!!.invoke(any())
}
@Test
@@ -401,10 +522,11 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
captor.value.onChipVisibilityRefreshed(false)
- verify(chipVisibleChanges.qqsConstraintsChanges, never())!!.invoke(qqsConstraints)
- verify(chipVisibleChanges.qsConstraintsChanges, never())!!.invoke(qsConstraints)
- verify(chipVisibleChanges.largeScreenConstraintsChanges, never())!!
- .invoke(largeScreenConstraints)
+ verify(chipVisibleChanges.qqsConstraintsChanges, Mockito.never())!!.invoke(qqsConstraints)
+ verify(chipVisibleChanges.qsConstraintsChanges, Mockito.never())!!.invoke(qsConstraints)
+ verify(chipVisibleChanges.largeScreenConstraintsChanges, Mockito.never())!!.invoke(
+ largeScreenConstraints
+ )
verify(chipNotVisibleChanges.qqsConstraintsChanges)!!.invoke(any())
verify(chipNotVisibleChanges.qsConstraintsChanges)!!.invoke(any())
@@ -425,9 +547,15 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
mockInsetsProvider(insetLeft to insetRight, false)
- whenever(combinedShadeHeadersConstraintManager
- .edgesGuidelinesConstraints(anyInt(), anyInt(), anyInt(), anyInt())
- ).thenReturn(mockConstraintsChanges)
+ whenever(
+ combinedShadeHeadersConstraintManager.edgesGuidelinesConstraints(
+ anyInt(),
+ anyInt(),
+ anyInt(),
+ anyInt()
+ )
+ )
+ .thenReturn(mockConstraintsChanges)
captor.value.onApplyWindowInsets(view, createWindowInsets())
@@ -453,9 +581,15 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
mockInsetsProvider(insetLeft to insetRight, false)
- whenever(combinedShadeHeadersConstraintManager
- .edgesGuidelinesConstraints(anyInt(), anyInt(), anyInt(), anyInt())
- ).thenReturn(mockConstraintsChanges)
+ whenever(
+ combinedShadeHeadersConstraintManager.edgesGuidelinesConstraints(
+ anyInt(),
+ anyInt(),
+ anyInt(),
+ anyInt()
+ )
+ )
+ .thenReturn(mockConstraintsChanges)
captor.value.onApplyWindowInsets(view, createWindowInsets())
@@ -479,8 +613,8 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
captor.value.onApplyWindowInsets(view, createWindowInsets(null))
verify(combinedShadeHeadersConstraintManager).emptyCutoutConstraints()
- verify(combinedShadeHeadersConstraintManager, never())
- .centerCutoutConstraints(anyBoolean(), anyInt())
+ verify(combinedShadeHeadersConstraintManager, Mockito.never())
+ .centerCutoutConstraints(Mockito.anyBoolean(), anyInt())
verify(mockConstraintsChanges.qqsConstraintsChanges)!!.invoke(any())
verify(mockConstraintsChanges.qsConstraintsChanges)!!.invoke(any())
@@ -499,8 +633,8 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
captor.value.onApplyWindowInsets(view, createWindowInsets())
verify(combinedShadeHeadersConstraintManager).emptyCutoutConstraints()
- verify(combinedShadeHeadersConstraintManager, never())
- .centerCutoutConstraints(anyBoolean(), anyInt())
+ verify(combinedShadeHeadersConstraintManager, Mockito.never())
+ .centerCutoutConstraints(Mockito.anyBoolean(), anyInt())
verify(mockConstraintsChanges.qqsConstraintsChanges)!!.invoke(any())
verify(mockConstraintsChanges.qsConstraintsChanges)!!.invoke(any())
@@ -521,8 +655,8 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
captor.value.onApplyWindowInsets(view, createWindowInsets())
verify(combinedShadeHeadersConstraintManager).emptyCutoutConstraints()
- verify(combinedShadeHeadersConstraintManager, never())
- .centerCutoutConstraints(anyBoolean(), anyInt())
+ verify(combinedShadeHeadersConstraintManager, Mockito.never())
+ .centerCutoutConstraints(Mockito.anyBoolean(), anyInt())
verify(mockConstraintsChanges.qqsConstraintsChanges)!!.invoke(any())
verify(mockConstraintsChanges.qsConstraintsChanges)!!.invoke(any())
@@ -543,8 +677,8 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
captor.value.onApplyWindowInsets(view, createWindowInsets(Rect(1, 2, 3, 4)))
verify(combinedShadeHeadersConstraintManager).emptyCutoutConstraints()
- verify(combinedShadeHeadersConstraintManager, never())
- .centerCutoutConstraints(anyBoolean(), anyInt())
+ verify(combinedShadeHeadersConstraintManager, Mockito.never())
+ .centerCutoutConstraints(Mockito.anyBoolean(), anyInt())
verify(mockConstraintsChanges.qqsConstraintsChanges)!!.invoke(any())
verify(mockConstraintsChanges.qsConstraintsChanges)!!.invoke(any())
@@ -569,13 +703,17 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
mockInsetsProvider(0 to 0, false)
- whenever(combinedShadeHeadersConstraintManager
- .centerCutoutConstraints(anyBoolean(), anyInt())
- ).thenReturn(mockConstraintsChanges)
+ whenever(
+ combinedShadeHeadersConstraintManager.centerCutoutConstraints(
+ Mockito.anyBoolean(),
+ anyInt()
+ )
+ )
+ .thenReturn(mockConstraintsChanges)
captor.value.onApplyWindowInsets(view, createWindowInsets(Rect(0, 0, cutoutWidth, 1)))
- verify(combinedShadeHeadersConstraintManager, never()).emptyCutoutConstraints()
+ verify(combinedShadeHeadersConstraintManager, Mockito.never()).emptyCutoutConstraints()
val offset = (width - paddingLeft - paddingRight - cutoutWidth) / 2
verify(combinedShadeHeadersConstraintManager).centerCutoutConstraints(false, offset)
@@ -602,13 +740,17 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
mockInsetsProvider(0 to 0, false)
- whenever(combinedShadeHeadersConstraintManager
- .centerCutoutConstraints(anyBoolean(), anyInt())
- ).thenReturn(mockConstraintsChanges)
+ whenever(
+ combinedShadeHeadersConstraintManager.centerCutoutConstraints(
+ Mockito.anyBoolean(),
+ anyInt()
+ )
+ )
+ .thenReturn(mockConstraintsChanges)
captor.value.onApplyWindowInsets(view, createWindowInsets(Rect(0, 0, cutoutWidth, 1)))
- verify(combinedShadeHeadersConstraintManager, never()).emptyCutoutConstraints()
+ verify(combinedShadeHeadersConstraintManager, Mockito.never()).emptyCutoutConstraints()
val offset = (width - paddingLeft - paddingRight - cutoutWidth) / 2
verify(combinedShadeHeadersConstraintManager).centerCutoutConstraints(true, offset)
@@ -619,52 +761,8 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
@Test
fun alarmIconNotIgnored() {
- verify(statusIcons, never()).addIgnoredSlot(
- context.getString(com.android.internal.R.string.status_bar_alarm_clock)
- )
- }
-
- @Test
- fun demoMode_attachDemoMode() {
- verify(demoModeController).addCallback(capture(demoModeControllerCapture))
- demoModeControllerCapture.value.onDemoModeStarted()
- verify(clock).onDemoModeStarted()
- }
-
- @Test
- fun demoMode_detachDemoMode() {
- controller.simulateViewDetached()
- verify(demoModeController).removeCallback(capture(demoModeControllerCapture))
- demoModeControllerCapture.value.onDemoModeFinished()
- verify(clock).onDemoModeFinished()
- }
-
- @Test
- fun animateOutOnStartCustomizing() {
- val animator = Mockito.mock(ViewPropertyAnimator::class.java, Answers.RETURNS_SELF)
- val duration = 1000L
- whenever(view.animate()).thenReturn(animator)
-
- controller.startCustomizingAnimation(show = true, duration)
-
- verify(animator).setDuration(duration)
- verify(animator).alpha(0f)
- verify(animator).setInterpolator(Interpolators.ALPHA_OUT)
- verify(animator).start()
- }
-
- @Test
- fun animateInOnEndCustomizing() {
- val animator = Mockito.mock(ViewPropertyAnimator::class.java, Answers.RETURNS_SELF)
- val duration = 1000L
- whenever(view.animate()).thenReturn(animator)
-
- controller.startCustomizingAnimation(show = false, duration)
-
- verify(animator).setDuration(duration)
- verify(animator).alpha(1f)
- verify(animator).setInterpolator(Interpolators.ALPHA_IN)
- verify(animator).start()
+ verify(statusIcons, Mockito.never())
+ .addIgnoredSlot(context.getString(com.android.internal.R.string.status_bar_alarm_clock))
}
@Test
@@ -674,11 +772,11 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
@Test
fun privacyChipParentVisibleAlways() {
- controller.largeScreenActive = true
- controller.largeScreenActive = false
- controller.largeScreenActive = true
+ shadeHeaderController.largeScreenActive = true
+ shadeHeaderController.largeScreenActive = false
+ shadeHeaderController.largeScreenActive = true
- verify(privacyIconsController, never()).onParentInvisible()
+ verify(privacyIconsController, Mockito.never()).onParentInvisible()
}
@Test
@@ -700,9 +798,9 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
fun onDensityOrFontScaleChanged_reloadConstraints() {
// After density or font scale change, constraints need to be reloaded to reflect new
// dimensions.
- reset(qqsConstraints)
- reset(qsConstraints)
- reset(largeScreenConstraints)
+ Mockito.reset(qqsConstraints)
+ Mockito.reset(qsConstraints)
+ Mockito.reset(largeScreenConstraints)
configurationController.notifyDensityOrFontScaleChanged()
@@ -729,11 +827,11 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
}
private fun View.executeLayoutChange(
- left: Int,
- top: Int,
- right: Int,
- bottom: Int,
- listener: View.OnLayoutChangeListener
+ left: Int,
+ top: Int,
+ right: Int,
+ bottom: Int,
+ listener: View.OnLayoutChangeListener
) {
val oldLeft = this.left
val oldTop = this.top
@@ -746,21 +844,19 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
whenever(this.height).thenReturn(bottom - top)
whenever(this.width).thenReturn(right - left)
listener.onLayoutChange(
- this,
- oldLeft,
- oldTop,
- oldRight,
- oldBottom,
- left,
- top,
- right,
- bottom
+ this,
+ oldLeft,
+ oldTop,
+ oldRight,
+ oldBottom,
+ left,
+ top,
+ right,
+ bottom
)
}
- private fun createWindowInsets(
- topCutout: Rect? = Rect()
- ): WindowInsets {
+ private fun createWindowInsets(topCutout: Rect? = Rect()): WindowInsets {
val windowInsets: WindowInsets = mock()
val displayCutout: DisplayCutout = mock()
whenever(windowInsets.displayCutout)
@@ -795,17 +891,30 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
}
private fun setUpDefaultInsets() {
- whenever(combinedShadeHeadersConstraintManager
- .edgesGuidelinesConstraints(anyInt(), anyInt(), anyInt(), anyInt())
- ).thenReturn(EMPTY_CHANGES)
+ whenever(
+ combinedShadeHeadersConstraintManager.edgesGuidelinesConstraints(
+ anyInt(),
+ anyInt(),
+ anyInt(),
+ anyInt()
+ )
+ )
+ .thenReturn(EMPTY_CHANGES)
whenever(combinedShadeHeadersConstraintManager.emptyCutoutConstraints())
.thenReturn(EMPTY_CHANGES)
- whenever(combinedShadeHeadersConstraintManager
- .centerCutoutConstraints(anyBoolean(), anyInt())
- ).thenReturn(EMPTY_CHANGES)
- whenever(combinedShadeHeadersConstraintManager
- .privacyChipVisibilityConstraints(anyBoolean())
- ).thenReturn(EMPTY_CHANGES)
+ whenever(
+ combinedShadeHeadersConstraintManager.centerCutoutConstraints(
+ Mockito.anyBoolean(),
+ anyInt()
+ )
+ )
+ .thenReturn(EMPTY_CHANGES)
+ whenever(
+ combinedShadeHeadersConstraintManager.privacyChipVisibilityConstraints(
+ Mockito.anyBoolean()
+ )
+ )
+ .thenReturn(EMPTY_CHANGES)
whenever(insetsProvider.getStatusBarContentInsetsForCurrentRotation())
.thenReturn(Pair(0, 0).toAndroidPair())
whenever(insetsProvider.currentRotationHasCornerCutout()).thenReturn(false)
@@ -814,11 +923,11 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
private fun setupCurrentInsets(cutout: DisplayCutout?) {
val mockedDisplay =
- mock<Display>().also { display -> whenever(display.cutout).thenReturn(cutout) }
+ mock<Display>().also { display -> whenever(display.cutout).thenReturn(cutout) }
whenever(viewContext.display).thenReturn(mockedDisplay)
}
- private fun<T, U> Pair<T, U>.toAndroidPair(): android.util.Pair<T, U> {
+ private fun <T, U> Pair<T, U>.toAndroidPair(): android.util.Pair<T, U> {
return android.util.Pair(first, second)
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt
index 7cac854c0853..d5a1f804e6a0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt
@@ -2,37 +2,24 @@ package com.android.systemui.shade.transition
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
-import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
-import com.android.systemui.plugins.qs.QS
-import com.android.systemui.shade.NotificationPanelViewController
import com.android.systemui.shade.STATE_OPENING
import com.android.systemui.shade.ShadeExpansionChangeEvent
import com.android.systemui.shade.ShadeExpansionStateManager
-import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.SysuiStatusBarStateController
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
import com.android.systemui.statusbar.policy.FakeConfigurationController
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
-import org.mockito.Mockito.reset
import org.mockito.Mockito.verify
-import org.mockito.Mockito.verifyZeroInteractions
-import org.mockito.Mockito.`when` as whenever
import org.mockito.MockitoAnnotations
@RunWith(AndroidTestingRunner::class)
@SmallTest
class ShadeTransitionControllerTest : SysuiTestCase() {
- @Mock private lateinit var npvc: NotificationPanelViewController
- @Mock private lateinit var nsslController: NotificationStackScrollLayoutController
- @Mock private lateinit var qs: QS
- @Mock private lateinit var noOpOverScroller: NoOpOverScroller
- @Mock private lateinit var splitShadeOverScroller: SplitShadeOverScroller
@Mock private lateinit var scrimShadeTransitionController: ScrimShadeTransitionController
@Mock private lateinit var dumpManager: DumpManager
@Mock private lateinit var statusBarStateController: SysuiStatusBarStateController
@@ -52,119 +39,19 @@ class ShadeTransitionControllerTest : SysuiTestCase() {
shadeExpansionStateManager,
dumpManager,
context,
- splitShadeOverScrollerFactory = { _, _ -> splitShadeOverScroller },
- noOpOverScroller,
scrimShadeTransitionController,
statusBarStateController,
)
-
- // Resetting as they are notified upon initialization.
- reset(noOpOverScroller, splitShadeOverScroller)
- }
-
- @Test
- fun onPanelExpansionChanged_inSplitShade_forwardsToSplitShadeOverScroller() {
- initLateProperties()
- enableSplitShade()
-
- startPanelExpansion()
-
- verify(splitShadeOverScroller).onPanelStateChanged(STATE_OPENING)
- verify(splitShadeOverScroller).onDragDownAmountChanged(DEFAULT_DRAG_DOWN_AMOUNT)
- verifyZeroInteractions(noOpOverScroller)
- }
-
- @Test
- fun onPanelStateChanged_inSplitShade_propertiesNotInitialized_forwardsToNoOpOverScroller() {
- enableSplitShade()
-
- startPanelExpansion()
-
- verify(noOpOverScroller).onPanelStateChanged(STATE_OPENING)
- verify(noOpOverScroller).onDragDownAmountChanged(DEFAULT_DRAG_DOWN_AMOUNT)
- verifyZeroInteractions(splitShadeOverScroller)
- }
-
- @Test
- fun onPanelStateChanged_inSplitShade_onKeyguard_forwardsToNoOpOverScroller() {
- initLateProperties()
- enableSplitShade()
- setOnKeyguard()
-
- startPanelExpansion()
-
- verify(noOpOverScroller).onPanelStateChanged(STATE_OPENING)
- verify(noOpOverScroller).onDragDownAmountChanged(DEFAULT_DRAG_DOWN_AMOUNT)
- verifyZeroInteractions(splitShadeOverScroller)
- }
-
- @Test
- fun onPanelStateChanged_inSplitShade_onLockedShade_forwardsToNoOpOverScroller() {
- initLateProperties()
- enableSplitShade()
- setOnLockedShade()
-
- startPanelExpansion()
-
- verify(noOpOverScroller).onPanelStateChanged(STATE_OPENING)
- verify(noOpOverScroller).onDragDownAmountChanged(DEFAULT_DRAG_DOWN_AMOUNT)
- verifyZeroInteractions(splitShadeOverScroller)
- }
-
- @Test
- fun onPanelExpansionChanged_inSplitShade_onUnlockedShade_forwardsToSplitShadeOverScroller() {
- initLateProperties()
- enableSplitShade()
- setOnUnlockedShade()
-
- startPanelExpansion()
-
- verify(splitShadeOverScroller).onPanelStateChanged(STATE_OPENING)
- verify(splitShadeOverScroller).onDragDownAmountChanged(DEFAULT_DRAG_DOWN_AMOUNT)
- verifyZeroInteractions(noOpOverScroller)
- }
-
- @Test
- fun onPanelStateChanged_notInSplitShade_forwardsToNoOpOverScroller() {
- initLateProperties()
- disableSplitShade()
-
- startPanelExpansion()
-
- verify(noOpOverScroller).onPanelStateChanged(STATE_OPENING)
- verify(noOpOverScroller).onDragDownAmountChanged(DEFAULT_DRAG_DOWN_AMOUNT)
- verifyZeroInteractions(splitShadeOverScroller)
}
@Test
fun onPanelStateChanged_forwardsToScrimTransitionController() {
- initLateProperties()
-
startPanelExpansion()
verify(scrimShadeTransitionController).onPanelStateChanged(STATE_OPENING)
verify(scrimShadeTransitionController).onPanelExpansionChanged(DEFAULT_EXPANSION_EVENT)
}
- private fun initLateProperties() {
- controller.qs = qs
- controller.notificationStackScrollLayoutController = nsslController
- controller.notificationPanelViewController = npvc
- }
-
- private fun disableSplitShade() {
- setSplitShadeEnabled(false)
- }
-
- private fun enableSplitShade() {
- setSplitShadeEnabled(true)
- }
-
- private fun setSplitShadeEnabled(enabled: Boolean) {
- overrideResource(R.bool.config_use_split_notification_shade, enabled)
- configurationController.notifyConfigurationChanged()
- }
-
private fun startPanelExpansion() {
shadeExpansionStateManager.onPanelExpansionChanged(
DEFAULT_EXPANSION_EVENT.fraction,
@@ -174,23 +61,6 @@ class ShadeTransitionControllerTest : SysuiTestCase() {
)
}
- private fun setOnKeyguard() {
- setShadeState(StatusBarState.KEYGUARD)
- }
-
- private fun setOnLockedShade() {
- setShadeState(StatusBarState.SHADE_LOCKED)
- }
-
- private fun setOnUnlockedShade() {
- setShadeState(StatusBarState.SHADE)
- }
-
- private fun setShadeState(state: Int) {
- whenever(statusBarStateController.state).thenReturn(state)
- whenever(statusBarStateController.currentOrUpcomingState).thenReturn(state)
- }
-
companion object {
private const val DEFAULT_DRAG_DOWN_AMOUNT = 123f
private val DEFAULT_EXPANSION_EVENT =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/SplitShadeOverScrollerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/SplitShadeOverScrollerTest.kt
deleted file mode 100644
index 0e48b4835dfe..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/SplitShadeOverScrollerTest.kt
+++ /dev/null
@@ -1,112 +0,0 @@
-package com.android.systemui.shade.transition
-
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper
-import androidx.test.filters.SmallTest
-import com.android.systemui.R
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.dump.DumpManager
-import com.android.systemui.plugins.qs.QS
-import com.android.systemui.shade.STATE_CLOSED
-import com.android.systemui.shade.STATE_OPEN
-import com.android.systemui.shade.STATE_OPENING
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
-import com.android.systemui.statusbar.phone.ScrimController
-import com.android.systemui.statusbar.policy.FakeConfigurationController
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.Mockito.atLeastOnce
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.verifyZeroInteractions
-import org.mockito.Mockito.`when` as whenever
-import org.mockito.MockitoAnnotations
-
-@RunWith(AndroidTestingRunner::class)
-@TestableLooper.RunWithLooper(setAsMainLooper = true)
-@SmallTest
-class SplitShadeOverScrollerTest : SysuiTestCase() {
-
- @Mock private lateinit var dumpManager: DumpManager
- @Mock private lateinit var scrimController: ScrimController
- @Mock private lateinit var qs: QS
- @Mock private lateinit var nsslController: NotificationStackScrollLayoutController
-
- private val configurationController = FakeConfigurationController()
- private lateinit var overScroller: SplitShadeOverScroller
-
- @Before
- fun setUp() {
- MockitoAnnotations.initMocks(this)
-
- whenever(nsslController.height).thenReturn(1000)
- overScroller =
- SplitShadeOverScroller(
- configurationController,
- dumpManager,
- context,
- scrimController,
- { qs },
- { nsslController })
- }
-
- @Test
- fun onDragDownAmountChanged_panelOpening_overScrolls_basedOnHeightAndMaxAmount() {
- val maxOverScrollAmount = 50
- val dragDownAmount = 100f
- overrideResource(R.dimen.shade_max_over_scroll_amount, maxOverScrollAmount)
- configurationController.notifyConfigurationChanged()
-
- overScroller.onPanelStateChanged(STATE_OPENING)
- overScroller.onDragDownAmountChanged(dragDownAmount)
-
- val expectedOverScrollAmount =
- (dragDownAmount / nsslController.height * maxOverScrollAmount).toInt()
- verify(qs).setOverScrollAmount(expectedOverScrollAmount)
- verify(nsslController).setOverScrollAmount(expectedOverScrollAmount)
- verify(scrimController).setNotificationsOverScrollAmount(expectedOverScrollAmount)
- }
-
- @Test
- fun onDragDownAmountChanged_panelClosed_doesNotOverScroll() {
- overScroller.onPanelStateChanged(STATE_CLOSED)
- overScroller.onDragDownAmountChanged(100f)
-
- verifyZeroInteractions(qs, scrimController, nsslController)
- }
-
- @Test
- fun onDragDownAmountChanged_panelOpen_doesNotOverScroll() {
- overScroller.onPanelStateChanged(STATE_OPEN)
- overScroller.onDragDownAmountChanged(100f)
-
- verifyZeroInteractions(qs, scrimController, nsslController)
- }
-
- @Test
- fun onPanelStateChanged_opening_thenOpen_releasesOverScroll() {
- overScroller.onPanelStateChanged(STATE_OPENING)
- overScroller.onDragDownAmountChanged(100f)
-
- overScroller.onPanelStateChanged(STATE_OPEN)
- overScroller.finishAnimations()
-
- verify(qs, atLeastOnce()).setOverScrollAmount(0)
- verify(scrimController, atLeastOnce()).setNotificationsOverScrollAmount(0)
- verify(nsslController, atLeastOnce()).setOverScrollAmount(0)
- }
-
- @Test
- fun onPanelStateChanged_opening_thenClosed_releasesOverScroll() {
- overScroller.onPanelStateChanged(STATE_OPENING)
- overScroller.onDragDownAmountChanged(100f)
-
- overScroller.onPanelStateChanged(STATE_CLOSED)
- overScroller.finishAnimations()
-
- verify(qs, atLeastOnce()).setOverScrollAmount(0)
- verify(scrimController, atLeastOnce()).setNotificationsOverScrollAmount(0)
- verify(nsslController, atLeastOnce()).setOverScrollAmount(0)
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt
index 7a74b1229c5c..56fc0c74dafa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt
@@ -36,21 +36,26 @@ class UnfoldConstantTranslateAnimatorTest : SysuiTestCase() {
private val progressProvider = TestUnfoldTransitionProvider()
- @Mock private lateinit var parent: ViewGroup
+ @Mock
+ private lateinit var parent: ViewGroup
+
+ @Mock
+ private lateinit var shouldBeAnimated: () -> Boolean
private lateinit var animator: UnfoldConstantTranslateAnimator
- private val viewsIdToRegister =
- setOf(
- ViewIdToTranslate(START_VIEW_ID, Direction.START),
- ViewIdToTranslate(END_VIEW_ID, Direction.END))
+ private val viewsIdToRegister
+ get() =
+ setOf(
+ ViewIdToTranslate(START_VIEW_ID, Direction.START, shouldBeAnimated),
+ ViewIdToTranslate(END_VIEW_ID, Direction.END, shouldBeAnimated)
+ )
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
-
- animator =
- UnfoldConstantTranslateAnimator(viewsIdToRegister, progressProvider)
+ whenever(shouldBeAnimated.invoke()).thenReturn(true)
+ animator = UnfoldConstantTranslateAnimator(viewsIdToRegister, progressProvider)
animator.init(parent, MAX_TRANSLATION)
}
@@ -96,6 +101,20 @@ class UnfoldConstantTranslateAnimatorTest : SysuiTestCase() {
moveAndValidate(listOf(leftView to START, rightView to END), View.LAYOUT_DIRECTION_LTR)
}
+ @Test
+ fun onTransition_completeStartedTranslation() {
+ // GIVEN
+ val leftView = View(context)
+ whenever(parent.findViewById<View>(START_VIEW_ID)).thenReturn(leftView)
+ // To start animation, shouldBeAnimated should return true.
+ // There is a possibility for shouldBeAnimated to return false during the animation.
+ whenever(shouldBeAnimated.invoke()).thenReturn(true).thenReturn(false)
+
+ // shouldBeAnimated state may change during the animation.
+ // However, started animation should be completed.
+ moveAndValidate(listOf(leftView to START), View.LAYOUT_DIRECTION_LTR)
+ }
+
private fun moveAndValidate(list: List<Pair<View, Int>>, layoutDirection: Int) {
// Compare values as ints because -0f != 0f
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
index 26eff61066ee..1fdb3647fcb2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
@@ -35,7 +35,6 @@ import junit.framework.Assert.fail
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
-import org.json.JSONException
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -271,10 +270,14 @@ class ClockRegistryTest : SysuiTestCase() {
@Test
fun jsonDeserialization_gotExpectedObject() {
- val expected = ClockSettings("ID", null).apply { _applied_timestamp = 500 }
+ val expected = ClockSettings("ID", null).apply {
+ metadata.put("appliedTimestamp", 500)
+ }
val actual = ClockSettings.deserialize("""{
"clockId":"ID",
- "_applied_timestamp":500
+ "metadata": {
+ "appliedTimestamp":500
+ }
}""")
assertEquals(expected, actual)
}
@@ -291,29 +294,32 @@ class ClockRegistryTest : SysuiTestCase() {
val expected = ClockSettings("ID", null)
val actual = ClockSettings.deserialize("""{
"clockId":"ID",
- "_applied_timestamp":null
+ "metadata":null
}""")
assertEquals(expected, actual)
}
- @Test(expected = JSONException::class)
- fun jsonDeserialization_noId_threwException() {
- val expected = ClockSettings(null, null).apply { _applied_timestamp = 500 }
- val actual = ClockSettings.deserialize("{\"_applied_timestamp\":500}")
+ @Test
+ fun jsonDeserialization_noId_deserializedEmpty() {
+ val expected = ClockSettings(null, null).apply {
+ metadata.put("appliedTimestamp", 500)
+ }
+ val actual = ClockSettings.deserialize("{\"metadata\":{\"appliedTimestamp\":500}}")
assertEquals(expected, actual)
}
@Test
fun jsonSerialization_gotExpectedString() {
- val expected = "{\"clockId\":\"ID\",\"_applied_timestamp\":500}"
- val actual = ClockSettings.serialize(ClockSettings("ID", null)
- .apply { _applied_timestamp = 500 })
+ val expected = "{\"clockId\":\"ID\",\"metadata\":{\"appliedTimestamp\":500}}"
+ val actual = ClockSettings.serialize(ClockSettings("ID", null).apply {
+ metadata.put("appliedTimestamp", 500)
+ })
assertEquals(expected, actual)
}
@Test
fun jsonSerialization_noTimestamp_gotExpectedString() {
- val expected = "{\"clockId\":\"ID\"}"
+ val expected = "{\"clockId\":\"ID\",\"metadata\":{}}"
val actual = ClockSettings.serialize(ClockSettings("ID", null))
assertEquals(expected, actual)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
index cd2efc061b72..7fa27f34cd9f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
@@ -26,6 +26,7 @@ import android.widget.FrameLayout
import androidx.test.filters.SmallTest
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
+import com.android.systemui.plugins.ClockSettings
import com.android.systemui.shared.clocks.DefaultClockController.Companion.DOZE_COLOR
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.eq
@@ -40,7 +41,6 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyFloat
-import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.notNull
import org.mockito.Mock
import org.mockito.Mockito.never
@@ -97,13 +97,14 @@ class DefaultClockProviderTest : SysuiTestCase() {
@Test
fun defaultClock_initialize() {
val clock = provider.createClock(DEFAULT_CLOCK_ID)
- verify(mockSmallClockView).setColors(Color.MAGENTA, Color.MAGENTA)
- verify(mockLargeClockView).setColors(Color.MAGENTA, Color.MAGENTA)
+ verify(mockSmallClockView).setColors(DOZE_COLOR, Color.MAGENTA)
+ verify(mockLargeClockView).setColors(DOZE_COLOR, Color.MAGENTA)
clock.initialize(resources, 0f, 0f)
- verify(mockSmallClockView).setColors(eq(DOZE_COLOR), anyInt())
- verify(mockLargeClockView).setColors(eq(DOZE_COLOR), anyInt())
+ val expectedColor = 0
+ verify(mockSmallClockView).setColors(DOZE_COLOR, expectedColor)
+ verify(mockLargeClockView).setColors(DOZE_COLOR, expectedColor)
verify(mockSmallClockView).onTimeZoneChanged(notNull())
verify(mockLargeClockView).onTimeZoneChanged(notNull())
verify(mockSmallClockView).refreshTime()
@@ -159,15 +160,31 @@ class DefaultClockProviderTest : SysuiTestCase() {
@Test
fun defaultClock_events_onColorPaletteChanged() {
+ val expectedColor = 0
val clock = provider.createClock(DEFAULT_CLOCK_ID)
- verify(mockSmallClockView).setColors(Color.MAGENTA, Color.MAGENTA)
- verify(mockLargeClockView).setColors(Color.MAGENTA, Color.MAGENTA)
+ verify(mockSmallClockView).setColors(DOZE_COLOR, Color.MAGENTA)
+ verify(mockLargeClockView).setColors(DOZE_COLOR, Color.MAGENTA)
clock.events.onColorPaletteChanged(resources)
- verify(mockSmallClockView).setColors(eq(DOZE_COLOR), anyInt())
- verify(mockLargeClockView).setColors(eq(DOZE_COLOR), anyInt())
+ verify(mockSmallClockView).setColors(DOZE_COLOR, expectedColor)
+ verify(mockLargeClockView).setColors(DOZE_COLOR, expectedColor)
+ }
+
+ @Test
+ fun defaultClock_events_onSeedColorChanged() {
+ val initSeedColor = 10
+ val newSeedColor = 20
+ val clock = provider.createClock(ClockSettings(DEFAULT_CLOCK_ID, initSeedColor))
+
+ verify(mockSmallClockView).setColors(DOZE_COLOR, initSeedColor)
+ verify(mockLargeClockView).setColors(DOZE_COLOR, initSeedColor)
+
+ clock.events.onSeedColorChanged(newSeedColor)
+
+ verify(mockSmallClockView).setColors(DOZE_COLOR, newSeedColor)
+ verify(mockLargeClockView).setColors(DOZE_COLOR, newSeedColor)
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/system/RemoteTransitionTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/system/RemoteTransitionTest.java
index 4478039912c8..64e58d0de2b9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/system/RemoteTransitionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/system/RemoteTransitionTest.java
@@ -49,6 +49,7 @@ import android.window.TransitionInfo;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
+import com.android.wm.shell.util.TransitionUtil;
import org.junit.Before;
import org.junit.Test;
@@ -120,7 +121,7 @@ public class RemoteTransitionTest extends SysuiTestCase {
change.setTaskInfo(createTaskInfo(1 /* taskId */, ACTIVITY_TYPE_HOME));
change.setEndAbsBounds(endBounds);
change.setEndRelOffset(0, 0);
- RemoteAnimationTarget wrapped = RemoteAnimationTargetCompat.newTarget(
+ RemoteAnimationTarget wrapped = TransitionUtil.newTarget(
change, 0 /* order */, tinfo, mock(SurfaceControl.Transaction.class), null);
assertEquals(ACTIVITY_TYPE_HOME, wrapped.windowConfiguration.getActivityType());
assertEquals(new Rect(0, 0, 100, 140), wrapped.localBounds);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyboardShortcutsReceiverTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyboardShortcutsReceiverTest.java
index bea2cfb8bb5c..bedb2b33d07b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyboardShortcutsReceiverTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyboardShortcutsReceiverTest.java
@@ -73,7 +73,7 @@ public class KeyboardShortcutsReceiverTest extends SysuiTestCase {
.startMocking();
mFeatureFlags.set(Flags.SHORTCUT_LIST_SEARCH_LAYOUT, false);
mKeyboardShortcutsReceiver = spy(new KeyboardShortcutsReceiver(mFeatureFlags));
- when(Utilities.isTablet(mContext)).thenReturn(true);
+ when(Utilities.isLargeScreen(mContext)).thenReturn(true);
mKeyboardShortcutsReceiver.onReceive(mContext, mIntent);
@@ -90,7 +90,7 @@ public class KeyboardShortcutsReceiverTest extends SysuiTestCase {
.startMocking();
mFeatureFlags.set(Flags.SHORTCUT_LIST_SEARCH_LAYOUT, false);
mKeyboardShortcutsReceiver = spy(new KeyboardShortcutsReceiver(mFeatureFlags));
- when(Utilities.isTablet(mContext)).thenReturn(false);
+ when(Utilities.isLargeScreen(mContext)).thenReturn(false);
mKeyboardShortcutsReceiver.onReceive(mContext, mIntent);
@@ -107,7 +107,7 @@ public class KeyboardShortcutsReceiverTest extends SysuiTestCase {
.startMocking();
mFeatureFlags.set(Flags.SHORTCUT_LIST_SEARCH_LAYOUT, true);
mKeyboardShortcutsReceiver = spy(new KeyboardShortcutsReceiver(mFeatureFlags));
- when(Utilities.isTablet(mContext)).thenReturn(true);
+ when(Utilities.isLargeScreen(mContext)).thenReturn(true);
mKeyboardShortcutsReceiver.onReceive(mContext, mIntent);
@@ -124,7 +124,7 @@ public class KeyboardShortcutsReceiverTest extends SysuiTestCase {
.startMocking();
mFeatureFlags.set(Flags.SHORTCUT_LIST_SEARCH_LAYOUT, true);
mKeyboardShortcutsReceiver = spy(new KeyboardShortcutsReceiver(mFeatureFlags));
- when(Utilities.isTablet(mContext)).thenReturn(false);
+ when(Utilities.isLargeScreen(mContext)).thenReturn(false);
mKeyboardShortcutsReceiver.onReceive(mContext, mIntent);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
index d99cdd514f37..ab615f99ebad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
@@ -211,16 +211,6 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
}
@Test
- fun testTriggeringBouncerWhenPrivateNotificationsArentAllowed() {
- whenever(lockScreenUserManager.userAllowsPrivateNotificationsInPublic(anyInt())).thenReturn(
- false)
- transitionController.goToLockedShade(null)
- verify(statusbarStateController, never()).setState(anyInt())
- verify(statusbarStateController).setLeaveOpenOnKeyguardHide(true)
- verify(mCentralSurfaces).showBouncerWithDimissAndCancelIfKeyguard(anyObject(), anyObject())
- }
-
- @Test
fun testTriggeringBouncerNoNotificationsOnLockscreen() {
whenever(lockScreenUserManager.shouldShowLockscreenNotifications()).thenReturn(false)
transitionController.goToLockedShade(null)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
index 452606dfcca4..8ee1ea8a9916 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
@@ -44,6 +44,7 @@ import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
+import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.Dependency;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
@@ -354,7 +355,8 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
mDeviceProvisionedController,
mKeyguardStateController,
mSettings,
- mock(DumpManager.class));
+ mock(DumpManager.class),
+ mock(LockPatternUtils.class));
}
public BroadcastReceiver getBaseBroadcastReceiverForTest() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/FakeStatusEvent.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/FakeStatusEvent.kt
new file mode 100644
index 000000000000..cd0646543e69
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/FakeStatusEvent.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2023 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.events
+
+/**
+ * This is a freely configurable implementation of [StatusEvent]. It is intended to be used in
+ * tests.
+ */
+class FakeStatusEvent(
+ override val viewCreator: ViewCreator,
+ override val priority: Int = 50,
+ override var forceVisible: Boolean = false,
+ override val showAnimation: Boolean = true,
+ override var contentDescription: String? = "",
+) : StatusEvent
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImplTest.kt
new file mode 100644
index 000000000000..08a9f3139d71
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImplTest.kt
@@ -0,0 +1,470 @@
+/*
+ * Copyright (C) 2023 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.events
+
+import android.graphics.Rect
+import android.os.Process
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+import android.view.View
+import android.widget.FrameLayout
+import androidx.core.animation.AnimatorTestRule
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.privacy.OngoingPrivacyChip
+import com.android.systemui.statusbar.BatteryStatusChip
+import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
+import com.android.systemui.statusbar.window.StatusBarWindowController
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.time.FakeSystemClock
+import junit.framework.Assert.assertEquals
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.advanceTimeBy
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.anyBoolean
+import org.mockito.Mockito.never
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper(setAsMainLooper = true)
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+class SystemStatusAnimationSchedulerImplTest : SysuiTestCase() {
+
+ @Mock private lateinit var systemEventCoordinator: SystemEventCoordinator
+ @Mock private lateinit var statusBarWindowController: StatusBarWindowController
+ @Mock private lateinit var statusBarContentInsetProvider: StatusBarContentInsetsProvider
+ @Mock private lateinit var dumpManager: DumpManager
+ @Mock private lateinit var listener: SystemStatusAnimationCallback
+
+ private lateinit var systemClock: FakeSystemClock
+ private lateinit var chipAnimationController: SystemEventChipAnimationController
+ private lateinit var systemStatusAnimationScheduler: SystemStatusAnimationScheduler
+ private val fakeFeatureFlags = FakeFeatureFlags()
+
+ @get:Rule val animatorTestRule = AnimatorTestRule()
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+
+ fakeFeatureFlags.set(Flags.PLUG_IN_STATUS_BAR_CHIP, true)
+
+ systemClock = FakeSystemClock()
+ chipAnimationController =
+ SystemEventChipAnimationController(
+ mContext,
+ statusBarWindowController,
+ statusBarContentInsetProvider,
+ fakeFeatureFlags
+ )
+
+ // ensure that isTooEarly() check in SystemStatusAnimationScheduler does not return true
+ systemClock.advanceTime(Process.getStartUptimeMillis() + MIN_UPTIME)
+
+ // StatusBarContentInsetProvider is mocked. Ensure that it returns some mocked values.
+ whenever(statusBarContentInsetProvider.getStatusBarContentInsetsForCurrentRotation())
+ .thenReturn(android.util.Pair(10, 10))
+ whenever(statusBarContentInsetProvider.getStatusBarContentAreaForCurrentRotation())
+ .thenReturn(Rect(10, 0, 990, 100))
+
+ // StatusBarWindowController is mocked. The addViewToWindow function needs to be mocked to
+ // ensure that the chip view is added to a parent view
+ whenever(statusBarWindowController.addViewToWindow(any(), any())).then {
+ val statusbarFake = FrameLayout(mContext)
+ statusbarFake.layout(0, 0, 1000, 100)
+ statusbarFake.addView(
+ it.arguments[0] as View,
+ it.arguments[1] as FrameLayout.LayoutParams
+ )
+ }
+ }
+
+ @Test
+ fun testBatteryStatusEvent_standardAnimationLifecycle() = runTest {
+ // Instantiate class under test with TestScope from runTest
+ initializeSystemStatusAnimationScheduler(testScope = this)
+
+ val batteryChip = createAndScheduleFakeBatteryEvent()
+
+ // assert that animation is queued
+ assertEquals(ANIMATION_QUEUED, systemStatusAnimationScheduler.getAnimationState())
+
+ // skip debounce delay
+ advanceTimeBy(DEBOUNCE_DELAY + 1)
+ // status chip starts animating in after debounce delay
+ assertEquals(ANIMATING_IN, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(0f, batteryChip.contentView.alpha)
+ assertEquals(0f, batteryChip.view.alpha)
+ verify(listener, times(1)).onSystemEventAnimationBegin()
+
+ // skip appear animation
+ animatorTestRule.advanceTimeBy(APPEAR_ANIMATION_DURATION)
+ advanceTimeBy(APPEAR_ANIMATION_DURATION)
+ // assert that status chip is visible
+ assertEquals(RUNNING_CHIP_ANIM, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(1f, batteryChip.contentView.alpha)
+ assertEquals(1f, batteryChip.view.alpha)
+
+ // skip status chip display time
+ advanceTimeBy(DISPLAY_LENGTH + 1)
+ // assert that it is still visible but switched to the ANIMATING_OUT state
+ assertEquals(ANIMATING_OUT, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(1f, batteryChip.contentView.alpha)
+ assertEquals(1f, batteryChip.view.alpha)
+ verify(listener, times(1)).onSystemEventAnimationFinish(false)
+
+ // skip disappear animation
+ animatorTestRule.advanceTimeBy(DISAPPEAR_ANIMATION_DURATION)
+ // assert that it is not visible anymore
+ assertEquals(IDLE, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(0f, batteryChip.contentView.alpha)
+ assertEquals(0f, batteryChip.view.alpha)
+ }
+
+ @Test
+ fun testPrivacyStatusEvent_standardAnimationLifecycle() = runTest {
+ // Instantiate class under test with TestScope from runTest
+ initializeSystemStatusAnimationScheduler(testScope = this)
+
+ val privacyChip = createAndScheduleFakePrivacyEvent()
+
+ // assert that animation is queued
+ assertEquals(ANIMATION_QUEUED, systemStatusAnimationScheduler.getAnimationState())
+
+ // skip debounce delay
+ advanceTimeBy(DEBOUNCE_DELAY + 1)
+ // status chip starts animating in after debounce delay
+ assertEquals(ANIMATING_IN, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(0f, privacyChip.view.alpha)
+ verify(listener, times(1)).onSystemEventAnimationBegin()
+
+ // skip appear animation
+ animatorTestRule.advanceTimeBy(APPEAR_ANIMATION_DURATION)
+ advanceTimeBy(APPEAR_ANIMATION_DURATION + 1)
+ // assert that status chip is visible
+ assertEquals(RUNNING_CHIP_ANIM, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(1f, privacyChip.view.alpha)
+
+ // skip status chip display time
+ advanceTimeBy(DISPLAY_LENGTH + 1)
+ // assert that it is still visible but switched to the ANIMATING_OUT state
+ assertEquals(ANIMATING_OUT, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(1f, privacyChip.view.alpha)
+ verify(listener, times(1)).onSystemEventAnimationFinish(true)
+ verify(listener, times(1)).onSystemStatusAnimationTransitionToPersistentDot(any())
+
+ // skip transition to persistent dot
+ advanceTimeBy(DISAPPEAR_ANIMATION_DURATION + 1)
+ animatorTestRule.advanceTimeBy(DISAPPEAR_ANIMATION_DURATION)
+ // assert that it the dot is now visible
+ assertEquals(SHOWING_PERSISTENT_DOT, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(1f, privacyChip.view.alpha)
+
+ // notify SystemStatusAnimationScheduler to remove persistent dot
+ systemStatusAnimationScheduler.removePersistentDot()
+ // assert that IDLE state is entered
+ assertEquals(IDLE, systemStatusAnimationScheduler.getAnimationState())
+ verify(listener, times(1)).onHidePersistentDot()
+ }
+
+ @Test
+ fun testHighPriorityEvent_takesPrecedenceOverScheduledLowPriorityEvent() = runTest {
+ // Instantiate class under test with TestScope from runTest
+ initializeSystemStatusAnimationScheduler(testScope = this)
+
+ // create and schedule low priority event
+ val batteryChip = createAndScheduleFakeBatteryEvent()
+ batteryChip.view.alpha = 0f
+
+ // assert that animation is queued
+ assertEquals(ANIMATION_QUEUED, systemStatusAnimationScheduler.getAnimationState())
+
+ // create and schedule high priority event
+ val privacyChip = createAndScheduleFakePrivacyEvent()
+
+ // assert that animation is queued
+ assertEquals(ANIMATION_QUEUED, systemStatusAnimationScheduler.getAnimationState())
+
+ // skip debounce delay and appear animation duration
+ fastForwardAnimationToState(RUNNING_CHIP_ANIM)
+
+ // high priority status chip is visible while low priority status chip is not visible
+ assertEquals(RUNNING_CHIP_ANIM, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(1f, privacyChip.view.alpha)
+ assertEquals(0f, batteryChip.view.alpha)
+ }
+
+ @Test
+ fun testHighPriorityEvent_cancelsCurrentlyDisplayedLowPriorityEvent() = runTest {
+ // Instantiate class under test with TestScope from runTest
+ initializeSystemStatusAnimationScheduler(testScope = this)
+
+ // create and schedule low priority event
+ val batteryChip = createAndScheduleFakeBatteryEvent()
+
+ // fast forward to RUNNING_CHIP_ANIM state
+ fastForwardAnimationToState(RUNNING_CHIP_ANIM)
+
+ // assert that chip is displayed
+ assertEquals(RUNNING_CHIP_ANIM, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(1f, batteryChip.view.alpha)
+
+ // create and schedule high priority event
+ val privacyChip = createAndScheduleFakePrivacyEvent()
+
+ // ensure that the event cancellation coroutine is started by the test scope
+ testScheduler.runCurrent()
+
+ // assert that currently displayed chip is immediately animated out
+ assertEquals(ANIMATING_OUT, systemStatusAnimationScheduler.getAnimationState())
+
+ // skip disappear animation
+ animatorTestRule.advanceTimeBy(DISAPPEAR_ANIMATION_DURATION)
+
+ // assert that high priority privacy chip animation is queued
+ assertEquals(ANIMATION_QUEUED, systemStatusAnimationScheduler.getAnimationState())
+
+ // skip debounce delay and appear animation
+ advanceTimeBy(DEBOUNCE_DELAY + APPEAR_ANIMATION_DURATION + 1)
+ animatorTestRule.advanceTimeBy(APPEAR_ANIMATION_DURATION)
+
+ // high priority status chip is visible while low priority status chip is not visible
+ assertEquals(RUNNING_CHIP_ANIM, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(1f, privacyChip.view.alpha)
+ assertEquals(0f, batteryChip.view.alpha)
+ }
+
+ @Test
+ fun testHighPriorityEvent_cancelsCurrentlyAnimatedLowPriorityEvent() = runTest {
+ // Instantiate class under test with TestScope from runTest
+ initializeSystemStatusAnimationScheduler(testScope = this)
+
+ // create and schedule low priority event
+ val batteryChip = createAndScheduleFakeBatteryEvent()
+
+ // skip debounce delay
+ advanceTimeBy(DEBOUNCE_DELAY + 1)
+
+ // assert that chip is animated in
+ assertEquals(ANIMATING_IN, systemStatusAnimationScheduler.getAnimationState())
+
+ // create and schedule high priority event
+ val privacyChip = createAndScheduleFakePrivacyEvent()
+
+ // ensure that the event cancellation coroutine is started by the test scope
+ testScheduler.runCurrent()
+
+ // assert that currently animated chip keeps animating
+ assertEquals(ANIMATING_IN, systemStatusAnimationScheduler.getAnimationState())
+
+ // skip appear animation
+ animatorTestRule.advanceTimeBy(APPEAR_ANIMATION_DURATION)
+ advanceTimeBy(APPEAR_ANIMATION_DURATION + 1)
+
+ // assert that low priority chip is animated out immediately after finishing the appear
+ // animation
+ assertEquals(ANIMATING_OUT, systemStatusAnimationScheduler.getAnimationState())
+
+ // skip disappear animation
+ animatorTestRule.advanceTimeBy(DISAPPEAR_ANIMATION_DURATION)
+
+ // assert that high priority privacy chip animation is queued
+ assertEquals(ANIMATION_QUEUED, systemStatusAnimationScheduler.getAnimationState())
+
+ // skip debounce delay and appear animation
+ advanceTimeBy(DEBOUNCE_DELAY + APPEAR_ANIMATION_DURATION + 1)
+ animatorTestRule.advanceTimeBy(APPEAR_ANIMATION_DURATION)
+
+ // high priority status chip is visible while low priority status chip is not visible
+ assertEquals(RUNNING_CHIP_ANIM, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(1f, privacyChip.view.alpha)
+ assertEquals(0f, batteryChip.view.alpha)
+ }
+
+ @Test
+ fun testHighPriorityEvent_isNotReplacedByLowPriorityEvent() = runTest {
+ // Instantiate class under test with TestScope from runTest
+ initializeSystemStatusAnimationScheduler(testScope = this)
+
+ // create and schedule high priority event
+ val privacyChip = createAndScheduleFakePrivacyEvent()
+
+ // create and schedule low priority event
+ val batteryChip = createAndScheduleFakeBatteryEvent()
+ batteryChip.view.alpha = 0f
+
+ // skip debounce delay and appear animation
+ advanceTimeBy(DEBOUNCE_DELAY + APPEAR_ANIMATION_DURATION + 1)
+ animatorTestRule.advanceTimeBy(APPEAR_ANIMATION_DURATION)
+
+ // high priority status chip is visible while low priority status chip is not visible
+ assertEquals(RUNNING_CHIP_ANIM, systemStatusAnimationScheduler.getAnimationState())
+ assertEquals(1f, privacyChip.view.alpha)
+ assertEquals(0f, batteryChip.view.alpha)
+ }
+
+ @Test
+ fun testPrivacyDot_isRemoved() = runTest {
+ // Instantiate class under test with TestScope from runTest
+ initializeSystemStatusAnimationScheduler(testScope = this)
+
+ // create and schedule high priority event
+ createAndScheduleFakePrivacyEvent()
+
+ // skip chip animation lifecycle and fast forward to SHOWING_PERSISTENT_DOT state
+ fastForwardAnimationToState(SHOWING_PERSISTENT_DOT)
+ assertEquals(SHOWING_PERSISTENT_DOT, systemStatusAnimationScheduler.getAnimationState())
+ verify(listener, times(1)).onSystemStatusAnimationTransitionToPersistentDot(any())
+
+ // remove persistent dot and verify that animationState changes to IDLE
+ systemStatusAnimationScheduler.removePersistentDot()
+ assertEquals(IDLE, systemStatusAnimationScheduler.getAnimationState())
+ verify(listener, times(1)).onHidePersistentDot()
+ }
+
+ @Test
+ fun testPrivacyDot_isRemovedDuringChipAnimation() = runTest {
+ // Instantiate class under test with TestScope from runTest
+ initializeSystemStatusAnimationScheduler(testScope = this)
+
+ // create and schedule high priority event
+ createAndScheduleFakePrivacyEvent()
+
+ // skip chip animation lifecycle and fast forward to RUNNING_CHIP_ANIM state
+ fastForwardAnimationToState(RUNNING_CHIP_ANIM)
+ assertEquals(RUNNING_CHIP_ANIM, systemStatusAnimationScheduler.getAnimationState())
+
+ // request removal of persistent dot
+ systemStatusAnimationScheduler.removePersistentDot()
+
+ // skip display time and verify that disappear animation is run
+ advanceTimeBy(DISPLAY_LENGTH + 1)
+ assertEquals(ANIMATING_OUT, systemStatusAnimationScheduler.getAnimationState())
+
+ // skip disappear animation and verify that animationState changes to IDLE instead of
+ // SHOWING_PERSISTENT_DOT
+ animatorTestRule.advanceTimeBy(DISAPPEAR_ANIMATION_DURATION)
+ assertEquals(IDLE, systemStatusAnimationScheduler.getAnimationState())
+ // verify that the persistent dot callbacks are not invoked
+ verify(listener, never()).onSystemStatusAnimationTransitionToPersistentDot(any())
+ verify(listener, never()).onHidePersistentDot()
+ }
+
+ @Test
+ fun testNewEvent_isScheduled_whenPostedDuringRemovalAnimation() = runTest {
+ // Instantiate class under test with TestScope from runTest
+ initializeSystemStatusAnimationScheduler(testScope = this)
+
+ // create and schedule high priority event
+ createAndScheduleFakePrivacyEvent()
+
+ // skip chip animation lifecycle and fast forward to ANIMATING_OUT state
+ fastForwardAnimationToState(ANIMATING_OUT)
+ assertEquals(ANIMATING_OUT, systemStatusAnimationScheduler.getAnimationState())
+ verify(listener, times(1)).onSystemStatusAnimationTransitionToPersistentDot(any())
+
+ // request removal of persistent dot
+ systemStatusAnimationScheduler.removePersistentDot()
+ testScheduler.runCurrent()
+
+ // schedule another high priority event while the event is animating out
+ createAndScheduleFakePrivacyEvent()
+
+ // verify that the state is still ANIMATING_OUT
+ assertEquals(ANIMATING_OUT, systemStatusAnimationScheduler.getAnimationState())
+
+ // skip disappear animation duration and verify that new state is ANIMATION_QUEUED
+ animatorTestRule.advanceTimeBy(DISAPPEAR_ANIMATION_DURATION)
+ testScheduler.runCurrent()
+ assertEquals(ANIMATION_QUEUED, systemStatusAnimationScheduler.getAnimationState())
+ // also verify that onHidePersistentDot callback is called
+ verify(listener, times(1)).onHidePersistentDot()
+ }
+
+ private fun TestScope.fastForwardAnimationToState(@SystemAnimationState animationState: Int) {
+ // this function should only be called directly after posting a status event
+ assertEquals(ANIMATION_QUEUED, systemStatusAnimationScheduler.getAnimationState())
+ if (animationState == IDLE || animationState == ANIMATION_QUEUED) return
+ // skip debounce delay
+ advanceTimeBy(DEBOUNCE_DELAY + 1)
+
+ // status chip starts animating in after debounce delay
+ assertEquals(ANIMATING_IN, systemStatusAnimationScheduler.getAnimationState())
+ verify(listener, times(1)).onSystemEventAnimationBegin()
+ if (animationState == ANIMATING_IN) return
+
+ // skip appear animation
+ animatorTestRule.advanceTimeBy(APPEAR_ANIMATION_DURATION)
+ advanceTimeBy(APPEAR_ANIMATION_DURATION)
+ assertEquals(RUNNING_CHIP_ANIM, systemStatusAnimationScheduler.getAnimationState())
+ if (animationState == RUNNING_CHIP_ANIM) return
+
+ // skip status chip display time
+ advanceTimeBy(DISPLAY_LENGTH + 1)
+ assertEquals(ANIMATING_OUT, systemStatusAnimationScheduler.getAnimationState())
+ verify(listener, times(1)).onSystemEventAnimationFinish(anyBoolean())
+ if (animationState == ANIMATING_OUT) return
+
+ // skip disappear animation
+ animatorTestRule.advanceTimeBy(DISAPPEAR_ANIMATION_DURATION)
+ }
+
+ private fun createAndScheduleFakePrivacyEvent(): OngoingPrivacyChip {
+ val privacyChip = OngoingPrivacyChip(mContext)
+ val fakePrivacyStatusEvent =
+ FakeStatusEvent(viewCreator = { privacyChip }, priority = 100, forceVisible = true)
+ systemStatusAnimationScheduler.onStatusEvent(fakePrivacyStatusEvent)
+ return privacyChip
+ }
+
+ private fun createAndScheduleFakeBatteryEvent(): BatteryStatusChip {
+ val batteryChip = BatteryStatusChip(mContext)
+ val fakeBatteryEvent =
+ FakeStatusEvent(viewCreator = { batteryChip }, priority = 50, forceVisible = false)
+ systemStatusAnimationScheduler.onStatusEvent(fakeBatteryEvent)
+ return batteryChip
+ }
+
+ private fun initializeSystemStatusAnimationScheduler(testScope: TestScope) {
+ systemStatusAnimationScheduler =
+ SystemStatusAnimationSchedulerImpl(
+ systemEventCoordinator,
+ chipAnimationController,
+ statusBarWindowController,
+ dumpManager,
+ systemClock,
+ CoroutineScope(StandardTestDispatcher(testScope.testScheduler))
+ )
+ // add a mock listener
+ systemStatusAnimationScheduler.addCallback(listener)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLoggerTest.kt
new file mode 100644
index 000000000000..7a6779684fc5
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLoggerTest.kt
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.log.LogBuffer
+import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.plugins.log.LogcatEchoTracker
+import com.android.systemui.statusbar.StatusBarState
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class NotificationWakeUpCoordinatorLoggerTest : SysuiTestCase() {
+
+ private val logBufferCounter = LogBufferCounter()
+ private lateinit var logger: NotificationWakeUpCoordinatorLogger
+
+ private fun verifyDidLog(times: Int) {
+ logBufferCounter.verifyDidLog(times)
+ }
+
+ @Before
+ fun setup() {
+ logger = NotificationWakeUpCoordinatorLogger(logBufferCounter.logBuffer)
+ }
+
+ @Test
+ fun setDozeAmountWillThrottleFractionalUpdates() {
+ logger.logSetDozeAmount(0f, 0f, "source1", StatusBarState.SHADE, changed = false)
+ verifyDidLog(1)
+ logger.logSetDozeAmount(0.1f, 0.1f, "source1", StatusBarState.SHADE, changed = true)
+ verifyDidLog(1)
+ logger.logSetDozeAmount(0.2f, 0.2f, "source1", StatusBarState.SHADE, changed = true)
+ logger.logSetDozeAmount(0.3f, 0.3f, "source1", StatusBarState.SHADE, changed = true)
+ logger.logSetDozeAmount(0.4f, 0.4f, "source1", StatusBarState.SHADE, changed = true)
+ logger.logSetDozeAmount(0.5f, 0.5f, "source1", StatusBarState.SHADE, changed = true)
+ verifyDidLog(0)
+ logger.logSetDozeAmount(1f, 1f, "source1", StatusBarState.SHADE, changed = true)
+ verifyDidLog(1)
+ }
+
+ @Test
+ fun setDozeAmountWillIncludeFractionalUpdatesWhenStateChanges() {
+ logger.logSetDozeAmount(0f, 0f, "source1", StatusBarState.SHADE, changed = false)
+ verifyDidLog(1)
+ logger.logSetDozeAmount(0.1f, 0.1f, "source1", StatusBarState.SHADE, changed = true)
+ verifyDidLog(1)
+ logger.logSetDozeAmount(0.2f, 0.2f, "source1", StatusBarState.SHADE, changed = true)
+ logger.logSetDozeAmount(0.3f, 0.3f, "source1", StatusBarState.SHADE, changed = true)
+ logger.logSetDozeAmount(0.4f, 0.4f, "source1", StatusBarState.SHADE, changed = true)
+ logger.logSetDozeAmount(0.5f, 0.5f, "source1", StatusBarState.SHADE, changed = true)
+ verifyDidLog(0)
+ logger.logSetDozeAmount(0.5f, 0.5f, "source1", StatusBarState.KEYGUARD, changed = false)
+ verifyDidLog(1)
+ }
+
+ @Test
+ fun setDozeAmountWillIncludeFractionalUpdatesWhenSourceChanges() {
+ logger.logSetDozeAmount(0f, 0f, "source1", StatusBarState.SHADE, changed = false)
+ verifyDidLog(1)
+ logger.logSetDozeAmount(0.1f, 0.1f, "source1", StatusBarState.SHADE, changed = true)
+ verifyDidLog(1)
+ logger.logSetDozeAmount(0.2f, 0.2f, "source1", StatusBarState.SHADE, changed = true)
+ logger.logSetDozeAmount(0.3f, 0.3f, "source1", StatusBarState.SHADE, changed = true)
+ logger.logSetDozeAmount(0.4f, 0.4f, "source1", StatusBarState.SHADE, changed = true)
+ logger.logSetDozeAmount(0.5f, 0.5f, "source1", StatusBarState.SHADE, changed = true)
+ verifyDidLog(0)
+ logger.logSetDozeAmount(0.5f, 0.5f, "source2", StatusBarState.SHADE, changed = false)
+ verifyDidLog(1)
+ }
+
+ class LogBufferCounter {
+ val recentLogs = mutableListOf<Pair<String, LogLevel>>()
+ val tracker =
+ object : LogcatEchoTracker {
+ override val logInBackgroundThread: Boolean = false
+ override fun isBufferLoggable(bufferName: String, level: LogLevel): Boolean = false
+ override fun isTagLoggable(tagName: String, level: LogLevel): Boolean {
+ recentLogs.add(tagName to level)
+ return true
+ }
+ }
+ val logBuffer =
+ LogBuffer(name = "test", maxSize = 1, logcatEchoTracker = tracker, systrace = false)
+
+ fun verifyDidLog(times: Int) {
+ assertThat(recentLogs).hasSize(times)
+ recentLogs.clear()
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorTest.kt
new file mode 100644
index 000000000000..95591a4b321c
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorTest.kt
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.statusbar.StatusBarState
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
+import com.android.systemui.statusbar.phone.DozeParameters
+import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.statusbar.phone.ScreenOffAnimationController
+import com.android.systemui.statusbar.policy.HeadsUpManager
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.mockito.withArgCaptor
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.anyFloat
+import org.mockito.Mockito.clearInvocations
+import org.mockito.Mockito.verify
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class NotificationWakeUpCoordinatorTest : SysuiTestCase() {
+
+ private val dumpManager: DumpManager = mock()
+ private val headsUpManager: HeadsUpManager = mock()
+ private val statusBarStateController: StatusBarStateController = mock()
+ private val bypassController: KeyguardBypassController = mock()
+ private val dozeParameters: DozeParameters = mock()
+ private val screenOffAnimationController: ScreenOffAnimationController = mock()
+ private val logger: NotificationWakeUpCoordinatorLogger = mock()
+ private val stackScrollerController: NotificationStackScrollLayoutController = mock()
+
+ private lateinit var notificationWakeUpCoordinator: NotificationWakeUpCoordinator
+ private lateinit var statusBarStateCallback: StatusBarStateController.StateListener
+ private lateinit var bypassChangeCallback: KeyguardBypassController.OnBypassStateChangedListener
+
+ private var bypassEnabled: Boolean = false
+ private var statusBarState: Int = StatusBarState.KEYGUARD
+ private var dozeAmount: Float = 0f
+
+ private fun setBypassEnabled(enabled: Boolean) {
+ bypassEnabled = enabled
+ bypassChangeCallback.onBypassStateChanged(enabled)
+ }
+
+ private fun setStatusBarState(state: Int) {
+ statusBarState = state
+ statusBarStateCallback.onStateChanged(state)
+ }
+
+ private fun setDozeAmount(dozeAmount: Float) {
+ this.dozeAmount = dozeAmount
+ statusBarStateCallback.onDozeAmountChanged(dozeAmount, dozeAmount)
+ }
+
+ @Before
+ fun setup() {
+ whenever(bypassController.bypassEnabled).then { bypassEnabled }
+ whenever(statusBarStateController.state).then { statusBarState }
+ notificationWakeUpCoordinator =
+ NotificationWakeUpCoordinator(
+ dumpManager,
+ headsUpManager,
+ statusBarStateController,
+ bypassController,
+ dozeParameters,
+ screenOffAnimationController,
+ logger,
+ )
+ statusBarStateCallback = withArgCaptor {
+ verify(statusBarStateController).addCallback(capture())
+ }
+ bypassChangeCallback = withArgCaptor {
+ verify(bypassController).registerOnBypassStateChangedListener(capture())
+ }
+ notificationWakeUpCoordinator.setStackScroller(stackScrollerController)
+ }
+
+ @Test
+ fun setDozeToOneWillFullyHideNotifications() {
+ setDozeAmount(1f)
+ verifyStackScrollerDozeAndHideAmount(dozeAmount = 1f, hideAmount = 1f)
+ assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isTrue()
+ }
+
+ @Test
+ fun setDozeToZeroWillFullyShowNotifications() {
+ setDozeAmount(0f)
+ verifyStackScrollerDozeAndHideAmount(dozeAmount = 0f, hideAmount = 0f)
+ assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isFalse()
+ }
+
+ @Test
+ fun setDozeToOneThenZeroWillFullyShowNotifications() {
+ setDozeToOneWillFullyHideNotifications()
+ clearInvocations(stackScrollerController)
+ setDozeToZeroWillFullyShowNotifications()
+ }
+
+ @Test
+ fun setDozeToHalfWillHalfShowNotifications() {
+ setDozeAmount(0.5f)
+ verifyStackScrollerDozeAndHideAmount(dozeAmount = 0.5f, hideAmount = 0.5f)
+ assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isFalse()
+ }
+
+ @Test
+ fun setDozeToZeroWithBypassWillFullyHideNotifications() {
+ bypassEnabled = true
+ setDozeAmount(0f)
+ verifyStackScrollerDozeAndHideAmount(dozeAmount = 01f, hideAmount = 1f)
+ assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isTrue()
+ }
+
+ @Test
+ fun disablingBypassWillShowNotifications() {
+ setDozeToZeroWithBypassWillFullyHideNotifications()
+ clearInvocations(stackScrollerController)
+ setBypassEnabled(false)
+ verifyStackScrollerDozeAndHideAmount(dozeAmount = 0f, hideAmount = 0f)
+ assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isFalse()
+ }
+
+ @Test
+ fun switchingToShadeWithBypassEnabledWillShowNotifications() {
+ setDozeToZeroWithBypassWillFullyHideNotifications()
+ clearInvocations(stackScrollerController)
+ setStatusBarState(StatusBarState.SHADE)
+ verifyStackScrollerDozeAndHideAmount(dozeAmount = 0f, hideAmount = 0f)
+ assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isFalse()
+ assertThat(notificationWakeUpCoordinator.statusBarState).isEqualTo(StatusBarState.SHADE)
+ }
+
+ private fun verifyStackScrollerDozeAndHideAmount(dozeAmount: Float, hideAmount: Float) {
+ // First verify that we did in-fact receive the correct values
+ verify(stackScrollerController).setDozeAmount(dozeAmount)
+ verify(stackScrollerController).setHideAmount(hideAmount, hideAmount)
+ // Now verify that there was just this ONE call to each of these methods
+ verify(stackScrollerController).setDozeAmount(anyFloat())
+ verify(stackScrollerController).setHideAmount(anyFloat(), anyFloat())
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/FakeNodeController.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/FakeNodeController.kt
new file mode 100644
index 000000000000..2de21ae8f0a1
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/FakeNodeController.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.statusbar.notification.collection.render
+
+import android.view.View
+
+class FakeNodeController(
+ override val view: View,
+ override val nodeLabel: String = "fakeNodeController"
+) : NodeController {
+ override fun offerToKeepInParentForAnimation(): Boolean = false
+ override fun removeFromParentIfKeptForAnimation(): Boolean = false
+ override fun resetKeepInParentForAnimation() = Unit
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/fsi/FsiChromeRepoTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/fsi/FsiChromeRepoTest.kt
deleted file mode 100644
index a6a9e51aa555..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/fsi/FsiChromeRepoTest.kt
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.notification.fsi
-
-import android.R
-import android.app.Notification
-import android.app.NotificationManager
-import android.app.PendingIntent
-import android.content.pm.ApplicationInfo
-import android.content.pm.PackageManager
-import android.graphics.drawable.Drawable
-import android.os.UserHandle
-import android.service.dreams.IDreamManager
-import android.service.notification.StatusBarNotification
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper.RunWithLooper
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.flags.FakeFeatureFlags
-import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
-import com.android.systemui.statusbar.notification.collection.NotificationEntry
-import com.android.systemui.statusbar.notification.collection.provider.LaunchFullScreenIntentProvider
-import com.android.systemui.statusbar.phone.CentralSurfaces
-import java.util.concurrent.Executor
-import junit.framework.Assert.assertEquals
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.ArgumentMatchers.any
-import org.mockito.ArgumentMatchers.anyString
-import org.mockito.Mock
-import org.mockito.Mockito
-import org.mockito.Mockito.never
-import org.mockito.Mockito.times
-import org.mockito.Mockito.`when` as whenever
-import org.mockito.MockitoAnnotations
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
-@RunWithLooper(setAsMainLooper = true)
-class FsiChromeRepoTest : SysuiTestCase() {
-
- @Mock lateinit var centralSurfaces: CentralSurfaces
- @Mock lateinit var fsiChromeRepo: FsiChromeRepo
- @Mock lateinit var packageManager: PackageManager
-
- var keyguardRepo = FakeKeyguardRepository()
- @Mock private lateinit var applicationInfo: ApplicationInfo
-
- @Mock lateinit var launchFullScreenIntentProvider: LaunchFullScreenIntentProvider
- var featureFlags = FakeFeatureFlags()
- @Mock lateinit var dreamManager: IDreamManager
-
- // Execute all foreground & background requests immediately
- private val uiBgExecutor = Executor { r -> r.run() }
-
- private val appName: String = "appName"
- private val appIcon: Drawable = context.getDrawable(com.android.systemui.R.drawable.ic_android)
- private val fsi: PendingIntent = Mockito.mock(PendingIntent::class.java)
-
- @Before
- fun setUp() {
- MockitoAnnotations.initMocks(this)
-
- // Set up package manager mocks
- whenever(packageManager.getApplicationIcon(anyString())).thenReturn(appIcon)
- whenever(packageManager.getApplicationIcon(any(ApplicationInfo::class.java)))
- .thenReturn(appIcon)
- whenever(packageManager.getApplicationLabel(any())).thenReturn(appName)
- mContext.setMockPackageManager(packageManager)
-
- fsiChromeRepo =
- FsiChromeRepo(
- mContext,
- packageManager,
- keyguardRepo,
- launchFullScreenIntentProvider,
- featureFlags,
- uiBgExecutor,
- dreamManager,
- centralSurfaces
- )
- }
-
- private fun createFsiEntry(fsi: PendingIntent): NotificationEntry {
- val nb =
- Notification.Builder(mContext, "a")
- .setContentTitle("foo")
- .setSmallIcon(R.drawable.sym_def_app_icon)
- .setFullScreenIntent(fsi, /* highPriority= */ true)
-
- val sbn =
- StatusBarNotification(
- "pkg",
- "opPkg",
- /* id= */ 0,
- "tag" + System.currentTimeMillis(),
- /* uid= */ 0,
- /* initialPid */ 0,
- nb.build(),
- UserHandle(0),
- /* overrideGroupKey= */ null,
- /* postTime= */ 0
- )
-
- val entry = Mockito.mock(NotificationEntry::class.java)
- whenever(entry.importance).thenReturn(NotificationManager.IMPORTANCE_HIGH)
- whenever(entry.sbn).thenReturn(sbn)
- return entry
- }
-
- @Test
- fun testLaunchFullscreenIntent_flagNotEnabled_noLaunch() {
- // Setup
- featureFlags.set(Flags.FSI_CHROME, false)
-
- // Test
- val entry = createFsiEntry(fsi)
- fsiChromeRepo.launchFullscreenIntent(entry)
-
- // Verify
- Mockito.verify(centralSurfaces, never()).wakeUpForFullScreenIntent()
- }
-
- @Test
- fun testLaunchFullscreenIntent_notOnKeyguard_noLaunch() {
- // Setup
- featureFlags.set(Flags.FSI_CHROME, true)
- keyguardRepo.setKeyguardShowing(false)
-
- // Test
- val entry = createFsiEntry(fsi)
- fsiChromeRepo.launchFullscreenIntent(entry)
-
- // Verify
- Mockito.verify(centralSurfaces, never()).wakeUpForFullScreenIntent()
- }
-
- @Test
- fun testLaunchFullscreenIntent_stopsScreensaver() {
- // Setup
- featureFlags.set(Flags.FSI_CHROME, true)
- keyguardRepo.setKeyguardShowing(true)
-
- // Test
- val entry = createFsiEntry(fsi)
- fsiChromeRepo.launchFullscreenIntent(entry)
-
- // Verify
- Mockito.verify(dreamManager, times(1)).awaken()
- }
-
- @Test
- fun testLaunchFullscreenIntent_updatesFsiInfoFlow() {
- // Setup
- featureFlags.set(Flags.FSI_CHROME, true)
- keyguardRepo.setKeyguardShowing(true)
-
- // Test
- val entry = createFsiEntry(fsi)
- fsiChromeRepo.launchFullscreenIntent(entry)
-
- // Verify
- val expectedFsiInfo = FsiChromeRepo.FSIInfo(appName, appIcon, fsi)
- assertEquals(expectedFsiInfo, fsiChromeRepo.infoFlow.value)
- }
-
- @Test
- fun testLaunchFullscreenIntent_notifyFsiLaunched() {
- // Setup
- featureFlags.set(Flags.FSI_CHROME, true)
- keyguardRepo.setKeyguardShowing(true)
-
- // Test
- val entry = createFsiEntry(fsi)
- fsiChromeRepo.launchFullscreenIntent(entry)
-
- // Verify
- Mockito.verify(entry, times(1)).notifyFullScreenIntentLaunched()
- }
-
- @Test
- fun testLaunchFullscreenIntent_wakesUpDevice() {
- // Setup
- featureFlags.set(Flags.FSI_CHROME, true)
- keyguardRepo.setKeyguardShowing(true)
-
- // Test
- val entry = createFsiEntry(fsi)
- fsiChromeRepo.launchFullscreenIntent(entry)
-
- // Verify
- Mockito.verify(centralSurfaces, times(1)).wakeUpForFullScreenIntent()
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewModelFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewModelFactoryTest.kt
deleted file mode 100644
index 5cee9e377dfb..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewModelFactoryTest.kt
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.notification.fsi
-
-import android.app.PendingIntent
-import android.graphics.drawable.Drawable
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper.RunWithLooper
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.util.concurrency.FakeExecutor
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.mock
-import com.android.systemui.util.mockito.whenever
-import com.android.systemui.util.mockito.withArgCaptor
-import com.android.systemui.util.time.FakeSystemClock
-import com.android.wm.shell.TaskView
-import com.android.wm.shell.TaskViewFactory
-import com.google.common.truth.Truth.assertThat
-import java.util.Optional
-import java.util.function.Consumer
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.SharingStarted
-import kotlinx.coroutines.flow.onStart
-import kotlinx.coroutines.flow.stateIn
-import kotlinx.coroutines.test.runCurrent
-import kotlinx.coroutines.test.runTest
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.Mockito
-import org.mockito.Mockito.verify
-import org.mockito.MockitoAnnotations
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
-@RunWithLooper(setAsMainLooper = true)
-class FsiChromeViewModelFactoryTest : SysuiTestCase() {
- @Mock private lateinit var taskViewFactoryOptional: Optional<TaskViewFactory>
- @Mock private lateinit var taskViewFactory: TaskViewFactory
- @Mock lateinit var taskView: TaskView
-
- @Main var mainExecutor = FakeExecutor(FakeSystemClock())
- lateinit var viewModelFactory: FsiChromeViewModelFactory
-
- private val fakeInfoFlow = MutableStateFlow<FsiChromeRepo.FSIInfo?>(null)
- private var fsiChromeRepo: FsiChromeRepo =
- mock<FsiChromeRepo>().apply { whenever(infoFlow).thenReturn(fakeInfoFlow) }
-
- private val appName = "appName"
- private val appIcon: Drawable = context.getDrawable(com.android.systemui.R.drawable.ic_android)
- private val fsi: PendingIntent = Mockito.mock(PendingIntent::class.java)
- private val fsiInfo = FsiChromeRepo.FSIInfo(appName, appIcon, fsi)
-
- @Before
- fun setUp() {
- MockitoAnnotations.initMocks(this)
-
- whenever(taskViewFactoryOptional.get()).thenReturn(taskViewFactory)
-
- viewModelFactory =
- FsiChromeViewModelFactory(fsiChromeRepo, taskViewFactoryOptional, context, mainExecutor)
- }
-
- @Test
- fun testViewModelFlow_update_createsTaskView() {
- runTest {
- val latestViewModel =
- viewModelFactory.viewModelFlow
- .onStart { FsiDebug.log("viewModelFactory.viewModelFlow.onStart") }
- .stateIn(
- backgroundScope, // stateIn runs forever, don't count it as test coroutine
- SharingStarted.Eagerly,
- null
- )
- runCurrent() // Drain queued backgroundScope operations
-
- // Test: emit the fake FSIInfo
- fakeInfoFlow.emit(fsiInfo)
- runCurrent()
-
- val taskViewFactoryCallback: Consumer<TaskView> = withArgCaptor {
- verify(taskViewFactory).create(any(), any(), capture())
- }
- taskViewFactoryCallback.accept(taskView) // this will call k.resume
- runCurrent()
-
- // Verify that the factory has produced a new ViewModel
- // containing the relevant data from FsiInfo
- val expectedViewModel =
- FsiChromeViewModel(appName, appIcon, taskView, fsi, fsiChromeRepo)
-
- assertThat(latestViewModel.value).isEqualTo(expectedViewModel)
- }
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt
index 5b6c8c6a3f92..fb3aba1a77a0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt
@@ -31,15 +31,19 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.NotificationMediaManager
import com.android.systemui.statusbar.SmartReplyController
import com.android.systemui.statusbar.notification.collection.provider.NotificationDismissibilityProvider
+import com.android.systemui.statusbar.notification.collection.render.FakeNodeController
import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager
import com.android.systemui.statusbar.notification.logging.NotificationLogger
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier
+import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer
import com.android.systemui.statusbar.notification.stack.NotificationListContainer
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.policy.HeadsUpManager
import com.android.systemui.statusbar.policy.SmartReplyConstants
import com.android.systemui.statusbar.policy.dagger.RemoteInputViewSubcomponent
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.time.SystemClock
import com.android.systemui.wmshell.BubblesManager
@@ -68,6 +72,7 @@ class ExpandableNotificationRowControllerTest : SysuiTestCase() {
private val metricsLogger: MetricsLogger = mock()
private val logBufferLogger: NotificationRowLogger = mock()
private val listContainer: NotificationListContainer = mock()
+ private val childrenContainer: NotificationChildrenContainer = mock()
private val mediaManager: NotificationMediaManager = mock()
private val smartReplyConstants: SmartReplyConstants = mock()
private val smartReplyController: SmartReplyController = mock()
@@ -129,6 +134,7 @@ class ExpandableNotificationRowControllerTest : SysuiTestCase() {
dragController,
dismissibilityProvider
)
+ whenever(view.childrenContainer).thenReturn(childrenContainer)
}
@After
@@ -173,4 +179,32 @@ class ExpandableNotificationRowControllerTest : SysuiTestCase() {
Assert.assertFalse(controller.removeFromParentIfKeptForAnimation())
Mockito.verifyNoMoreInteractions(parentView)
}
+
+ @Test
+ fun removeChild_whenTransfer() {
+ val childView: ExpandableNotificationRow = mock()
+ val childNodeController = FakeNodeController(childView)
+
+ // GIVEN a child is removed for transfer
+ controller.removeChild(childNodeController, /* isTransfer= */ true)
+
+ // VERIFY the listContainer is not notified
+ Mockito.verify(childView).isChangingPosition = eq(true)
+ Mockito.verify(view).removeChildNotification(eq(childView))
+ Mockito.verify(listContainer, never()).notifyGroupChildRemoved(any(), any())
+ }
+
+ @Test
+ fun removeChild_whenNotTransfer() {
+ val childView: ExpandableNotificationRow = mock()
+ val childNodeController = FakeNodeController(childView)
+
+ // GIVEN a child is removed for real
+ controller.removeChild(childNodeController, /* isTransfer= */ false)
+
+ // VERIFY the listContainer is passed the childrenContainer for transient animations
+ Mockito.verify(childView, never()).isChangingPosition = any()
+ Mockito.verify(view).removeChildNotification(eq(childView))
+ Mockito.verify(listContainer).notifyGroupChildRemoved(eq(childView), eq(childrenContainer))
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
index 5b8305dbbd33..89c399bbf204 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
@@ -415,6 +415,37 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase {
verify(mNotificationStackScrollLayout).updateEmptyShadeView(anyBoolean(), anyBoolean());
}
+ @Test
+ public void testAttach_updatesViewStatusBarState() {
+ // GIVEN: Controller is attached
+ mController.attach(mNotificationStackScrollLayout);
+ ArgumentCaptor<StatusBarStateController.StateListener> captor =
+ ArgumentCaptor.forClass(StatusBarStateController.StateListener.class);
+ verify(mSysuiStatusBarStateController).addCallback(captor.capture(), anyInt());
+ StatusBarStateController.StateListener stateListener = captor.getValue();
+
+ // WHEN: StatusBarState changes to SHADE
+ when(mSysuiStatusBarStateController.getState()).thenReturn(SHADE);
+ stateListener.onStateChanged(SHADE);
+
+ // THEN: NSSL is updated with the current state
+ verify(mNotificationStackScrollLayout).setStatusBarState(SHADE);
+
+ // WHEN: Controller is detached
+ mController.mOnAttachStateChangeListener
+ .onViewDetachedFromWindow(mNotificationStackScrollLayout);
+
+ // WHEN: StatusBarState changes to KEYGUARD
+ when(mSysuiStatusBarStateController.getState()).thenReturn(KEYGUARD);
+
+ // WHEN: Controller is re-attached
+ mController.mOnAttachStateChangeListener
+ .onViewAttachedToWindow(mNotificationStackScrollLayout);
+
+ // THEN: NSSL is updated with the current state
+ verify(mNotificationStackScrollLayout).setStatusBarState(KEYGUARD);
+ }
+
private LogMaker logMatcher(int category, int type) {
return argThat(new LogMatcher(category, type));
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
index 680a32375988..78da78269ac4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
@@ -20,6 +20,7 @@ import static junit.framework.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
@@ -227,14 +228,154 @@ public class NotificationSwipeHelperTest extends SysuiTestCase {
}
@Test
- public void testHandleUpEvent_menuRow() {
- when(mSwipeHelper.getCurrentMenuRow()).thenReturn(mMenuRow);
- doNothing().when(mSwipeHelper).handleMenuRowSwipe(mEvent, mView, 0, mMenuRow);
+ public void testHandleUpEvent_menuRowWithoutMenu_dismiss() {
+ doNothing().when(mSwipeHelper).dismiss(any(), anyFloat());
+ doReturn(true).when(mSwipeHelper).isDismissGesture(any());
+ doReturn(true).when(mSwipeHelper).swipedFarEnough();
+ when(mMenuRow.shouldShowMenu()).thenReturn(true);
+ mSwipeHelper.setCurrentMenuRow(mMenuRow);
+
+ assertTrue("Menu row exists",
+ mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
+ verify(mMenuRow, times(1)).onTouchEnd();
+ verify(mSwipeHelper, times(1)).isDismissGesture(mEvent);
+ verify(mSwipeHelper, times(1)).dismiss(mView, 0);
+ verify(mSwipeHelper, never()).isFalseGesture();
+ }
+
+ @Test
+ public void testHandleUpEvent_menuRowWithoutMenu_snapback() {
+ doNothing().when(mSwipeHelper).snapChild(any(), anyInt(), anyFloat());
+ doReturn(false).when(mSwipeHelper).isDismissGesture(any());
+ doReturn(true).when(mSwipeHelper).swipedFarEnough();
+ when(mMenuRow.shouldShowMenu()).thenReturn(true);
+ mSwipeHelper.setCurrentMenuRow(mMenuRow);
+
+ assertTrue("Menu row exists",
+ mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
+ verify(mMenuRow, times(1)).onTouchEnd();
+ verify(mSwipeHelper, times(1)).isDismissGesture(mEvent);
+ verify(mSwipeHelper, times(1)).snapClosed(mView, 0);
+ verify(mMenuRow, times(1)).onSnapClosed();
+ verify(mSwipeHelper, never()).isFalseGesture();
+ }
+
+ @Test
+ public void testHandleUpEvent_menuRowWithOpenMenu_dismissed() {
+ doNothing().when(mSwipeHelper).dismiss(any(), anyFloat());
+ doReturn(true).when(mSwipeHelper).isDismissGesture(any());
+ doReturn(true).when(mSwipeHelper).swipedFarEnough();
+ when(mMenuRow.shouldShowMenu()).thenReturn(true);
+ when(mMenuRow.isSnappedAndOnSameSide()).thenReturn(true);
+ mSwipeHelper.setCurrentMenuRow(mMenuRow);
+
+ assertTrue("Menu row exists",
+ mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
+ verify(mMenuRow, times(1)).onTouchEnd();
+ verify(mSwipeHelper, times(1)).isDismissGesture(mEvent);
+ verify(mSwipeHelper, times(1)).dismiss(mView, 0);
+ verify(mSwipeHelper, never()).isFalseGesture();
+ }
+
+ @Test
+ public void testHandleUpEvent_menuRowWithOpenMenu_snapback() {
+ doNothing().when(mSwipeHelper).snapChild(any(), anyInt(), anyFloat());
+ doReturn(false).when(mSwipeHelper).isDismissGesture(any());
+ doReturn(true).when(mSwipeHelper).swipedFarEnough();
+ when(mMenuRow.shouldShowMenu()).thenReturn(true);
+ when(mMenuRow.isSnappedAndOnSameSide()).thenReturn(true);
+ mSwipeHelper.setCurrentMenuRow(mMenuRow);
+
+ assertTrue("Menu row exists",
+ mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
+ verify(mMenuRow, times(1)).onTouchEnd();
+ verify(mSwipeHelper, times(1)).isDismissGesture(mEvent);
+ verify(mSwipeHelper, times(1)).snapClosed(mView, 0);
+ verify(mMenuRow, times(1)).onSnapClosed();
+ verify(mSwipeHelper, never()).isFalseGesture();
+ }
+
+ @Test
+ public void testHandleUpEvent_menuRowWithClosedMenu_dismissed() {
+ doNothing().when(mSwipeHelper).dismiss(any(), anyFloat());
+ doReturn(true).when(mSwipeHelper).isDismissGesture(any());
+ doReturn(true).when(mSwipeHelper).swipedFarEnough();
+ when(mMenuRow.shouldShowMenu()).thenReturn(true);
+ when(mMenuRow.isSnappedAndOnSameSide()).thenReturn(false);
+ mSwipeHelper.setCurrentMenuRow(mMenuRow);
assertTrue("Menu row exists",
mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
verify(mMenuRow, times(1)).onTouchEnd();
- verify(mSwipeHelper, times(1)).handleMenuRowSwipe(mEvent, mView, 0, mMenuRow);
+ verify(mSwipeHelper, times(1)).isDismissGesture(mEvent);
+ verify(mSwipeHelper, times(1)).dismiss(mView, 0);
+ verify(mSwipeHelper, never()).isFalseGesture();
+ }
+
+ @Test
+ public void testHandleUpEvent_menuRowWithClosedMenu_snapback() {
+ doNothing().when(mSwipeHelper).snapChild(any(), anyInt(), anyFloat());
+ doReturn(false).when(mSwipeHelper).isDismissGesture(any());
+ doReturn(true).when(mSwipeHelper).swipedFarEnough();
+ when(mMenuRow.shouldShowMenu()).thenReturn(true);
+ when(mMenuRow.isSnappedAndOnSameSide()).thenReturn(false);
+ mSwipeHelper.setCurrentMenuRow(mMenuRow);
+
+ assertTrue("Menu row exists",
+ mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
+ verify(mMenuRow, times(1)).onTouchEnd();
+ verify(mSwipeHelper, times(1)).isDismissGesture(mEvent);
+ verify(mSwipeHelper, times(1)).snapClosed(mView, 0);
+ verify(mMenuRow, times(1)).onSnapClosed();
+ verify(mSwipeHelper, never()).isFalseGesture();
+ }
+
+ @Test
+ public void testIsDismissGesture() {
+ doReturn(false).when(mSwipeHelper).isFalseGesture();
+ doReturn(true).when(mSwipeHelper).swipedFarEnough();
+ doReturn(true).when(mSwipeHelper).swipedFastEnough();
+ when(mCallback.canChildBeDismissedInDirection(any(), anyBoolean())).thenReturn(true);
+ when(mEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_UP);
+
+ assertTrue("Should be a dismiss gesture", mSwipeHelper.isDismissGesture(mEvent));
+ verify(mSwipeHelper, times(1)).isFalseGesture();
+ }
+
+ @Test
+ public void testIsDismissGesture_falseGesture() {
+ doReturn(true).when(mSwipeHelper).isFalseGesture();
+ doReturn(true).when(mSwipeHelper).swipedFarEnough();
+ doReturn(true).when(mSwipeHelper).swipedFastEnough();
+ when(mCallback.canChildBeDismissedInDirection(any(), anyBoolean())).thenReturn(true);
+ when(mEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_UP);
+
+ assertFalse("False gesture should stop dismissal", mSwipeHelper.isDismissGesture(mEvent));
+ verify(mSwipeHelper, times(1)).isFalseGesture();
+ }
+
+ @Test
+ public void testIsDismissGesture_farEnough() {
+ doReturn(false).when(mSwipeHelper).isFalseGesture();
+ doReturn(true).when(mSwipeHelper).swipedFarEnough();
+ doReturn(false).when(mSwipeHelper).swipedFastEnough();
+ when(mCallback.canChildBeDismissedInDirection(any(), anyBoolean())).thenReturn(true);
+ when(mEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_UP);
+
+ assertTrue("Should be a dismissal", mSwipeHelper.isDismissGesture(mEvent));
+ verify(mSwipeHelper, times(1)).isFalseGesture();
+ }
+
+ @Test
+ public void testIsDismissGesture_notFarOrFastEnough() {
+ doReturn(false).when(mSwipeHelper).isFalseGesture();
+ doReturn(false).when(mSwipeHelper).swipedFarEnough();
+ doReturn(false).when(mSwipeHelper).swipedFastEnough();
+ when(mCallback.canChildBeDismissedInDirection(any(), anyBoolean())).thenReturn(true);
+ when(mEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_UP);
+
+ assertFalse("Should not be a dismissal", mSwipeHelper.isDismissGesture(mEvent));
+ verify(mSwipeHelper, times(1)).isFalseGesture();
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
index f568547d3b59..e680a4ec19d1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
@@ -53,7 +53,7 @@ import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.qs.AutoAddTracker;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.ReduceBrightColorsController;
import com.android.systemui.qs.SettingObserver;
import com.android.systemui.qs.external.CustomTile;
@@ -104,7 +104,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
private static final int USER = 0;
- @Mock private QSTileHost mQsTileHost;
+ @Mock private QSHost mQsHost;
@Mock private AutoAddTracker mAutoAddTracker;
@Mock private CastController mCastController;
@Mock private HotspotController mHotspotController;
@@ -144,7 +144,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
R.string.safety_quick_settings_tile_class, TEST_CUSTOM_SAFETY_CLASS);
when(mAutoAddTrackerBuilder.build()).thenReturn(mAutoAddTracker);
- when(mQsTileHost.getUserContext()).thenReturn(mUserContext);
+ when(mQsHost.getUserContext()).thenReturn(mUserContext);
when(mUserContext.getUser()).thenReturn(UserHandle.of(USER));
mPackageManager = Mockito.spy(mContext.getPackageManager());
when(mPackageManager.getPermissionControllerPackageName())
@@ -174,7 +174,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
WalletController walletController,
SafetyController safetyController,
@Named(RBC_AVAILABLE) boolean isReduceBrightColorsAvailable) {
- return new AutoTileManager(context, autoAddTrackerBuilder, mQsTileHost,
+ return new AutoTileManager(context, autoAddTrackerBuilder, mQsHost,
Handler.createAsync(TestableLooper.get(this).getLooper()),
mSecureSettings,
hotspotController,
@@ -359,7 +359,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
return;
}
mAutoTileManager.mNightDisplayCallback.onActivated(true);
- verify(mQsTileHost).addTile("night");
+ verify(mQsHost).addTile("night");
}
@Test
@@ -368,7 +368,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
return;
}
mAutoTileManager.mNightDisplayCallback.onActivated(false);
- verify(mQsTileHost, never()).addTile("night");
+ verify(mQsHost, never()).addTile("night");
}
@Test
@@ -378,7 +378,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
}
mAutoTileManager.mNightDisplayCallback.onAutoModeChanged(
ColorDisplayManager.AUTO_MODE_TWILIGHT);
- verify(mQsTileHost).addTile("night");
+ verify(mQsHost).addTile("night");
}
@Test
@@ -388,7 +388,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
}
mAutoTileManager.mNightDisplayCallback.onAutoModeChanged(
ColorDisplayManager.AUTO_MODE_CUSTOM_TIME);
- verify(mQsTileHost).addTile("night");
+ verify(mQsHost).addTile("night");
}
@Test
@@ -398,19 +398,19 @@ public class AutoTileManagerTest extends SysuiTestCase {
}
mAutoTileManager.mNightDisplayCallback.onAutoModeChanged(
ColorDisplayManager.AUTO_MODE_DISABLED);
- verify(mQsTileHost, never()).addTile("night");
+ verify(mQsHost, never()).addTile("night");
}
@Test
public void reduceBrightColorsTileAdded_whenActivated() {
mAutoTileManager.mReduceBrightColorsCallback.onActivated(true);
- verify(mQsTileHost).addTile("reduce_brightness");
+ verify(mQsHost).addTile("reduce_brightness");
}
@Test
public void reduceBrightColorsTileNotAdded_whenDeactivated() {
mAutoTileManager.mReduceBrightColorsCallback.onActivated(false);
- verify(mQsTileHost, never()).addTile("reduce_brightness");
+ verify(mQsHost, never()).addTile("reduce_brightness");
}
private static List<CastDevice> buildFakeCastDevice(boolean isCasting) {
@@ -423,28 +423,28 @@ public class AutoTileManagerTest extends SysuiTestCase {
public void castTileAdded_whenDeviceIsCasting() {
doReturn(buildFakeCastDevice(true)).when(mCastController).getCastDevices();
mAutoTileManager.mCastCallback.onCastDevicesChanged();
- verify(mQsTileHost).addTile("cast");
+ verify(mQsHost).addTile("cast");
}
@Test
public void castTileNotAdded_whenDeviceIsNotCasting() {
doReturn(buildFakeCastDevice(false)).when(mCastController).getCastDevices();
mAutoTileManager.mCastCallback.onCastDevicesChanged();
- verify(mQsTileHost, never()).addTile("cast");
+ verify(mQsHost, never()).addTile("cast");
}
@Test
public void testSettingTileAdded_onChanged() {
changeValue(TEST_SETTING, 1);
verify(mAutoAddTracker).setTileAdded(TEST_SPEC);
- verify(mQsTileHost).addTile(TEST_SPEC);
+ verify(mQsHost).addTile(TEST_SPEC);
}
@Test
public void testSettingTileAddedComponentAtEnd_onChanged() {
changeValue(TEST_SETTING_COMPONENT, 1);
verify(mAutoAddTracker).setTileAdded(TEST_CUSTOM_SPEC);
- verify(mQsTileHost).addTile(ComponentName.unflattenFromString(TEST_COMPONENT)
+ verify(mQsHost).addTile(ComponentName.unflattenFromString(TEST_COMPONENT)
, /* end */ true);
}
@@ -453,14 +453,14 @@ public class AutoTileManagerTest extends SysuiTestCase {
changeValue(TEST_SETTING, 1);
changeValue(TEST_SETTING, 2);
verify(mAutoAddTracker).setTileAdded(TEST_SPEC);
- verify(mQsTileHost).addTile(TEST_SPEC);
+ verify(mQsHost).addTile(TEST_SPEC);
}
@Test
public void testSettingTileNotAdded_onChangedTo0() {
changeValue(TEST_SETTING, 0);
verify(mAutoAddTracker, never()).setTileAdded(TEST_SPEC);
- verify(mQsTileHost, never()).addTile(TEST_SPEC);
+ verify(mQsHost, never()).addTile(TEST_SPEC);
}
@Test
@@ -469,27 +469,27 @@ public class AutoTileManagerTest extends SysuiTestCase {
changeValue(TEST_SETTING, 1);
verify(mAutoAddTracker, never()).setTileAdded(TEST_SPEC);
- verify(mQsTileHost, never()).addTile(TEST_SPEC);
+ verify(mQsHost, never()).addTile(TEST_SPEC);
}
@Test
public void testSafetyTileNotAdded_ifPreviouslyAdded() {
ComponentName safetyComponent = CustomTile.getComponentFromSpec(TEST_CUSTOM_SAFETY_SPEC);
mAutoTileManager.init();
- verify(mQsTileHost, times(1)).addTile(safetyComponent, true);
+ verify(mQsHost, times(1)).addTile(safetyComponent, true);
when(mAutoAddTracker.isAdded(TEST_CUSTOM_SAFETY_SPEC)).thenReturn(true);
mAutoTileManager.init();
- verify(mQsTileHost, times(1)).addTile(safetyComponent, true);
+ verify(mQsHost, times(1)).addTile(safetyComponent, true);
}
@Test
public void testSafetyTileAdded_onUserChange() {
ComponentName safetyComponent = CustomTile.getComponentFromSpec(TEST_CUSTOM_SAFETY_SPEC);
mAutoTileManager.init();
- verify(mQsTileHost, times(1)).addTile(safetyComponent, true);
+ verify(mQsHost, times(1)).addTile(safetyComponent, true);
when(mAutoAddTracker.isAdded(TEST_CUSTOM_SAFETY_SPEC)).thenReturn(false);
mAutoTileManager.changeUser(UserHandle.of(USER + 1));
- verify(mQsTileHost, times(2)).addTile(safetyComponent, true);
+ verify(mQsHost, times(2)).addTile(safetyComponent, true);
}
@Test
@@ -498,17 +498,17 @@ public class AutoTileManagerTest extends SysuiTestCase {
mAutoTileManager.init();
when(mAutoAddTracker.isAdded(TEST_CUSTOM_SAFETY_SPEC)).thenReturn(true);
mAutoTileManager.mSafetyCallback.onSafetyCenterEnableChanged(false);
- verify(mQsTileHost, times(1)).removeTile(TEST_CUSTOM_SAFETY_SPEC);
+ verify(mQsHost, times(1)).removeTile(TEST_CUSTOM_SAFETY_SPEC);
}
@Test
public void testSafetyTileAdded_onSafetyCenterEnable() {
ComponentName safetyComponent = CustomTile.getComponentFromSpec(TEST_CUSTOM_SAFETY_SPEC);
mAutoTileManager.init();
- verify(mQsTileHost, times(1)).addTile(safetyComponent, true);
+ verify(mQsHost, times(1)).addTile(safetyComponent, true);
mAutoTileManager.mSafetyCallback.onSafetyCenterEnableChanged(false);
mAutoTileManager.mSafetyCallback.onSafetyCenterEnableChanged(true);
- verify(mQsTileHost, times(2)).addTile(safetyComponent, true);
+ verify(mQsHost, times(2)).addTile(safetyComponent, true);
}
@Test
@@ -525,7 +525,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
mManagedProfileCallback.onManagedProfileChanged();
- verify(mQsTileHost, times(1)).addTile(eq("work"), eq(2));
+ verify(mQsHost, times(1)).addTile(eq("work"), eq(2));
verify(mAutoAddTracker, times(1)).setTileAdded(eq("work"));
}
@@ -542,7 +542,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
mManagedProfileCallback.onManagedProfileChanged();
- verify(mQsTileHost, times(1)).removeTile(eq("work"));
+ verify(mQsHost, times(1)).removeTile(eq("work"));
verify(mAutoAddTracker, times(1)).setTileRemoved(eq("work"));
}
@@ -550,7 +550,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
public void testAddControlsTileIfNotPresent() {
String spec = DEVICE_CONTROLS;
when(mAutoAddTracker.isAdded(eq(spec))).thenReturn(false);
- when(mQsTileHost.getTiles()).thenReturn(new ArrayList<>());
+ when(mQsHost.getTiles()).thenReturn(new ArrayList<>());
mAutoTileManager.init();
ArgumentCaptor<DeviceControlsController.Callback> captor =
@@ -559,7 +559,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
verify(mDeviceControlsController).setCallback(captor.capture());
captor.getValue().onControlsUpdate(3);
- verify(mQsTileHost).addTile(spec, 3);
+ verify(mQsHost).addTile(spec, 3);
verify(mAutoAddTracker).setTileAdded(spec);
}
@@ -567,7 +567,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
public void testDontAddControlsTileIfPresent() {
String spec = DEVICE_CONTROLS;
when(mAutoAddTracker.isAdded(eq(spec))).thenReturn(false);
- when(mQsTileHost.getTiles()).thenReturn(new ArrayList<>());
+ when(mQsHost.getTiles()).thenReturn(new ArrayList<>());
mAutoTileManager.init();
ArgumentCaptor<DeviceControlsController.Callback> captor =
@@ -576,7 +576,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
verify(mDeviceControlsController).setCallback(captor.capture());
captor.getValue().removeControlsAutoTracker();
- verify(mQsTileHost, never()).addTile(spec, 3);
+ verify(mQsHost, never()).addTile(spec, 3);
verify(mAutoAddTracker, never()).setTileAdded(spec);
verify(mAutoAddTracker).setTileRemoved(spec);
}
@@ -587,7 +587,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
when(mAutoAddTracker.isAdded(eq(spec))).thenReturn(true);
QSTile mockTile = mock(QSTile.class);
when(mockTile.getTileSpec()).thenReturn(spec);
- when(mQsTileHost.getTiles()).thenReturn(List.of(mockTile));
+ when(mQsHost.getTiles()).thenReturn(List.of(mockTile));
mAutoTileManager.init();
ArgumentCaptor<DeviceControlsController.Callback> captor =
@@ -596,7 +596,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
verify(mDeviceControlsController).setCallback(captor.capture());
captor.getValue().onControlsUpdate(3);
- verify(mQsTileHost, never()).addTile(spec, 3);
+ verify(mQsHost, never()).addTile(spec, 3);
verify(mAutoAddTracker, never()).setTileAdded(spec);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
index ec294b12a11a..68d67ca20007 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
@@ -517,6 +517,26 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
verify(mVibratorHelper).vibrateAuthError(anyString());
}
+ @Test
+ public void onFingerprintDetect_showBouncer() {
+ // WHEN fingerprint detect occurs
+ mBiometricUnlockController.onBiometricDetected(UserHandle.USER_CURRENT,
+ BiometricSourceType.FINGERPRINT, true /* isStrongBiometric */);
+
+ // THEN shows primary bouncer
+ verify(mStatusBarKeyguardViewManager).showPrimaryBouncer(anyBoolean());
+ }
+
+ @Test
+ public void onFaceDetect_showBouncer() {
+ // WHEN face detect occurs
+ mBiometricUnlockController.onBiometricDetected(UserHandle.USER_CURRENT,
+ BiometricSourceType.FACE, false /* isStrongBiometric */);
+
+ // THEN shows primary bouncer
+ verify(mStatusBarKeyguardViewManager).showPrimaryBouncer(anyBoolean());
+ }
+
private void givenFingerprintModeUnlockCollapsing() {
when(mUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
when(mUpdateMonitor.isDeviceInteractive()).thenReturn(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java
index 1e2fe35a3b6f..31a1e4f9a4d9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java
@@ -43,6 +43,7 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shade.CameraLauncher;
import com.android.systemui.shade.NotificationPanelViewController;
@@ -94,6 +95,7 @@ public class CentralSurfacesCommandQueueCallbacksTest extends SysuiTestCase {
@Mock private SystemBarAttributesListener mSystemBarAttributesListener;
@Mock private Lazy<CameraLauncher> mCameraLauncherLazy;
@Mock private UserTracker mUserTracker;
+ @Mock private QSHost mQSHost;
CentralSurfacesCommandQueueCallbacks mSbcqCallbacks;
@@ -128,7 +130,8 @@ public class CentralSurfacesCommandQueueCallbacksTest extends SysuiTestCase {
DEFAULT_DISPLAY,
mSystemBarAttributesListener,
mCameraLauncherLazy,
- mUserTracker);
+ mUserTracker,
+ mQSHost);
when(mUserTracker.getUserHandle()).thenReturn(
UserHandle.of(ActivityManager.getCurrentUser()));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
index 38e82281856f..c4ee32666d74 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
@@ -77,6 +77,8 @@ import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewRootImpl;
import android.view.WindowManager;
+import android.window.BackEvent;
+import android.window.OnBackAnimationCallback;
import android.window.OnBackInvokedCallback;
import android.window.OnBackInvokedDispatcher;
import android.window.WindowOnBackInvokedDispatcher;
@@ -114,6 +116,7 @@ import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.keyguard.ui.viewmodel.LightRevealScrimViewModel;
import com.android.systemui.navigationbar.NavigationBarController;
+import com.android.systemui.notetask.NoteTaskController;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.plugins.PluginDependencyProvider;
import com.android.systemui.plugins.PluginManager;
@@ -181,6 +184,8 @@ import com.android.systemui.volume.VolumeComponent;
import com.android.wm.shell.bubbles.Bubbles;
import com.android.wm.shell.startingsurface.StartingSurface;
+import dagger.Lazy;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -193,8 +198,6 @@ import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
import java.util.Optional;
-import dagger.Lazy;
-
@SmallTest
@RunWith(AndroidTestingRunner.class)
@RunWithLooper(setAsMainLooper = true)
@@ -259,6 +262,7 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
@Mock private StatusBarWindowStateController mStatusBarWindowStateController;
@Mock private UserSwitcherController mUserSwitcherController;
@Mock private Bubbles mBubbles;
+ @Mock private NoteTaskController mNoteTaskController;
@Mock private NotificationShadeWindowController mNotificationShadeWindowController;
@Mock private NotificationIconAreaController mNotificationIconAreaController;
@Mock private NotificationShadeWindowViewController mNotificationShadeWindowViewController;
@@ -331,6 +335,10 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
mFeatureFlags.set(Flags.WM_ENABLE_PREDICTIVE_BACK_SYSUI, false);
// Set default value to avoid IllegalStateException.
mFeatureFlags.set(Flags.SHORTCUT_LIST_SEARCH_LAYOUT, false);
+ // For the Shade to respond to Back gesture, we must enable the event routing
+ mFeatureFlags.set(Flags.WM_SHADE_ALLOW_BACK_GESTURE, true);
+ // For the Shade to animate during the Back gesture, we must enable the animation flag.
+ mFeatureFlags.set(Flags.WM_SHADE_ANIMATE_BACK_GESTURE, true);
IThermalService thermalService = mock(IThermalService.class);
mPowerManager = new PowerManager(mContext, mPowerManagerService, thermalService,
@@ -472,6 +480,7 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
mWakefulnessLifecycle,
mStatusBarStateController,
Optional.of(mBubbles),
+ () -> mNoteTaskController,
mDeviceProvisionedController,
mNavigationBarController,
mAccessibilityFloatingMenuController,
@@ -852,6 +861,50 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
verify(mShadeController).animateCollapseShade();
}
+ /**
+ * When back progress is at 100%, the onBackProgressed animation driver inside
+ * NotificationPanelViewController should be invoked appropriately (with 1.0f passed in).
+ */
+ @Test
+ public void testPredictiveBackAnimation_progressMaxScalesPanel() {
+ mCentralSurfaces.setNotificationShadeWindowViewController(
+ mNotificationShadeWindowViewController);
+ mCentralSurfaces.handleVisibleToUserChanged(true);
+ verify(mOnBackInvokedDispatcher).registerOnBackInvokedCallback(
+ eq(OnBackInvokedDispatcher.PRIORITY_DEFAULT),
+ mOnBackInvokedCallback.capture());
+
+ OnBackAnimationCallback onBackAnimationCallback =
+ (OnBackAnimationCallback) (mOnBackInvokedCallback.getValue());
+ when(mNotificationPanelViewController.canPanelBeCollapsed()).thenReturn(true);
+
+ BackEvent fakeSwipeInFromLeftEdge = new BackEvent(20.0f, 100.0f, 1.0f, BackEvent.EDGE_LEFT);
+ onBackAnimationCallback.onBackProgressed(fakeSwipeInFromLeftEdge);
+ verify(mNotificationPanelViewController).onBackProgressed(eq(1.0f));
+ }
+
+ /**
+ * When back progress is at 0%, the onBackProgressed animation driver inside
+ * NotificationPanelViewController should be invoked appropriately (with 0.0f passed in).
+ */
+ @Test
+ public void testPredictiveBackAnimation_progressMinScalesPanel() {
+ mCentralSurfaces.setNotificationShadeWindowViewController(
+ mNotificationShadeWindowViewController);
+ mCentralSurfaces.handleVisibleToUserChanged(true);
+ verify(mOnBackInvokedDispatcher).registerOnBackInvokedCallback(
+ eq(OnBackInvokedDispatcher.PRIORITY_DEFAULT),
+ mOnBackInvokedCallback.capture());
+
+ OnBackAnimationCallback onBackAnimationCallback =
+ (OnBackAnimationCallback) (mOnBackInvokedCallback.getValue());
+ when(mNotificationPanelViewController.canPanelBeCollapsed()).thenReturn(true);
+
+ BackEvent fakeSwipeInFromLeftEdge = new BackEvent(20.0f, 10.0f, 0.0f, BackEvent.EDGE_LEFT);
+ onBackAnimationCallback.onBackProgressed(fakeSwipeInFromLeftEdge);
+ verify(mNotificationPanelViewController).onBackProgressed(eq(0.0f));
+ }
+
@Test
public void testPanelOpenForHeadsUp() {
when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
@@ -1027,6 +1080,17 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
}
@Test
+ public void testSetDozingNotUnlocking_transitionToAuthScrimmed_cancelKeyguardFadingAway() {
+ when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
+ when(mKeyguardStateController.isKeyguardFadingAway()).thenReturn(true);
+
+ mCentralSurfaces.updateScrimController();
+
+ verify(mScrimController).transitionTo(eq(ScrimState.AUTH_SCRIMMED_SHADE));
+ verify(mStatusBarKeyguardViewManager).onKeyguardFadedAway();
+ }
+
+ @Test
public void testShowKeyguardImplementation_setsState() {
when(mLockscreenUserManager.getCurrentProfiles()).thenReturn(new SparseArray<>());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java
index 1582cee365d5..7d9c0913e15a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java
@@ -32,7 +32,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
-import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
+import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider;
import com.android.systemui.statusbar.window.StatusBarWindowController;
import com.android.wm.shell.bubbles.Bubbles;
@@ -62,7 +62,7 @@ public class NotificationIconAreaControllerTest extends SysuiTestCase {
@Mock
DozeParameters mDozeParameters;
@Mock
- CommonNotifCollection mNotifCollection;
+ SectionStyleProvider mSectionStyleProvider;
@Mock
DarkIconDispatcher mDarkIconDispatcher;
@Mock
@@ -87,6 +87,7 @@ public class NotificationIconAreaControllerTest extends SysuiTestCase {
mNotificationMediaManager,
mListener,
mDozeParameters,
+ mSectionStyleProvider,
Optional.of(mBubbles),
mDemoModeController,
mDarkIconDispatcher,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt
index 305b9fea7569..6b18169bcd86 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.phone
import android.app.AlarmManager
-import android.app.IActivityManager
import android.app.admin.DevicePolicyManager
import android.content.SharedPreferences
import android.os.UserManager
@@ -87,7 +86,6 @@ class PhoneStatusBarPolicyTest : SysuiTestCase() {
@Mock private lateinit var keyguardStateController: KeyguardStateController
@Mock private lateinit var locationController: LocationController
@Mock private lateinit var sensorPrivacyController: SensorPrivacyController
- @Mock private lateinit var iActivityManager: IActivityManager
@Mock private lateinit var alarmManager: AlarmManager
@Mock private lateinit var userManager: UserManager
@Mock private lateinit var userTracker: UserTracker
@@ -176,6 +174,7 @@ class PhoneStatusBarPolicyTest : SysuiTestCase() {
commandQueue,
broadcastDispatcher,
executor,
+ executor,
testableLooper.looper,
context.resources,
castController,
@@ -190,7 +189,6 @@ class PhoneStatusBarPolicyTest : SysuiTestCase() {
keyguardStateController,
locationController,
sensorPrivacyController,
- iActivityManager,
alarmManager,
userManager,
userTracker,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index c0537a6dc4cf..dc5a0472f49e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -1356,33 +1356,10 @@ public class ScrimControllerTest extends SysuiTestCase {
}
@Test
- public void notificationAlpha_unnocclusionAnimating_bouncerActive_usesKeyguardNotifAlpha() {
- when(mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit()).thenReturn(true);
- mScrimController.setClipsQsScrim(true);
-
- mScrimController.transitionTo(ScrimState.KEYGUARD);
- mScrimController.setUnocclusionAnimationRunning(true);
-
- assertAlphaAfterExpansion(
- mNotificationsScrim, ScrimState.KEYGUARD.getNotifAlpha(), /* expansion */ 0f);
- assertAlphaAfterExpansion(
- mNotificationsScrim, ScrimState.KEYGUARD.getNotifAlpha(), /* expansion */ 0.4f);
- assertAlphaAfterExpansion(
- mNotificationsScrim, ScrimState.KEYGUARD.getNotifAlpha(), /* expansion */ 1.0f);
-
- // Verify normal behavior after
- mScrimController.setUnocclusionAnimationRunning(false);
- float expansion = 0.4f;
- float alpha = 1 - BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion);
- assertAlphaAfterExpansion(mNotificationsScrim, alpha, expansion);
- }
-
- @Test
public void notificationAlpha_unnocclusionAnimating_bouncerNotActive_usesKeyguardNotifAlpha() {
when(mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit()).thenReturn(false);
mScrimController.transitionTo(ScrimState.KEYGUARD);
- mScrimController.setUnocclusionAnimationRunning(true);
assertAlphaAfterExpansion(
mNotificationsScrim, ScrimState.KEYGUARD.getNotifAlpha(), /* expansion */ 0f);
@@ -1392,7 +1369,6 @@ public class ScrimControllerTest extends SysuiTestCase {
mNotificationsScrim, ScrimState.KEYGUARD.getNotifAlpha(), /* expansion */ 1.0f);
// Verify normal behavior after
- mScrimController.setUnocclusionAnimationRunning(false);
float expansion = 0.4f;
float alpha = 1 - ShadeInterpolation.getNotificationScrimAlpha(expansion);
assertAlphaAfterExpansion(mNotificationsScrim, alpha, expansion);
@@ -1598,7 +1574,6 @@ public class ScrimControllerTest extends SysuiTestCase {
@Test
public void setUnOccludingAnimationKeyguard() {
- mScrimController.setUnocclusionAnimationRunning(true);
mScrimController.transitionTo(ScrimState.KEYGUARD);
finishAnimationsImmediately();
assertThat(mNotificationsScrim.getViewAlpha())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index d8446f4721b3..158e9adcff43 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -38,6 +38,8 @@ import android.testing.TestableLooper;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewRootImpl;
+import android.view.WindowInsets;
+import android.view.WindowInsetsController;
import android.window.BackEvent;
import android.window.OnBackAnimationCallback;
import android.window.OnBackInvokedCallback;
@@ -65,8 +67,10 @@ import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInt
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback;
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.navigationbar.NavigationModeController;
+import com.android.systemui.navigationbar.TaskbarDelegate;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.shade.NotificationPanelViewController;
+import com.android.systemui.shade.NotificationShadeWindowView;
import com.android.systemui.shade.ShadeController;
import com.android.systemui.shade.ShadeExpansionChangeEvent;
import com.android.systemui.shade.ShadeExpansionStateManager;
@@ -123,6 +127,9 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
@Mock private BouncerView mBouncerView;
@Mock private BouncerViewDelegate mBouncerViewDelegate;
@Mock private OnBackAnimationCallback mBouncerViewDelegateBackCallback;
+ @Mock private NotificationShadeWindowView mNotificationShadeWindowView;
+ @Mock private WindowInsetsController mWindowInsetsController;
+ @Mock private TaskbarDelegate mTaskbarDelegate;
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
private PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback
@@ -151,6 +158,11 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
.isEnabled(Flags.WM_ENABLE_PREDICTIVE_BACK_BOUNCER_ANIM))
.thenReturn(true);
+ when(mCentralSurfaces.getNotificationShadeWindowView())
+ .thenReturn(mNotificationShadeWindowView);
+ when(mNotificationShadeWindowView.getWindowInsetsController())
+ .thenReturn(mWindowInsetsController);
+
mStatusBarKeyguardViewManager =
new StatusBarKeyguardViewManager(
getContext(),
@@ -356,17 +368,6 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
}
@Test
- public void setOccluded_animatesPanelExpansion_onlyIfBouncerHidden() {
- mStatusBarKeyguardViewManager.setOccluded(false /* occluded */, true /* animated */);
- verify(mCentralSurfaces).animateKeyguardUnoccluding();
-
- when(mPrimaryBouncerInteractor.isFullyShowing()).thenReturn(true);
- clearInvocations(mCentralSurfaces);
- mStatusBarKeyguardViewManager.setOccluded(false /* occluded */, true /* animated */);
- verify(mCentralSurfaces, never()).animateKeyguardUnoccluding();
- }
-
- @Test
public void setOccluded_onKeyguardOccludedChangedCalled() {
clearInvocations(mKeyguardStateController);
clearInvocations(mKeyguardUpdateMonitor);
@@ -640,6 +641,14 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
}
@Test
+ public void testHideTaskbar() {
+ when(mTaskbarDelegate.isInitialized()).thenReturn(true);
+ mStatusBarKeyguardViewManager.setTaskbarDelegate(mTaskbarDelegate);
+ mStatusBarKeyguardViewManager.updateNavigationBarVisibility(false);
+ verify(mWindowInsetsController).hide(WindowInsets.Type.navigationBars());
+ }
+
+ @Test
public void hideAlternateBouncer_beforeCentralSurfacesRegistered() {
mStatusBarKeyguardViewManager =
new StatusBarKeyguardViewManager(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
index 85e8c341abb4..64545b16a2af 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
@@ -32,7 +32,6 @@ import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-import android.animation.Animator;
import android.app.Fragment;
import android.app.StatusBarManager;
import android.content.Context;
@@ -45,6 +44,7 @@ import android.view.View;
import android.view.ViewPropertyAnimator;
import android.widget.FrameLayout;
+import androidx.core.animation.Animator;
import androidx.test.filters.SmallTest;
import com.android.keyguard.KeyguardUpdateMonitor;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
index 00ce412f2a65..b072deedb9c9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
@@ -239,6 +239,7 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC
* list2 = [false, true]
* list3 = [a, b, c]
* ```
+ *
* We'll generate test cases for:
*
* Test (1, false, a) Test (2, false, a) Test (3, false, a) Test (1, true, a) Test (1,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/stylus/OWNERS b/packages/SystemUI/tests/src/com/android/systemui/stylus/OWNERS
index 7ccb316dbca5..0ec996be72de 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/stylus/OWNERS
+++ b/packages/SystemUI/tests/src/com/android/systemui/stylus/OWNERS
@@ -5,4 +5,6 @@ juliacr@google.com
madym@google.com
mgalhardo@google.com
petrcermak@google.com
+stevenckng@google.com
+tkachenkoi@google.com
vanjan@google.com \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusManagerTest.kt
index f8bf4b91e11a..4525ad27b749 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusManagerTest.kt
@@ -65,8 +65,6 @@ class StylusManagerTest : SysuiTestCase() {
@Mock lateinit var uiEventLogger: UiEventLogger
@Mock lateinit var stylusCallback: StylusManager.StylusCallback
@Mock lateinit var otherStylusCallback: StylusManager.StylusCallback
- @Mock lateinit var stylusBatteryCallback: StylusManager.StylusBatteryCallback
- @Mock lateinit var otherStylusBatteryCallback: StylusManager.StylusBatteryCallback
private lateinit var mockitoSession: StaticMockitoSession
private lateinit var stylusManager: StylusManager
@@ -123,7 +121,6 @@ class StylusManagerTest : SysuiTestCase() {
stylusManager.startListener()
stylusManager.registerCallback(stylusCallback)
- stylusManager.registerBatteryCallback(stylusBatteryCallback)
clearInvocations(inputManager)
}
@@ -434,23 +431,6 @@ class StylusManagerTest : SysuiTestCase() {
}
@Test
- fun onMetadataChanged_multipleRegisteredBatteryCallbacks_executesAll() {
- stylusManager.onInputDeviceAdded(BT_STYLUS_DEVICE_ID)
- stylusManager.registerBatteryCallback(otherStylusBatteryCallback)
-
- stylusManager.onMetadataChanged(
- bluetoothDevice,
- BluetoothDevice.METADATA_MAIN_CHARGING,
- "true".toByteArray()
- )
-
- verify(stylusBatteryCallback, times(1))
- .onStylusBluetoothChargingStateChanged(BT_STYLUS_DEVICE_ID, bluetoothDevice, true)
- verify(otherStylusBatteryCallback, times(1))
- .onStylusBluetoothChargingStateChanged(BT_STYLUS_DEVICE_ID, bluetoothDevice, true)
- }
-
- @Test
fun onMetadataChanged_chargingStateTrue_executesBatteryCallbacks() {
stylusManager.onInputDeviceAdded(BT_STYLUS_DEVICE_ID)
@@ -460,7 +440,7 @@ class StylusManagerTest : SysuiTestCase() {
"true".toByteArray()
)
- verify(stylusBatteryCallback, times(1))
+ verify(stylusCallback, times(1))
.onStylusBluetoothChargingStateChanged(BT_STYLUS_DEVICE_ID, bluetoothDevice, true)
}
@@ -474,7 +454,7 @@ class StylusManagerTest : SysuiTestCase() {
"false".toByteArray()
)
- verify(stylusBatteryCallback, times(1))
+ verify(stylusCallback, times(1))
.onStylusBluetoothChargingStateChanged(BT_STYLUS_DEVICE_ID, bluetoothDevice, false)
}
@@ -486,7 +466,7 @@ class StylusManagerTest : SysuiTestCase() {
"true".toByteArray()
)
- verifyNoMoreInteractions(stylusBatteryCallback)
+ verifyNoMoreInteractions(stylusCallback)
}
@Test
@@ -499,8 +479,7 @@ class StylusManagerTest : SysuiTestCase() {
"true".toByteArray()
)
- verify(stylusBatteryCallback, never())
- .onStylusBluetoothChargingStateChanged(any(), any(), any())
+ verify(stylusCallback, never()).onStylusBluetoothChargingStateChanged(any(), any(), any())
}
@Test
@@ -614,7 +593,7 @@ class StylusManagerTest : SysuiTestCase() {
fun onBatteryStateChanged_executesBatteryCallbacks() {
stylusManager.onBatteryStateChanged(STYLUS_DEVICE_ID, 1, batteryState)
- verify(stylusBatteryCallback, times(1))
+ verify(stylusCallback, times(1))
.onStylusUsiBatteryStateChanged(STYLUS_DEVICE_ID, 1, batteryState)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerStartableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerStartableTest.kt
index 82b80f53d6b0..3db0ecc4e8df 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerStartableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerStartableTest.kt
@@ -96,7 +96,6 @@ class StylusUsiPowerStartableTest : SysuiTestCase() {
startable.start()
verify(stylusManager, times(1)).registerCallback(startable)
- verify(stylusManager, times(1)).registerBatteryCallback(startable)
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt
index 5288608a202d..0413d92b6abb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt
@@ -25,7 +25,6 @@ import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_FULL_OPEN
import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_HALF_OPEN
import com.android.systemui.unfold.updates.FOLD_UPDATE_START_CLOSING
import com.android.systemui.unfold.updates.FOLD_UPDATE_START_OPENING
-import com.android.systemui.unfold.updates.FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE
import com.android.systemui.unfold.util.TestFoldStateProvider
import org.junit.Before
import org.junit.Test
@@ -50,7 +49,7 @@ class PhysicsBasedUnfoldTransitionProgressProviderTest : SysuiTestCase() {
runOnMainThreadWithInterval(
{ foldStateProvider.sendFoldUpdate(FOLD_UPDATE_START_OPENING) },
{ foldStateProvider.sendHingeAngleUpdate(10f) },
- { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) },
+ { foldStateProvider.sendUnfoldedScreenAvailable() },
{ foldStateProvider.sendHingeAngleUpdate(90f) },
{ foldStateProvider.sendHingeAngleUpdate(180f) },
{ foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN) },
@@ -67,7 +66,7 @@ class PhysicsBasedUnfoldTransitionProgressProviderTest : SysuiTestCase() {
runOnMainThreadWithInterval(
{ foldStateProvider.sendFoldUpdate(FOLD_UPDATE_START_OPENING) },
{ foldStateProvider.sendHingeAngleUpdate(10f) },
- { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) },
+ { foldStateProvider.sendUnfoldedScreenAvailable() },
{ foldStateProvider.sendHingeAngleUpdate(90f) },
{ foldStateProvider.sendHingeAngleUpdate(180f) },
{ foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN) },
@@ -84,7 +83,7 @@ class PhysicsBasedUnfoldTransitionProgressProviderTest : SysuiTestCase() {
{ foldStateProvider.sendHingeAngleUpdate(90f) },
{ foldStateProvider.sendHingeAngleUpdate(180f) },
{ foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN) },
- { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) },
+ { foldStateProvider.sendUnfoldedScreenAvailable() },
)
with(listener.ensureTransitionFinished()) {
@@ -113,7 +112,7 @@ class PhysicsBasedUnfoldTransitionProgressProviderTest : SysuiTestCase() {
fun testUnfoldAndStopUnfolding_finishesTheUnfoldTransition() {
runOnMainThreadWithInterval(
{ foldStateProvider.sendFoldUpdate(FOLD_UPDATE_START_OPENING) },
- { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) },
+ { foldStateProvider.sendUnfoldedScreenAvailable() },
{ foldStateProvider.sendHingeAngleUpdate(10f) },
{ foldStateProvider.sendHingeAngleUpdate(90f) },
{ foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_HALF_OPEN) },
@@ -129,7 +128,7 @@ class PhysicsBasedUnfoldTransitionProgressProviderTest : SysuiTestCase() {
fun testFoldImmediatelyAfterUnfold_runsFoldAnimation() {
runOnMainThreadWithInterval(
{ foldStateProvider.sendFoldUpdate(FOLD_UPDATE_START_OPENING) },
- { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) },
+ { foldStateProvider.sendUnfoldedScreenAvailable() },
{ foldStateProvider.sendHingeAngleUpdate(10f) },
{ foldStateProvider.sendHingeAngleUpdate(90f) },
{
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt
index 6086e16fb49a..8476d0d45603 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt
@@ -26,6 +26,7 @@ import com.android.systemui.unfold.config.UnfoldTransitionConfig
import com.android.systemui.unfold.system.ActivityManagerActivityTypeProvider
import com.android.systemui.unfold.updates.FoldProvider.FoldCallback
import com.android.systemui.unfold.updates.RotationChangeProvider.RotationListener
+import com.android.systemui.unfold.updates.hinge.FULLY_OPEN_DEGREES
import com.android.systemui.unfold.updates.hinge.HingeAngleProvider
import com.android.systemui.unfold.updates.screen.ScreenStatusProvider
import com.android.systemui.unfold.updates.screen.ScreenStatusProvider.ScreenListener
@@ -71,6 +72,7 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
private val foldUpdates: MutableList<Int> = arrayListOf()
private val hingeAngleUpdates: MutableList<Float> = arrayListOf()
+ private val unfoldedScreenAvailabilityUpdates: MutableList<Unit> = arrayListOf()
private var scheduledRunnable: Runnable? = null
private var scheduledRunnableDelay: Long? = null
@@ -106,6 +108,10 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
override fun onFoldUpdate(update: Int) {
foldUpdates.add(update)
}
+
+ override fun onUnfoldedScreenAvailable() {
+ unfoldedScreenAvailabilityUpdates.add(Unit)
+ }
})
foldStateProvider.start()
@@ -156,8 +162,8 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
sendHingeAngleEvent(10)
screenOnStatusProvider.notifyScreenTurnedOn()
- assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_OPENING,
- FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE)
+ assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_OPENING)
+ assertThat(unfoldedScreenAvailabilityUpdates).hasSize(1)
}
@Test
@@ -174,8 +180,9 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
sendHingeAngleEvent(40)
sendHingeAngleEvent(10)
- assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_OPENING,
- FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE, FOLD_UPDATE_START_CLOSING)
+ assertThat(foldUpdates)
+ .containsExactly(FOLD_UPDATE_START_OPENING, FOLD_UPDATE_START_CLOSING)
+ assertThat(unfoldedScreenAvailabilityUpdates).hasSize(1)
}
@Test
@@ -223,7 +230,7 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
fireScreenOnEvent()
- assertThat(foldUpdates).containsExactly(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE)
+ assertThat(unfoldedScreenAvailabilityUpdates).hasSize(1)
}
@Test
@@ -277,7 +284,7 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
@Test
fun startClosingEvent_afterTimeout_finishHalfOpenEventEmitted() {
- sendHingeAngleEvent(90)
+ setInitialHingeAngle(90)
sendHingeAngleEvent(80)
simulateTimeout(HALF_OPENED_TIMEOUT_MILLIS)
@@ -288,7 +295,7 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
@Test
fun startClosingEvent_beforeTimeout_abortNotEmitted() {
- sendHingeAngleEvent(90)
+ setInitialHingeAngle(90)
sendHingeAngleEvent(80)
simulateTimeout(HALF_OPENED_TIMEOUT_MILLIS - 1)
@@ -298,7 +305,7 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
@Test
fun startClosingEvent_eventBeforeTimeout_oneEventEmitted() {
- sendHingeAngleEvent(180)
+ setInitialHingeAngle(180)
sendHingeAngleEvent(90)
simulateTimeout(HALF_OPENED_TIMEOUT_MILLIS - 1)
@@ -309,7 +316,7 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
@Test
fun startClosingEvent_timeoutAfterTimeoutRescheduled_finishHalfOpenStateEmitted() {
- sendHingeAngleEvent(180)
+ setInitialHingeAngle(180)
sendHingeAngleEvent(90)
// The timeout should not trigger here.
@@ -323,7 +330,7 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
@Test
fun startClosingEvent_shortTimeBetween_emitsOnlyOneEvents() {
- sendHingeAngleEvent(180)
+ setInitialHingeAngle(180)
sendHingeAngleEvent(90)
sendHingeAngleEvent(80)
@@ -334,20 +341,19 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
@Test
fun startClosingEvent_whileClosing_emittedDespiteInitialAngle() {
val maxAngle = 180 - FULLY_OPEN_THRESHOLD_DEGREES.toInt()
- for (i in 1..maxAngle) {
- foldUpdates.clear()
-
- simulateFolding(startAngle = i)
+ val minAngle = Math.ceil(HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES.toDouble()).toInt() + 1
+ for (startAngle in minAngle..maxAngle) {
+ setInitialHingeAngle(startAngle)
+ sendHingeAngleEvent(startAngle - HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES.toInt() - 1)
assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
- simulateTimeout() // Timeout to set the state to aborted.
}
}
@Test
fun startClosingEvent_whileNotOnLauncher_doesNotTriggerBeforeThreshold() {
setupForegroundActivityType(isHomeActivity = false)
- sendHingeAngleEvent(180)
+ setInitialHingeAngle(180)
sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
@@ -357,7 +363,7 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
@Test
fun startClosingEvent_whileActivityTypeNotAvailable_triggerBeforeThreshold() {
setupForegroundActivityType(isHomeActivity = null)
- sendHingeAngleEvent(180)
+ setInitialHingeAngle(180)
sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
@@ -367,7 +373,7 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
@Test
fun startClosingEvent_whileOnLauncher_doesTriggerBeforeThreshold() {
setupForegroundActivityType(isHomeActivity = true)
- sendHingeAngleEvent(180)
+ setInitialHingeAngle(180)
sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
@@ -377,9 +383,11 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
@Test
fun startClosingEvent_whileNotOnLauncher_triggersAfterThreshold() {
setupForegroundActivityType(isHomeActivity = false)
- sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES)
+ setInitialHingeAngle(START_CLOSING_ON_APPS_THRESHOLD_DEGREES)
- sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES - 1)
+ sendHingeAngleEvent(
+ START_CLOSING_ON_APPS_THRESHOLD_DEGREES -
+ HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES.toInt() - 1)
assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
}
@@ -388,7 +396,7 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
fun startClosingEvent_whileNotOnKeyguardAndNotOnLauncher_doesNotTriggerBeforeThreshold() {
setKeyguardVisibility(visible = false)
setupForegroundActivityType(isHomeActivity = false)
- sendHingeAngleEvent(180)
+ setInitialHingeAngle(180)
sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
@@ -398,7 +406,7 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
@Test
fun startClosingEvent_whileKeyguardStateNotAvailable_triggerBeforeThreshold() {
setKeyguardVisibility(visible = null)
- sendHingeAngleEvent(180)
+ setInitialHingeAngle(180)
sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
@@ -408,7 +416,7 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
@Test
fun startClosingEvent_whileonKeyguard_doesTriggerBeforeThreshold() {
setKeyguardVisibility(visible = true)
- sendHingeAngleEvent(180)
+ setInitialHingeAngle(180)
sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
@@ -418,9 +426,59 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
@Test
fun startClosingEvent_whileNotOnKeyguard_triggersAfterThreshold() {
setKeyguardVisibility(visible = false)
- sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES)
+ setInitialHingeAngle(START_CLOSING_ON_APPS_THRESHOLD_DEGREES)
- sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES - 1)
+ sendHingeAngleEvent(
+ START_CLOSING_ON_APPS_THRESHOLD_DEGREES -
+ HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES.toInt() - 1)
+
+ assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
+ }
+
+ @Test
+ fun startClosingEvent_doesNotTriggerBelowThreshold() {
+ val thresholdAngle = (FULLY_OPEN_DEGREES - FULLY_OPEN_THRESHOLD_DEGREES).toInt()
+ setInitialHingeAngle(180)
+ sendHingeAngleEvent(thresholdAngle + 1)
+
+ assertThat(foldUpdates).isEmpty()
+ }
+
+ @Test
+ fun startClosingEvent_triggersAfterThreshold() {
+ val thresholdAngle = (FULLY_OPEN_DEGREES - FULLY_OPEN_THRESHOLD_DEGREES).toInt()
+ setInitialHingeAngle(180)
+ sendHingeAngleEvent(thresholdAngle + 1)
+ sendHingeAngleEvent(thresholdAngle - 1)
+
+ assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
+ }
+
+ @Test
+ fun startClosingEvent_triggersAfterThreshold_fromHalfOpen() {
+ setInitialHingeAngle(120)
+ sendHingeAngleEvent((120 - HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES + 1).toInt())
+ assertThat(foldUpdates).isEmpty()
+ sendHingeAngleEvent((120 - HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES - 1).toInt())
+
+ assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
+ }
+
+ @Test
+ fun startOpeningAndClosingEvents_triggerWithOpenAndClose() {
+ setInitialHingeAngle(120)
+ sendHingeAngleEvent(130)
+ sendHingeAngleEvent(120)
+ assertThat(foldUpdates)
+ .containsExactly(FOLD_UPDATE_START_OPENING, FOLD_UPDATE_START_CLOSING)
+ }
+
+ @Test
+ fun startClosingEvent_notInterrupted_whenAngleIsSlightlyIncreased() {
+ setInitialHingeAngle(120)
+ sendHingeAngleEvent(110)
+ sendHingeAngleEvent(111)
+ sendHingeAngleEvent(100)
assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
}
@@ -504,11 +562,6 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
}
}
- private fun simulateFolding(startAngle: Int) {
- sendHingeAngleEvent(startAngle)
- sendHingeAngleEvent(startAngle - 1)
- }
-
private fun setFoldState(folded: Boolean) {
foldProvider.notifyFolded(folded)
}
@@ -521,6 +574,17 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
testHingeAngleProvider.notifyAngle(angle.toFloat())
}
+ private fun setInitialHingeAngle(angle: Int) {
+ setFoldState(angle == 0)
+ sendHingeAngleEvent(angle)
+ if (scheduledRunnableDelay != null) {
+ simulateTimeout()
+ }
+ hingeAngleUpdates.clear()
+ foldUpdates.clear()
+ unfoldedScreenAvailabilityUpdates.clear()
+ }
+
private class TestFoldProvider : FoldProvider {
private val callbacks = arrayListOf<FoldCallback>()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt
index a064e8c81076..fbb0e5a72cd1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt
@@ -57,4 +57,8 @@ class TestFoldStateProvider : FoldStateProvider {
fun sendHingeAngleUpdate(angle: Float) {
listeners.forEach { it.onHingeAngleUpdate(angle) }
}
+
+ fun sendUnfoldedScreenAvailable() {
+ listeners.forEach { it.onUnfoldedScreenAvailable() }
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt
index 9312643a1453..e2f3cf7e085f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt
@@ -17,10 +17,7 @@
package com.android.systemui.user.data.repository
-import android.app.IActivityManager
-import android.app.UserSwitchObserver
import android.content.pm.UserInfo
-import android.os.IRemoteCallback
import android.os.UserHandle
import android.os.UserManager
import android.provider.Settings
@@ -44,14 +41,8 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
-import org.mockito.ArgumentCaptor
-import org.mockito.Captor
import org.mockito.Mock
-import org.mockito.Mockito.any
-import org.mockito.Mockito.anyString
import org.mockito.Mockito.mock
-import org.mockito.Mockito.times
-import org.mockito.Mockito.verify
import org.mockito.Mockito.`when` as whenever
import org.mockito.MockitoAnnotations
@@ -60,8 +51,6 @@ import org.mockito.MockitoAnnotations
class UserRepositoryImplTest : SysuiTestCase() {
@Mock private lateinit var manager: UserManager
- @Mock private lateinit var activityManager: IActivityManager
- @Captor private lateinit var userSwitchObserver: ArgumentCaptor<UserSwitchObserver>
private lateinit var underTest: UserRepositoryImpl
@@ -235,30 +224,31 @@ class UserRepositoryImplTest : SysuiTestCase() {
}
@Test
- fun userSwitchingInProgress_registersOnlyOneUserSwitchObserver() = runSelfCancelingTest {
+ fun userSwitchingInProgress_registersUserTrackerCallback() = runSelfCancelingTest {
underTest = create(this)
underTest.userSwitchingInProgress.launchIn(this)
underTest.userSwitchingInProgress.launchIn(this)
underTest.userSwitchingInProgress.launchIn(this)
- verify(activityManager, times(1)).registerUserSwitchObserver(any(), anyString())
+ // Two callbacks registered - one for observing user switching and one for observing the
+ // selected user
+ assertThat(tracker.callbacks.size).isEqualTo(2)
}
@Test
- fun userSwitchingInProgress_propagatesStateFromActivityManager() = runSelfCancelingTest {
+ fun userSwitchingInProgress_propagatesStateFromUserTracker() = runSelfCancelingTest {
underTest = create(this)
- verify(activityManager)
- .registerUserSwitchObserver(userSwitchObserver.capture(), anyString())
+ assertThat(tracker.callbacks.size).isEqualTo(2)
- userSwitchObserver.value.onUserSwitching(0, mock(IRemoteCallback::class.java))
+ tracker.onUserChanging(0)
var mostRecentSwitchingValue = false
underTest.userSwitchingInProgress.onEach { mostRecentSwitchingValue = it }.launchIn(this)
assertThat(mostRecentSwitchingValue).isTrue()
- userSwitchObserver.value.onUserSwitchComplete(0)
+ tracker.onUserChanged(0)
assertThat(mostRecentSwitchingValue).isFalse()
}
@@ -338,7 +328,6 @@ class UserRepositoryImplTest : SysuiTestCase() {
backgroundDispatcher = IMMEDIATE,
globalSettings = globalSettings,
tracker = tracker,
- activityManager = activityManager,
featureFlags = featureFlags,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/coroutines/Flow.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/coroutines/Flow.kt
index 9b4f4969f9e9..c2947b42f56d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/coroutines/Flow.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/coroutines/Flow.kt
@@ -29,6 +29,7 @@ import kotlinx.coroutines.test.runCurrent
/**
* Collect [flow] in a new [Job] and return a getter for the last collected value.
+ *
* ```
* fun myTest() = runTest {
* // ...
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeBiometricSettingsRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeBiometricSettingsRepository.kt
index 01dac362432d..d4b1701892c7 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeBiometricSettingsRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeBiometricSettingsRepository.kt
@@ -21,6 +21,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.flowOf
class FakeBiometricSettingsRepository : BiometricSettingsRepository {
@@ -42,6 +43,9 @@ class FakeBiometricSettingsRepository : BiometricSettingsRepository {
override val isFingerprintEnabledByDevicePolicy =
_isFingerprintEnabledByDevicePolicy.asStateFlow()
+ override val isFaceAuthSupportedInCurrentPosture: Flow<Boolean>
+ get() = flowOf(true)
+
fun setFingerprintEnrolled(isFingerprintEnrolled: Boolean) {
_isFingerprintEnrolled.value = isFingerprintEnrolled
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDevicePostureRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDevicePostureRepository.kt
new file mode 100644
index 000000000000..914c786a1c7f
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDevicePostureRepository.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2023 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.keyguard.data.repository
+
+import com.android.systemui.keyguard.shared.model.DevicePosture
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+
+class FakeDevicePostureRepository : DevicePostureRepository {
+ private val _currentDevicePosture = MutableStateFlow(DevicePosture.UNKNOWN)
+ override val currentDevicePosture: Flow<DevicePosture>
+ get() = _currentDevicePosture
+
+ fun setCurrentPosture(posture: DevicePosture) {
+ _currentDevicePosture.value = posture
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt
index 251014fc50b3..4242c1635468 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt
@@ -22,6 +22,7 @@ import android.content.pm.UserInfo
import android.os.UserHandle
import android.test.mock.MockContentResolver
import com.android.systemui.util.mockito.mock
+import java.util.concurrent.CountDownLatch
import java.util.concurrent.Executor
/** A fake [UserTracker] to be used in tests. */
@@ -66,11 +67,19 @@ class FakeUserTracker(
_userId = _userInfo.id
_userHandle = UserHandle.of(_userId)
+ onUserChanging()
+ onUserChanged()
+ }
+
+ fun onUserChanging(userId: Int = _userId) {
+ val copy = callbacks.toList()
+ val latch = CountDownLatch(copy.size)
+ copy.forEach { it.onUserChanging(userId, userContext, latch) }
+ }
+
+ fun onUserChanged(userId: Int = _userId) {
val copy = callbacks.toList()
- copy.forEach {
- it.onUserChanging(_userId, userContext)
- it.onUserChanged(_userId, userContext)
- }
+ copy.forEach { it.onUserChanged(userId, userContext) }
}
fun onProfileChanged() {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/util/FakeSystemUIDialogController.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/util/FakeSystemUIDialogController.kt
new file mode 100644
index 000000000000..0c9ce0f145f1
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/util/FakeSystemUIDialogController.kt
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2023 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.util
+
+import android.content.DialogInterface
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import org.mockito.ArgumentCaptor
+import org.mockito.Mockito.doAnswer
+import org.mockito.Mockito.verify
+import org.mockito.stubbing.Stubber
+
+class FakeSystemUIDialogController {
+
+ val dialog: SystemUIDialog = mock()
+
+ private val clickListeners: MutableMap<Int, DialogInterface.OnClickListener> = mutableMapOf()
+
+ init {
+ saveListener(DialogInterface.BUTTON_POSITIVE)
+ .whenever(dialog)
+ .setPositiveButton(any(), any())
+ saveListener(DialogInterface.BUTTON_POSITIVE)
+ .whenever(dialog)
+ .setPositiveButton(any(), any(), any())
+
+ saveListener(DialogInterface.BUTTON_NEGATIVE)
+ .whenever(dialog)
+ .setNegativeButton(any(), any())
+ saveListener(DialogInterface.BUTTON_NEGATIVE)
+ .whenever(dialog)
+ .setNegativeButton(any(), any(), any())
+
+ saveListener(DialogInterface.BUTTON_NEUTRAL).whenever(dialog).setNeutralButton(any(), any())
+ saveListener(DialogInterface.BUTTON_NEUTRAL)
+ .whenever(dialog)
+ .setNeutralButton(any(), any(), any())
+ }
+
+ fun clickNegative() {
+ performClick(DialogInterface.BUTTON_NEGATIVE, "This dialog has no negative button")
+ }
+
+ fun clickPositive() {
+ performClick(DialogInterface.BUTTON_POSITIVE, "This dialog has no positive button")
+ }
+
+ fun clickNeutral() {
+ performClick(DialogInterface.BUTTON_NEUTRAL, "This dialog has no neutral button")
+ }
+
+ fun cancel() {
+ val captor = ArgumentCaptor.forClass(DialogInterface.OnCancelListener::class.java)
+ verify(dialog).setOnCancelListener(captor.capture())
+ captor.value.onCancel(dialog)
+ }
+
+ private fun performClick(which: Int, errorMessage: String) {
+ clickListeners
+ .getOrElse(which) { throw IllegalAccessException(errorMessage) }
+ .onClick(dialog, which)
+ }
+
+ private fun saveListener(which: Int): Stubber = doAnswer {
+ val listener = it.getArgument<DialogInterface.OnClickListener>(1)
+ clickListeners[which] = listener
+ Unit
+ }
+}
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt
index 4622464b204d..c437e5c23d1b 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt
@@ -21,7 +21,6 @@ import android.util.FloatProperty
import com.android.systemui.unfold.UnfoldTransitionProgressProvider
import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_CLOSED
-import com.android.systemui.unfold.updates.FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE
import com.android.systemui.unfold.updates.FoldStateProvider
import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdate
import javax.inject.Inject
@@ -59,12 +58,15 @@ constructor(private val foldStateProvider: FoldStateProvider) :
}
override fun onFoldUpdate(@FoldUpdate update: Int) {
- when (update) {
- FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE -> animator.start()
- FOLD_UPDATE_FINISH_CLOSED -> animator.cancel()
+ if (update == FOLD_UPDATE_FINISH_CLOSED) {
+ animator.cancel()
}
}
+ override fun onUnfoldedScreenAvailable() {
+ animator.start()
+ }
+
override fun addCallback(listener: TransitionProgressListener) {
listeners.add(listener)
}
@@ -73,8 +75,6 @@ constructor(private val foldStateProvider: FoldStateProvider) :
listeners.remove(listener)
}
- override fun onHingeAngleUpdate(angle: Float) {}
-
private object AnimationProgressProperty :
FloatProperty<FixedTimingTransitionProgressProvider>("animation_progress") {
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
index 6ffbe5aa25c0..d19b414cb963 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
@@ -28,7 +28,6 @@ import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_CLOSED
import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_FULL_OPEN
import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_HALF_OPEN
import com.android.systemui.unfold.updates.FOLD_UPDATE_START_CLOSING
-import com.android.systemui.unfold.updates.FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE
import com.android.systemui.unfold.updates.FoldStateProvider
import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdate
import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdatesListener
@@ -78,21 +77,11 @@ class PhysicsBasedUnfoldTransitionProgressProvider @Inject constructor(
override fun onFoldUpdate(@FoldUpdate update: Int) {
when (update) {
- FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE -> {
- startTransition(startValue = 0f)
-
- // Stop the animation if the device has already opened by the time when
- // the display is available as we won't receive the full open event anymore
- if (foldStateProvider.isFinishedOpening) {
- cancelTransition(endValue = 1f, animate = true)
- }
- }
FOLD_UPDATE_FINISH_FULL_OPEN, FOLD_UPDATE_FINISH_HALF_OPEN -> {
// Do not cancel if we haven't started the transition yet.
// This could happen when we fully unfolded the device before the screen
// became available. In this case we start and immediately cancel the animation
- // in FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE event handler, so we don't need to
- // cancel it here.
+ // in onUnfoldedScreenAvailable event handler, so we don't need to cancel it here.
if (isTransitionRunning) {
cancelTransition(endValue = 1f, animate = true)
}
@@ -125,6 +114,16 @@ class PhysicsBasedUnfoldTransitionProgressProvider @Inject constructor(
}
}
+ override fun onUnfoldedScreenAvailable() {
+ startTransition(startValue = 0f)
+
+ // Stop the animation if the device has already opened by the time when
+ // the display is available as we won't receive the full open event anymore
+ if (foldStateProvider.isFinishedOpening) {
+ cancelTransition(endValue = 1f, animate = true)
+ }
+ }
+
private fun cancelTransition(endValue: Float, animate: Boolean) {
if (isTransitionRunning && animate) {
if (endValue == 1.0f && !isAnimatedCancelRunning) {
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
index 97c9ba99f096..82fd2258120a 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
@@ -54,6 +54,7 @@ constructor(
@FoldUpdate private var lastFoldUpdate: Int? = null
@FloatRange(from = 0.0, to = 180.0) private var lastHingeAngle: Float = 0f
+ @FloatRange(from = 0.0, to = 180.0) private var lastHingeAngleBeforeTransition: Float = 0f
private val hingeAngleListener = HingeAngleListener()
private val screenListener = ScreenStatusListener()
@@ -112,29 +113,45 @@ constructor(
private fun onHingeAngle(angle: Float) {
if (DEBUG) {
- Log.d(TAG, "Hinge angle: $angle, lastHingeAngle: $lastHingeAngle")
+ Log.d(
+ TAG,
+ "Hinge angle: $angle, " +
+ "lastHingeAngle: $lastHingeAngle, " +
+ "lastHingeAngleBeforeTransition: $lastHingeAngleBeforeTransition"
+ )
Trace.traceCounter(Trace.TRACE_TAG_APP, "hinge_angle", angle.toInt())
}
- val isClosing = angle < lastHingeAngle
+ val currentDirection =
+ if (angle < lastHingeAngle) FOLD_UPDATE_START_CLOSING else FOLD_UPDATE_START_OPENING
+ if (isTransitionInProgress && currentDirection != lastFoldUpdate) {
+ lastHingeAngleBeforeTransition = lastHingeAngle
+ }
+
+ val isClosing = angle < lastHingeAngleBeforeTransition
+ val transitionUpdate =
+ if (isClosing) FOLD_UPDATE_START_CLOSING else FOLD_UPDATE_START_OPENING
+ val angleChangeSurpassedThreshold =
+ Math.abs(angle - lastHingeAngleBeforeTransition) > HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES
val isFullyOpened = FULLY_OPEN_DEGREES - angle < FULLY_OPEN_THRESHOLD_DEGREES
- val closingEventDispatched = lastFoldUpdate == FOLD_UPDATE_START_CLOSING
+ val eventNotAlreadyDispatched = lastFoldUpdate != transitionUpdate
val screenAvailableEventSent = isUnfoldHandled
- if (isClosing // hinge angle should be decreasing since last update
- && !closingEventDispatched // we haven't sent closing event already
- && !isFullyOpened // do not send closing event if we are in fully opened hinge
+ if (
+ angleChangeSurpassedThreshold && // Do not react immediately to small changes in angle
+ eventNotAlreadyDispatched && // we haven't sent transition event already
+ !isFullyOpened && // do not send transition event if we are in fully opened hinge
// angle range as closing threshold could overlap this range
- && screenAvailableEventSent // do not send closing event if we are still in
- // the process of turning on the inner display
- && isClosingThresholdMet(angle) // hinge angle is below certain threshold.
+ screenAvailableEventSent && // do not send transition event if we are still in the
+ // process of turning on the inner display
+ isClosingThresholdMet(angle) // hinge angle is below certain threshold.
) {
- notifyFoldUpdate(FOLD_UPDATE_START_CLOSING)
+ notifyFoldUpdate(transitionUpdate, lastHingeAngle)
}
if (isTransitionInProgress) {
if (isFullyOpened) {
- notifyFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN)
+ notifyFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN, angle)
cancelTimeout()
} else {
// The timeout will trigger some constant time after the last angle update.
@@ -146,7 +163,7 @@ constructor(
outputListeners.forEach { it.onHingeAngleUpdate(angle) }
}
- private fun isClosingThresholdMet(currentAngle: Float) : Boolean {
+ private fun isClosingThresholdMet(currentAngle: Float): Boolean {
val closingThreshold = getClosingThreshold()
return closingThreshold == null || currentAngle < closingThreshold
}
@@ -179,23 +196,29 @@ constructor(
if (isFolded) {
hingeAngleProvider.stop()
- notifyFoldUpdate(FOLD_UPDATE_FINISH_CLOSED)
+ notifyFoldUpdate(FOLD_UPDATE_FINISH_CLOSED, lastHingeAngle)
cancelTimeout()
isUnfoldHandled = false
} else {
- notifyFoldUpdate(FOLD_UPDATE_START_OPENING)
+ notifyFoldUpdate(FOLD_UPDATE_START_OPENING, lastHingeAngle)
rescheduleAbortAnimationTimeout()
hingeAngleProvider.start()
}
}
}
- private fun notifyFoldUpdate(@FoldUpdate update: Int) {
+ private fun notifyFoldUpdate(@FoldUpdate update: Int, angle: Float) {
if (DEBUG) {
Log.d(TAG, update.name())
}
+ val previouslyTransitioning = isTransitionInProgress
+
outputListeners.forEach { it.onFoldUpdate(update) }
lastFoldUpdate = update
+
+ if (previouslyTransitioning != isTransitionInProgress) {
+ lastHingeAngleBeforeTransition = angle
+ }
}
private fun rescheduleAbortAnimationTimeout() {
@@ -209,7 +232,8 @@ constructor(
handler.removeCallbacks(timeoutRunnable)
}
- private fun cancelAnimation(): Unit = notifyFoldUpdate(FOLD_UPDATE_FINISH_HALF_OPEN)
+ private fun cancelAnimation(): Unit =
+ notifyFoldUpdate(FOLD_UPDATE_FINISH_HALF_OPEN, lastHingeAngle)
private inner class ScreenStatusListener : ScreenStatusProvider.ScreenListener {
@@ -221,7 +245,7 @@ constructor(
// receive 'folded' event. If SystemUI started when device is already folded it will
// still receive 'folded' event on startup.
if (!isFolded && !isUnfoldHandled) {
- outputListeners.forEach { it.onFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) }
+ outputListeners.forEach { it.onUnfoldedScreenAvailable() }
isUnfoldHandled = true
}
}
@@ -257,7 +281,6 @@ fun @receiver:FoldUpdate Int.name() =
when (this) {
FOLD_UPDATE_START_OPENING -> "START_OPENING"
FOLD_UPDATE_START_CLOSING -> "START_CLOSING"
- FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE -> "UNFOLDED_SCREEN_AVAILABLE"
FOLD_UPDATE_FINISH_HALF_OPEN -> "FINISH_HALF_OPEN"
FOLD_UPDATE_FINISH_FULL_OPEN -> "FINISH_FULL_OPEN"
FOLD_UPDATE_FINISH_CLOSED -> "FINISH_CLOSED"
@@ -270,5 +293,8 @@ private val DEBUG = Log.isLoggable(TAG, Log.DEBUG)
/** Threshold after which we consider the device fully unfolded. */
@VisibleForTesting const val FULLY_OPEN_THRESHOLD_DEGREES = 15f
+/** Threshold after which hinge angle updates are considered. This is to eliminate noise. */
+@VisibleForTesting const val HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES = 7.5f
+
/** Fold animation on top of apps only when the angle exceeds this threshold. */
@VisibleForTesting const val START_CLOSING_ON_APPS_THRESHOLD_DEGREES = 60
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt
index c7a8bf336777..0af372f9da24 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt
@@ -31,8 +31,9 @@ interface FoldStateProvider : CallbackController<FoldUpdatesListener> {
val isFinishedOpening: Boolean
interface FoldUpdatesListener {
- fun onHingeAngleUpdate(@FloatRange(from = 0.0, to = 180.0) angle: Float)
- fun onFoldUpdate(@FoldUpdate update: Int)
+ @JvmDefault fun onHingeAngleUpdate(@FloatRange(from = 0.0, to = 180.0) angle: Float) {}
+ @JvmDefault fun onFoldUpdate(@FoldUpdate update: Int) {}
+ @JvmDefault fun onUnfoldedScreenAvailable() {}
}
@IntDef(
@@ -40,7 +41,6 @@ interface FoldStateProvider : CallbackController<FoldUpdatesListener> {
[
FOLD_UPDATE_START_OPENING,
FOLD_UPDATE_START_CLOSING,
- FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE,
FOLD_UPDATE_FINISH_HALF_OPEN,
FOLD_UPDATE_FINISH_FULL_OPEN,
FOLD_UPDATE_FINISH_CLOSED])
@@ -50,7 +50,6 @@ interface FoldStateProvider : CallbackController<FoldUpdatesListener> {
const val FOLD_UPDATE_START_OPENING = 0
const val FOLD_UPDATE_START_CLOSING = 1
-const val FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE = 2
-const val FOLD_UPDATE_FINISH_HALF_OPEN = 3
-const val FOLD_UPDATE_FINISH_FULL_OPEN = 4
-const val FOLD_UPDATE_FINISH_CLOSED = 5
+const val FOLD_UPDATE_FINISH_HALF_OPEN = 2
+const val FOLD_UPDATE_FINISH_FULL_OPEN = 3
+const val FOLD_UPDATE_FINISH_CLOSED = 4
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.kt
index b7bab3e5ed5a..f9751d9c279c 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.kt
@@ -47,6 +47,7 @@ constructor(source: UnfoldTransitionProgressProvider? = null) :
/**
* Sets the source for the unfold transition progress updates. Replaces current provider if it
* is already set
+ *
* @param provider transition provider that emits transition progress updates
*/
fun setSourceProvider(provider: UnfoldTransitionProgressProvider?) {
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index 0926f8ab5147..e159f18809c4 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -142,7 +142,7 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
protected final SystemSupport mSystemSupport;
protected final WindowManagerInternal mWindowManagerService;
private final SystemActionPerformer mSystemActionPerformer;
- private final AccessibilityWindowManager mA11yWindowManager;
+ final AccessibilityWindowManager mA11yWindowManager;
private final DisplayManager mDisplayManager;
private final PowerManager mPowerManager;
private final IPlatformCompat mIPlatformCompat;
@@ -1635,7 +1635,7 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
return false;
}
- if (event.isAccessibilityDataPrivate()
+ if (event.isAccessibilityDataSensitive()
&& (mFetchFlags & AccessibilityNodeInfo.FLAG_SERVICE_IS_ACCESSIBILITY_TOOL) == 0) {
return false;
}
@@ -2006,15 +2006,14 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
return accessibilityWindowId;
}
- private int resolveAccessibilityWindowIdForFindFocusLocked(int windowId, int focusType) {
+ int resolveAccessibilityWindowIdForFindFocusLocked(int windowId, int focusType) {
if (windowId == AccessibilityWindowInfo.ANY_WINDOW_ID) {
final int focusedWindowId = mA11yWindowManager.getFocusedWindowId(focusType);
// If the caller is a proxy and the found window doesn't belong to a proxy display
// (or vice versa), then return null. This doesn't work if there are multiple active
- // proxys, but in the future this code shouldn't be needed if input and a11y focus are
+ // proxys, but in the future this code shouldn't be needed if input focus are
// properly split. (so we will deal with the issues if we see them).
- //TODO(254545943): Remove this when there is user and proxy separation of input and a11y
- // focus
+ //TODO(254545943): Remove this when there is user and proxy separation of input focus
if (!mA11yWindowManager.windowIdBelongsToDisplayType(focusedWindowId, mDisplayTypes)) {
return AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index cde820ad1b91..7fba72b74e8d 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -3801,6 +3801,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
public boolean registerProxyForDisplay(IAccessibilityServiceClient client, int displayId)
throws RemoteException {
mSecurityPolicy.enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY);
+ mSecurityPolicy.enforceCallingOrSelfPermission(Manifest.permission.CREATE_VIRTUAL_DEVICE);
if (client == null) {
return false;
}
@@ -3823,7 +3824,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
try {
mProxyManager.registerProxy(client, displayId, mContext,
sIdCounter++, mMainHandler, mSecurityPolicy, this, getTraceManager(),
- mWindowManagerService, mA11yWindowManager);
+ mWindowManagerService);
synchronized (mLock) {
notifyClearAccessibilityCacheLocked();
@@ -3837,6 +3838,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
@Override
public boolean unregisterProxyForDisplay(int displayId) {
mSecurityPolicy.enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY);
+ mSecurityPolicy.enforceCallingOrSelfPermission(Manifest.permission.CREATE_VIRTUAL_DEVICE);
final long identity = Binder.clearCallingIdentity();
try {
return mProxyManager.unregisterProxy(displayId);
@@ -3928,6 +3930,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
mGlobalClients.getRegisteredCallbackCookie(i);
pw.append(Arrays.toString(client.mPackageNames));
}
+ pw.println();
+ mProxyManager.dump(fd, pw, args);
}
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
index f0c6c4f6cf2c..0e25a06b4727 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
@@ -19,6 +19,7 @@ package com.android.server.accessibility;
import static android.accessibilityservice.AccessibilityTrace.FLAGS_ACCESSIBILITY_INTERACTION_CONNECTION;
import static android.accessibilityservice.AccessibilityTrace.FLAGS_WINDOW_MANAGER_INTERNAL;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
+import static android.view.accessibility.AccessibilityEvent.WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED;
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
import static com.android.server.accessibility.AbstractAccessibilityServiceConnection.DISPLAY_TYPE_DEFAULT;
@@ -104,6 +105,8 @@ public class AccessibilityWindowManager {
private boolean mTouchInteractionInProgress;
+ private boolean mHasProxy;
+
/** List of Display Windows Observer, mapping from displayId -> DisplayWindowsObserver. */
private final SparseArray<DisplayWindowsObserver> mDisplayWindowsObservers =
new SparseArray<>();
@@ -159,6 +162,9 @@ public class AccessibilityWindowManager {
* Returns {@code true} if the window belongs to a display of {@code displayTypes}.
*/
public boolean windowIdBelongsToDisplayType(int focusedWindowId, int displayTypes) {
+ if (!mHasProxy) {
+ return true;
+ }
// UIAutomation wants focus from any display type.
final int displayTypeMask = DISPLAY_TYPE_PROXY | DISPLAY_TYPE_DEFAULT;
if ((displayTypes & displayTypeMask) == displayTypeMask) {
@@ -195,6 +201,7 @@ public class AccessibilityWindowManager {
private List<AccessibilityWindowInfo> mWindows;
private boolean mTrackingWindows = false;
private boolean mHasWatchOutsideTouchWindow;
+ private int mProxyDisplayAccessibilityFocusedWindow;
private boolean mIsProxy;
/**
@@ -608,8 +615,11 @@ public class AccessibilityWindowManager {
final int windowCount = windows.size();
final boolean isTopFocusedDisplay = mDisplayId == mTopFocusedDisplayId;
+ // A proxy with an a11y-focused window is a11y-focused should use the proxy focus id.
final boolean isAccessibilityFocusedDisplay =
- mDisplayId == mAccessibilityFocusedDisplayId;
+ mDisplayId == mAccessibilityFocusedDisplayId
+ || (mIsProxy && mProxyDisplayAccessibilityFocusedWindow
+ != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID);
// Modifies the value of top focused window, active window and a11y focused window
// only if this display is top focused display which has the top focused window.
if (isTopFocusedDisplay) {
@@ -635,9 +645,12 @@ public class AccessibilityWindowManager {
// We'll clear accessibility focus if the window with focus is no longer visible to
// accessibility services.
+ int a11yFocusedWindowId = mIsProxy
+ ? mProxyDisplayAccessibilityFocusedWindow
+ : mAccessibilityFocusedWindowId;
if (isAccessibilityFocusedDisplay) {
- shouldClearAccessibilityFocus = mAccessibilityFocusedWindowId
- != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
+ shouldClearAccessibilityFocus = a11yFocusedWindowId
+ != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
}
boolean hasWindowIgnore = false;
@@ -701,7 +714,7 @@ public class AccessibilityWindowManager {
if (isAccessibilityFocusedDisplay) {
for (int i = 0; i < accessibilityWindowCount; i++) {
final AccessibilityWindowInfo window = mWindows.get(i);
- if (window.getId() == mAccessibilityFocusedWindowId) {
+ if (window.getId() == a11yFocusedWindowId) {
window.setAccessibilityFocused(true);
shouldClearAccessibilityFocus = false;
break;
@@ -718,7 +731,7 @@ public class AccessibilityWindowManager {
}
if (shouldClearAccessibilityFocus) {
- clearAccessibilityFocusLocked(mAccessibilityFocusedWindowId);
+ clearAccessibilityFocusLocked(a11yFocusedWindowId);
}
}
@@ -897,6 +910,10 @@ public class AccessibilityWindowManager {
pw.println(" Top Focused Window Id = " + mTopFocusedWindowId);
pw.println(" Accessibility Focused Window Id = " + mAccessibilityFocusedWindowId
+ " ]");
+ if (mIsProxy) {
+ pw.println("Proxy accessibility focused window = "
+ + mProxyDisplayAccessibilityFocusedWindow);
+ }
pw.println();
if (mWindows != null) {
final int windowCount = mWindows.size();
@@ -1022,6 +1039,7 @@ public class AccessibilityWindowManager {
}
if (proxyed && !observer.mIsProxy) {
observer.mIsProxy = true;
+ mHasProxy = true;
}
if (observer.isTrackingWindowsLocked()) {
return;
@@ -1044,6 +1062,7 @@ public class AccessibilityWindowManager {
observer.stopTrackingWindowsLocked();
mDisplayWindowsObservers.remove(displayId);
}
+ resetHasProxyIfNeededLocked();
}
}
@@ -1053,11 +1072,26 @@ public class AccessibilityWindowManager {
*/
public void stopTrackingDisplayProxy(int displayId) {
synchronized (mLock) {
- DisplayWindowsObserver observer = mDisplayWindowsObservers.get(displayId);
+ final DisplayWindowsObserver proxyObserver = mDisplayWindowsObservers.get(displayId);
+ if (proxyObserver != null) {
+ proxyObserver.mIsProxy = false;
+ }
+ resetHasProxyIfNeededLocked();
+ }
+ }
+
+ private void resetHasProxyIfNeededLocked() {
+ boolean hasProxy = false;
+ final int count = mDisplayWindowsObservers.size();
+ for (int i = 0; i < count; i++) {
+ final DisplayWindowsObserver observer = mDisplayWindowsObservers.valueAt(i);
if (observer != null) {
- observer.mIsProxy = false;
+ if (observer.mIsProxy) {
+ hasProxy = true;
+ }
}
}
+ mHasProxy = hasProxy;
}
/**
@@ -1490,6 +1524,11 @@ public class AccessibilityWindowManager {
case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED: {
synchronized (mLock) {
+ // If window id belongs to a proxy display, then find the display, update the
+ // observer focus and send WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED events.
+ if (mHasProxy && setProxyFocusLocked(windowId)) {
+ return;
+ }
if (mAccessibilityFocusedWindowId != windowId) {
clearAccessibilityFocusLocked(mAccessibilityFocusedWindowId);
setAccessibilityFocusedWindowLocked(windowId);
@@ -1500,6 +1539,10 @@ public class AccessibilityWindowManager {
case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: {
synchronized (mLock) {
+ // If cleared happened on the proxy display, then clear the tracked focus.
+ if (mHasProxy && clearProxyFocusLocked(windowId, eventAction)) {
+ return;
+ }
if (mAccessibilityFocusNodeId == nodeId) {
mAccessibilityFocusNodeId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
}
@@ -1599,9 +1642,10 @@ public class AccessibilityWindowManager {
if (mAccessibilityFocusedDisplayId != Display.INVALID_DISPLAY
&& mAccessibilityFocusedWindowId
!= AccessibilityWindowInfo.UNDEFINED_WINDOW_ID) {
+ // Previously focused window -> send a focused event for losing focus
events.add(AccessibilityEvent.obtainWindowsChangedEvent(
mAccessibilityFocusedDisplayId, mAccessibilityFocusedWindowId,
- AccessibilityEvent.WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED));
+ WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED));
}
mAccessibilityFocusedWindowId = windowId;
@@ -1611,8 +1655,9 @@ public class AccessibilityWindowManager {
final DisplayWindowsObserver observer = mDisplayWindowsObservers.valueAt(i);
if (observer != null && observer.setAccessibilityFocusedWindowLocked(windowId)) {
mAccessibilityFocusedDisplayId = observer.mDisplayId;
+ // Newly focused window -> send a focused event for gaining focus
events.add(AccessibilityEvent.obtainWindowsChangedEvent(observer.mDisplayId,
- windowId, AccessibilityEvent.WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED));
+ windowId, WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED));
}
}
@@ -1662,6 +1707,33 @@ public class AccessibilityWindowManager {
* @return The focused windowId
*/
public int getFocusedWindowId(int focusType) {
+ return getFocusedWindowId(focusType, Display.INVALID_DISPLAY);
+ }
+
+ /**
+ * Returns focused windowId or accessibility focused windowId according to given focusType and
+ * display id.
+ * @param focusType {@link AccessibilityNodeInfo#FOCUS_INPUT} or
+ * {@link AccessibilityNodeInfo#FOCUS_ACCESSIBILITY}
+ * @param displayId the display id to check. If this display is proxy-ed, the proxy's a11y focus
+ * will be returned.
+ * @return The focused windowId
+ */
+ public int getFocusedWindowId(int focusType, int displayId) {
+ if (displayId == Display.INVALID_DISPLAY || displayId == Display.DEFAULT_DISPLAY
+ || !mHasProxy) {
+ return getDefaultFocus(focusType);
+ }
+
+ final DisplayWindowsObserver observer = mDisplayWindowsObservers.get(displayId);
+ if (observer != null && observer.mIsProxy) {
+ return getProxyFocus(focusType, observer);
+ } else {
+ return getDefaultFocus(focusType);
+ }
+ }
+
+ private int getDefaultFocus(int focusType) {
if (focusType == AccessibilityNodeInfo.FOCUS_INPUT) {
return mTopFocusedWindowId;
} else if (focusType == AccessibilityNodeInfo.FOCUS_ACCESSIBILITY) {
@@ -1670,6 +1742,16 @@ public class AccessibilityWindowManager {
return AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
}
+ private int getProxyFocus(int focusType, DisplayWindowsObserver observer) {
+ if (focusType == AccessibilityNodeInfo.FOCUS_INPUT) {
+ return mTopFocusedWindowId;
+ } else if (focusType == AccessibilityNodeInfo.FOCUS_ACCESSIBILITY) {
+ return observer.mProxyDisplayAccessibilityFocusedWindow;
+ } else {
+ return AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
+ }
+ }
+
/**
* Returns {@link AccessibilityWindowInfo} of PIP window.
*
@@ -1988,6 +2070,78 @@ public class AccessibilityWindowManager {
}
/**
+ * Checks if the window belongs to a proxy display and if so clears the focused window id.
+ * @param focusClearedWindowId the cleared window id.
+ * @return true if an observer is proxy-ed and has cleared its focused window id.
+ */
+ private boolean clearProxyFocusLocked(int focusClearedWindowId, int eventAction) {
+ // If we are just moving focus from one view to the other in the same window, do nothing.
+ if (eventAction == AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS) {
+ return false;
+ }
+ for (int i = 0; i < mDisplayWindowsObservers.size(); i++) {
+ final DisplayWindowsObserver observer = mDisplayWindowsObservers.get(i);
+ if (observer != null && observer.mWindows != null && observer.mIsProxy) {
+ final int windowCount = observer.mWindows.size();
+ for (int j = 0; j < windowCount; j++) {
+ AccessibilityWindowInfo window = observer.mWindows.get(j);
+ if (window.getId() == focusClearedWindowId) {
+ observer.mProxyDisplayAccessibilityFocusedWindow =
+ AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
+ // TODO(268754409): Look into sending a WINDOW_FOCUS_CHANGED event since
+ // window no longer has focus (default window logic doesn't), and
+ // whether the node id needs to be cached (default window logic does).
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Checks if the window belongs to a proxy display and if so sends
+ * WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED for that window and the previously focused window.
+ * @param focusedWindowId the focused window id.
+ * @return true if an observer is proxy-ed and contains the focused window.
+ */
+ private boolean setProxyFocusLocked(int focusedWindowId) {
+ for (int i = 0; i < mDisplayWindowsObservers.size(); i++) {
+ final DisplayWindowsObserver observer = mDisplayWindowsObservers.valueAt(i);
+ if (observer != null && observer.mIsProxy
+ && observer.setAccessibilityFocusedWindowLocked(focusedWindowId)) {
+ final int previouslyFocusedWindowId =
+ observer.mProxyDisplayAccessibilityFocusedWindow;
+
+ if (previouslyFocusedWindowId == focusedWindowId) {
+ // Don't send a focus event if the window is already focused.
+ return true;
+ }
+
+ // Previously focused window -> Clear focus on UI thread and send a focused event
+ // for losing focus
+ if (previouslyFocusedWindowId != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID) {
+ clearAccessibilityFocusLocked(previouslyFocusedWindowId);
+ mAccessibilityEventSender.sendAccessibilityEventForCurrentUserLocked(
+ AccessibilityEvent.obtainWindowsChangedEvent(
+ observer.mDisplayId, previouslyFocusedWindowId,
+ WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED));
+ }
+ observer.mProxyDisplayAccessibilityFocusedWindow = focusedWindowId;
+ // Newly focused window -> send a focused event for it gaining focus
+ mAccessibilityEventSender.sendAccessibilityEventForCurrentUserLocked(
+ AccessibilityEvent.obtainWindowsChangedEvent(
+ observer.mDisplayId,
+ observer.mProxyDisplayAccessibilityFocusedWindow,
+ WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED));
+
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
* Dumps all {@link AccessibilityWindowInfo}s here.
*/
public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
diff --git a/services/accessibility/java/com/android/server/accessibility/FlashNotificationsController.java b/services/accessibility/java/com/android/server/accessibility/FlashNotificationsController.java
index 86b5a12f3c47..a94ab34bc8b3 100644
--- a/services/accessibility/java/com/android/server/accessibility/FlashNotificationsController.java
+++ b/services/accessibility/java/com/android/server/accessibility/FlashNotificationsController.java
@@ -53,6 +53,7 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
+import android.util.FeatureFlagUtils;
import android.util.Log;
import android.view.Display;
import android.view.View;
@@ -342,10 +343,12 @@ class FlashNotificationsController {
private void requestStartFlashNotification(FlashNotification flashNotification) {
if (DEBUG) Log.d(LOG_TAG, "requestStartFlashNotification");
- mIsCameraFlashNotificationEnabled = Settings.System.getIntForUser(
+ boolean isFeatureOn = FeatureFlagUtils.isEnabled(mContext,
+ FeatureFlagUtils.SETTINGS_FLASH_NOTIFICATIONS);
+ mIsCameraFlashNotificationEnabled = isFeatureOn && Settings.System.getIntForUser(
mContext.getContentResolver(), SETTING_KEY_CAMERA_FLASH_NOTIFICATION, 0,
UserHandle.USER_CURRENT) != 0;
- mIsScreenFlashNotificationEnabled = Settings.System.getIntForUser(
+ mIsScreenFlashNotificationEnabled = isFeatureOn && Settings.System.getIntForUser(
mContext.getContentResolver(), SETTING_KEY_SCREEN_FLASH_NOTIFICATION, 0,
UserHandle.USER_CURRENT) != 0;
diff --git a/services/accessibility/java/com/android/server/accessibility/ProxyAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/ProxyAccessibilityServiceConnection.java
index df913aaf4893..b19a502547ab 100644
--- a/services/accessibility/java/com/android/server/accessibility/ProxyAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/ProxyAccessibilityServiceConnection.java
@@ -38,14 +38,18 @@ import android.os.RemoteCallback;
import android.os.RemoteException;
import android.view.KeyEvent;
import android.view.accessibility.AccessibilityDisplayProxy;
+import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityWindowInfo;
import androidx.annotation.Nullable;
import com.android.internal.R;
+import com.android.internal.util.DumpUtils;
import com.android.server.wm.WindowManagerInternal;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
@@ -61,6 +65,8 @@ import java.util.Set;
* TODO(241429275): Initialize this when a proxy is registered.
*/
public class ProxyAccessibilityServiceConnection extends AccessibilityServiceConnection {
+ private static final String LOG_TAG = "ProxyAccessibilityServiceConnection";
+
private int mDisplayId;
private List<AccessibilityServiceInfo> mInstalledAndEnabledServices;
@@ -255,6 +261,24 @@ public class ProxyAccessibilityServiceConnection extends AccessibilityServiceCon
}
@Override
+ int resolveAccessibilityWindowIdForFindFocusLocked(int windowId, int focusType) {
+ if (windowId == AccessibilityWindowInfo.ANY_WINDOW_ID) {
+ final int focusedWindowId = mA11yWindowManager.getFocusedWindowId(focusType,
+ mDisplayId);
+ // If the caller is a proxy and the found window doesn't belong to a proxy display
+ // (or vice versa), then return null. This doesn't work if there are multiple active
+ // proxys, but in the future this code shouldn't be needed if input focus
+ // properly split. (so we will deal with the issues if we see them).
+ //TODO(254545943): Remove this when there is user and proxy separation of input
+ if (!mA11yWindowManager.windowIdBelongsToDisplayType(focusedWindowId, mDisplayTypes)) {
+ return AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
+ }
+ return focusedWindowId;
+ }
+ return windowId;
+ }
+
+ @Override
public void binderDied() {
}
@@ -547,4 +571,25 @@ public class ProxyAccessibilityServiceConnection extends AccessibilityServiceCon
public void setAnimationScale(float scale) throws UnsupportedOperationException {
throw new UnsupportedOperationException("setAnimationScale is not supported");
}
+
+ @Override
+ public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
+ if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
+ synchronized (mLock) {
+ pw.append("Proxy[displayId=" + mDisplayId);
+ pw.append(", feedbackType"
+ + AccessibilityServiceInfo.feedbackTypeToString(mFeedbackType));
+ pw.append(", capabilities=" + mAccessibilityServiceInfo.getCapabilities());
+ pw.append(", eventTypes="
+ + AccessibilityEvent.eventTypeToString(mEventTypes));
+ pw.append(", notificationTimeout=" + mNotificationTimeout);
+ pw.append(", focusStrokeWidth=").append(String.valueOf(mFocusStrokeWidth));
+ pw.append(", focusColor=").append(String.valueOf(mFocusColor));
+ pw.append(", installedAndEnabledServiceCount=").append(String.valueOf(
+ mInstalledAndEnabledServices.size()));
+ pw.append(", installedAndEnabledServices=").append(
+ mInstalledAndEnabledServices.toString());
+ pw.append("]");
+ }
+ }
}
diff --git a/services/accessibility/java/com/android/server/accessibility/ProxyManager.java b/services/accessibility/java/com/android/server/accessibility/ProxyManager.java
index 2530338a03ab..e258de16caf5 100644
--- a/services/accessibility/java/com/android/server/accessibility/ProxyManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/ProxyManager.java
@@ -23,6 +23,7 @@ import android.hardware.display.DisplayManager;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
+import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
import android.view.accessibility.AccessibilityEvent;
@@ -30,6 +31,8 @@ import android.view.accessibility.AccessibilityManager;
import com.android.server.wm.WindowManagerInternal;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
import java.util.List;
/**
@@ -42,6 +45,9 @@ import java.util.List;
* TODO(262244375): Add unit tests.
*/
public class ProxyManager {
+ private static final boolean DEBUG = false;
+ private static final String LOG_TAG = "ProxyManager";
+
// Names used to populate ComponentName and ResolveInfo in connection.mA11yServiceInfo and in
// the infos of connection.setInstalledAndEnabledServices
static final String PROXY_COMPONENT_PACKAGE_NAME = "ProxyPackage";
@@ -78,8 +84,10 @@ public class ProxyManager {
AccessibilitySecurityPolicy securityPolicy,
AbstractAccessibilityServiceConnection.SystemSupport systemSupport,
AccessibilityTrace trace,
- WindowManagerInternal windowManagerInternal,
- AccessibilityWindowManager awm) throws RemoteException {
+ WindowManagerInternal windowManagerInternal) throws RemoteException {
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "Register proxy for display id: " + displayId);
+ }
// Set a default AccessibilityServiceInfo that is used before the proxy's info is
// populated. A proxy has the touch exploration and window capabilities.
@@ -93,7 +101,7 @@ public class ProxyManager {
new ProxyAccessibilityServiceConnection(context, info.getComponentName(), info,
id, mainHandler, mLock, securityPolicy, systemSupport, trace,
windowManagerInternal,
- awm, displayId);
+ mA11yWindowManager, displayId);
synchronized (mLock) {
mProxyA11yServiceConnections.put(displayId, connection);
@@ -135,6 +143,9 @@ public class ProxyManager {
if (mProxyA11yServiceConnections.contains(displayId)) {
mProxyA11yServiceConnections.remove(displayId);
removed = true;
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "Unregister proxy for display id " + displayId);
+ }
}
}
if (removed) {
@@ -156,19 +167,25 @@ public class ProxyManager {
*/
public boolean isProxyed(int displayId) {
synchronized (mLock) {
- return mProxyA11yServiceConnections.contains(displayId);
+ final boolean tracked = mProxyA11yServiceConnections.contains(displayId);
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "Tracking proxy display " + displayId + " : " + tracked);
+ }
+ return tracked;
}
}
/**
- * Sends AccessibilityEvents to all proxies.
- * {@link android.view.accessibility.AccessibilityDisplayProxy} will filter based on display.
- * TODO(b/250929565): Filtering should happen in the system, not in the proxy.
+ * Sends AccessibilityEvents to a proxy given the event's displayId.
*/
public void sendAccessibilityEventLocked(AccessibilityEvent event) {
final ProxyAccessibilityServiceConnection proxy =
mProxyA11yServiceConnections.get(event.getDisplayId());
if (proxy != null) {
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "Send proxy event " + event + " for display id "
+ + event.getDisplayId());
+ }
proxy.notifyAccessibilityEvent(event);
}
}
@@ -187,6 +204,9 @@ public class ProxyManager {
break;
}
}
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "At least one proxy can retrieve windows: " + observingWindows);
+ }
return observingWindows;
}
@@ -206,6 +226,14 @@ public class ProxyManager {
clientState |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED;
}
}
+
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "Accessibility is enabled for all proxies: "
+ + ((clientState & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0));
+ Slog.v(LOG_TAG, "Touch exploration is enabled for all proxies: "
+ + ((clientState & AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED)
+ != 0));
+ }
return clientState;
// TODO(b/254545943): When A11yManager is separated, include support for other properties.
}
@@ -235,6 +263,10 @@ public class ProxyManager {
mProxyA11yServiceConnections.valueAt(i);
relevantEventTypes |= proxy.getRelevantEventTypes();
}
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "Relevant event types for all proxies: "
+ + AccessibilityEvent.eventTypeToString(relevantEventTypes));
+ }
return relevantEventTypes;
}
@@ -276,4 +308,25 @@ public class ProxyManager {
void setAccessibilityInputFilter(AccessibilityInputFilter filter) {
mA11yInputFilter = filter;
}
+
+
+ /**
+ * Prints information belonging to each display that is controlled by an
+ * AccessibilityDisplayProxy.
+ */
+ void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ synchronized (mLock) {
+ pw.println();
+ pw.println("Proxy manager state:");
+ pw.println(" Number of proxy connections: " + mProxyA11yServiceConnections.size());
+ pw.println(" Registered proxy connections:");
+ for (int i = 0; i < mProxyA11yServiceConnections.size(); i++) {
+ final ProxyAccessibilityServiceConnection proxy =
+ mProxyA11yServiceConnections.valueAt(i);
+ if (proxy != null) {
+ proxy.dump(fd, pw, args);
+ }
+ }
+ }
+ }
} \ No newline at end of file
diff --git a/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java b/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java
index e6abc4c90fac..eba92305dd7b 100644
--- a/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java
+++ b/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java
@@ -335,7 +335,7 @@ public class SystemActionPerformer {
KeyEvent event = KeyEvent.obtain(downTime, time, action, keyCode, 0, 0,
KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM,
InputDevice.SOURCE_KEYBOARD, null);
- InputManager.getInstance()
+ mContext.getSystemService(InputManager.class)
.injectInputEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
event.recycle();
}
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
index 9c84c048003d..f85ef43f99fe 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
@@ -44,6 +44,8 @@ import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
+import android.os.VibrationEffect;
+import android.os.Vibrator;
import android.provider.Settings;
import android.util.Log;
import android.util.MathUtils;
@@ -279,7 +281,8 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
return mTempPointerProperties;
}
- private void transitionTo(State state) {
+ @VisibleForTesting
+ void transitionTo(State state) {
if (DEBUG_STATE_TRANSITIONS) {
Slog.i(mLogTag,
(State.nameOf(mCurrentState) + " -> " + State.nameOf(state)
@@ -287,6 +290,9 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
.replace(getClass().getName(), ""));
}
mPreviousState = mCurrentState;
+ if (state == mPanningScalingState) {
+ mPanningScalingState.prepareForState();
+ }
mCurrentState = state;
}
@@ -317,18 +323,34 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
final class PanningScalingState extends SimpleOnGestureListener
implements OnScaleGestureListener, State {
+ private final Context mContext;
private final ScaleGestureDetector mScaleGestureDetector;
private final GestureDetector mScrollGestureDetector;
final float mScalingThreshold;
float mInitialScaleFactor = -1;
- boolean mScaling;
+ @VisibleForTesting boolean mScaling;
+
+ /**
+ * Whether it needs to detect the target scale passes
+ * {@link FullScreenMagnificationController#getPersistedScale} during panning scale.
+ */
+ @VisibleForTesting boolean mDetectingPassPersistedScale;
+
+ // The threshold for relative difference from given scale to persisted scale. If the
+ // difference >= threshold, we can start detecting if the scale passes the persisted
+ // scale during panning.
+ @VisibleForTesting static final float CHECK_DETECTING_PASS_PERSISTED_SCALE_THRESHOLD = 0.2f;
+ // The threshold for relative difference from given scale to persisted scale. If the
+ // difference < threshold, we can decide that the scale passes the persisted scale.
+ @VisibleForTesting static final float PASSING_PERSISTED_SCALE_THRESHOLD = 0.01f;
PanningScalingState(Context context) {
final TypedValue scaleValue = new TypedValue();
context.getResources().getValue(
R.dimen.config_screen_magnification_scaling_threshold,
scaleValue, false);
+ mContext = context;
mScalingThreshold = scaleValue.getFloat();
mScaleGestureDetector = new ScaleGestureDetector(context, this, Handler.getMain());
mScaleGestureDetector.setQuickScaleEnabled(false);
@@ -351,12 +373,59 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
}
}
+
+ void prepareForState() {
+ checkShouldDetectPassPersistedScale();
+ }
+
+ private void checkShouldDetectPassPersistedScale() {
+ if (mDetectingPassPersistedScale) {
+ return;
+ }
+
+ final float currentScale =
+ mFullScreenMagnificationController.getScale(mDisplayId);
+ final float persistedScale =
+ mFullScreenMagnificationController.getPersistedScale(mDisplayId);
+
+ mDetectingPassPersistedScale =
+ (abs(currentScale - persistedScale) / persistedScale)
+ >= CHECK_DETECTING_PASS_PERSISTED_SCALE_THRESHOLD;
+ }
+
public void persistScaleAndTransitionTo(State state) {
mFullScreenMagnificationController.persistScale(mDisplayId);
clear();
transitionTo(state);
}
+ @VisibleForTesting
+ void setScaleAndClearIfNeeded(float scale, float pivotX, float pivotY) {
+ if (mDetectingPassPersistedScale) {
+ final float persistedScale =
+ mFullScreenMagnificationController.getPersistedScale(mDisplayId);
+ // If the scale passes the persisted scale during panning, perform a vibration
+ // feedback to user. Also, call {@link clear} to create a buffer zone so that
+ // user needs to panning more than {@link mScalingThreshold} to change scale again.
+ if (abs(scale - persistedScale) / persistedScale
+ < PASSING_PERSISTED_SCALE_THRESHOLD) {
+ scale = persistedScale;
+ final Vibrator vibrator = mContext.getSystemService(Vibrator.class);
+ if (vibrator != null) {
+ vibrator.vibrate(
+ VibrationEffect.createPredefined(VibrationEffect.EFFECT_TICK));
+ }
+ clear();
+ }
+ }
+
+ if (DEBUG_PANNING_SCALING) Slog.i(mLogTag, "Scaled content to: " + scale + "x");
+ mFullScreenMagnificationController.setScale(mDisplayId, scale, pivotX, pivotY, false,
+ AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
+
+ checkShouldDetectPassPersistedScale();
+ }
+
@Override
public boolean onScroll(MotionEvent first, MotionEvent second,
float distanceX, float distanceY) {
@@ -402,11 +471,7 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
scale = targetScale;
}
- final float pivotX = detector.getFocusX();
- final float pivotY = detector.getFocusY();
- if (DEBUG_PANNING_SCALING) Slog.i(mLogTag, "Scaled content to: " + scale + "x");
- mFullScreenMagnificationController.setScale(mDisplayId, scale, pivotX, pivotY, false,
- AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
+ setScaleAndClearIfNeeded(scale, detector.getFocusX(), detector.getFocusY());
return /* handled: */ true;
}
@@ -424,6 +489,7 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
public void clear() {
mInitialScaleFactor = -1;
mScaling = false;
+ mDetectingPassPersistedScale = false;
}
@Override
diff --git a/services/api/current.txt b/services/api/current.txt
index 329dbdf6346f..b55166c30965 100644
--- a/services/api/current.txt
+++ b/services/api/current.txt
@@ -43,6 +43,8 @@ package com.android.server.am {
method @Deprecated public boolean bindSdkSandboxService(@NonNull android.content.Intent, @NonNull android.content.ServiceConnection, int, @NonNull String, @NonNull String, int) throws android.os.RemoteException;
method public boolean canStartForegroundService(int, int, @NonNull String);
method public void killSdkSandboxClientAppProcess(@NonNull android.os.IBinder);
+ method @Nullable public android.content.ComponentName startSdkSandboxService(@NonNull android.content.Intent, int, @NonNull String, @NonNull String) throws android.os.RemoteException;
+ method public boolean stopSdkSandboxService(@NonNull android.content.Intent, int, @NonNull String, @NonNull String);
}
}
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 43b816bae651..61032dc7a59c 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -849,6 +849,32 @@ final class AutofillManagerServiceImpl
}
}
+
+ /**
+ * Updates the last fill response when a view was entered.
+ */
+ void logViewEntered(int sessionId, @Nullable Bundle clientState) {
+ synchronized (mLock) {
+ if (!isValidEventLocked("logViewEntered", sessionId)) {
+ return;
+ }
+
+ if (mEventHistory.getEvents() != null) {
+ // Do not log this event more than once
+ for (Event event : mEventHistory.getEvents()) {
+ if (event.getType() == Event.TYPE_VIEW_REQUESTED_AUTOFILL) {
+ Slog.v(TAG, "logViewEntered: already logged TYPE_VIEW_REQUESTED_AUTOFILL");
+ return;
+ }
+ }
+ }
+
+ mEventHistory.addEvent(
+ new Event(Event.TYPE_VIEW_REQUESTED_AUTOFILL, null, clientState, null,
+ null, null, null, null, null, null, null));
+ }
+ }
+
void logAugmentedAutofillAuthenticationSelected(int sessionId, @Nullable String selectedDataset,
@Nullable Bundle clientState) {
synchronized (mLock) {
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 598521f31ff5..4a12e3843972 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -442,6 +442,18 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
private boolean mPreviouslyFillDialogPotentiallyStarted;
/**
+ * Keeps track of if the user entered view, this is used to
+ * distinguish Fill Request that did not have user interaction
+ * with ones that did.
+ *
+ * This is set to true when entering view - after FillDialog FillRequest
+ * or on plain user tap.
+ */
+ @NonNull
+ @GuardedBy("mLock")
+ private boolean mLogViewEntered;
+
+ /**
* Keeps the fill dialog trigger ids of the last response. This invalidates
* the trigger ids of the previous response.
*/
@@ -1289,6 +1301,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
mMetricsLogger.write(newLogMaker(MetricsEvent.AUTOFILL_SESSION_STARTED)
.addTaggedData(MetricsEvent.FIELD_AUTOFILL_FLAGS, flags));
+ mLogViewEntered = false;
}
/**
@@ -1413,6 +1426,14 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
mService.setLastResponse(id, response);
+ synchronized (mLock) {
+ if (mLogViewEntered) {
+ mLogViewEntered = false;
+ mService.logViewEntered(id, null);
+ }
+ }
+
+
final long disableDuration = response.getDisableDuration();
final boolean autofillDisabled = disableDuration > 0;
if (autofillDisabled) {
@@ -3545,6 +3566,28 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
return;
}
+ synchronized (mLock) {
+ if (!mLogViewEntered) {
+ // If the current request is for FillDialog (preemptive)
+ // then this is the first time that the view is entered
+ // (mLogViewEntered == false) in this case, setLastResponse()
+ // has already been called, so just log here.
+ // If the current request is not and (mLogViewEntered == false)
+ // then the last session is being tracked (setLastResponse not called)
+ // so this calling logViewEntered will be a nop.
+ // Calling logViewEntered() twice will only log it once
+ // TODO(271181979): this is broken for multiple partitions
+ mService.logViewEntered(this.id, null);
+ }
+
+ // If this is the first time view is entered for inline, the last
+ // session is still being tracked, so logViewEntered() needs
+ // to be delayed until setLastResponse is called.
+ // For fill dialog requests case logViewEntered is already called above
+ // so this will do nothing. Assumption: only one fill dialog per session
+ mLogViewEntered = true;
+ }
+
// Previously, fill request will only start whenever a view is entered.
// With Fill Dialog, request starts prior to view getting entered. So, we can't end
// the event at this moment, otherwise we will be wrongly attributing fill dialog
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index a35cae9dffda..542cc2f0a0a6 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -59,6 +59,8 @@ import android.companion.DeviceNotAssociatedException;
import android.companion.IAssociationRequestCallback;
import android.companion.ICompanionDeviceManager;
import android.companion.IOnAssociationsChangedListener;
+import android.companion.IOnMessageReceivedListener;
+import android.companion.IOnTransportsChangedListener;
import android.companion.ISystemDataTransferCallback;
import android.content.ComponentName;
import android.content.Context;
@@ -232,7 +234,7 @@ public class CompanionDeviceManagerService extends SystemService {
/* cdmService */this, mAssociationStore);
mCompanionAppController = new CompanionApplicationController(
context, mAssociationStore, mDevicePresenceMonitor);
- mTransportManager = new CompanionTransportManager(context);
+ mTransportManager = new CompanionTransportManager(context, mAssociationStore);
mSystemDataTransferProcessor = new SystemDataTransferProcessor(this, mAssociationStore,
mSystemDataTransferRequestStore, mTransportManager);
@@ -601,6 +603,37 @@ public class CompanionDeviceManagerService extends SystemService {
}
@Override
+ @GuardedBy("CompanionDeviceManagerService.this.mTransportManager.mTransports")
+ public void addOnTransportsChangedListener(IOnTransportsChangedListener listener) {
+ mTransportManager.addListener(listener);
+ }
+
+ @Override
+ @GuardedBy("CompanionDeviceManagerService.this.mTransportManager.mTransports")
+ public void removeOnTransportsChangedListener(IOnTransportsChangedListener listener) {
+ mTransportManager.removeListener(listener);
+ }
+
+ @Override
+ @GuardedBy("CompanionDeviceManagerService.this.mTransportManager.mTransports")
+ public void sendMessage(int messageType, byte[] data, int[] associationIds) {
+ mTransportManager.sendMessage(messageType, data, associationIds);
+ }
+
+ @Override
+ @GuardedBy("CompanionDeviceManagerService.this.mTransportManager.mTransports")
+ public void addOnMessageReceivedListener(int messageType,
+ IOnMessageReceivedListener listener) {
+ mTransportManager.addListener(messageType, listener);
+ }
+
+ @Override
+ public void removeOnMessageReceivedListener(int messageType,
+ IOnMessageReceivedListener listener) {
+ mTransportManager.removeListener(messageType, listener);
+ }
+
+ @Override
public void legacyDisassociate(String deviceMacAddress, String packageName, int userId) {
Log.i(TAG, "legacyDisassociate() pkg=u" + userId + "/" + packageName
+ ", macAddress=" + deviceMacAddress);
diff --git a/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferProcessor.java b/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferProcessor.java
index 9f27f721ea83..f3a949d29ff8 100644
--- a/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferProcessor.java
+++ b/services/companion/java/com/android/server/companion/datatransfer/SystemDataTransferProcessor.java
@@ -23,6 +23,7 @@ import static android.companion.CompanionDeviceManager.COMPANION_DEVICE_DISCOVER
import static android.content.ComponentName.createRelative;
import static com.android.server.companion.Utils.prepareForIpc;
+import static com.android.server.companion.transport.Transport.MESSAGE_REQUEST_PERMISSION_RESTORE;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -30,6 +31,7 @@ import android.annotation.UserIdInt;
import android.app.PendingIntent;
import android.companion.AssociationInfo;
import android.companion.DeviceNotAssociatedException;
+import android.companion.IOnMessageReceivedListener;
import android.companion.ISystemDataTransferCallback;
import android.companion.datatransfer.PermissionSyncRequest;
import android.companion.datatransfer.SystemDataTransferRequest;
@@ -39,6 +41,7 @@ import android.content.Intent;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
+import android.os.IBinder;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.UserHandle;
@@ -91,7 +94,18 @@ public class SystemDataTransferProcessor {
mAssociationStore = associationStore;
mSystemDataTransferRequestStore = systemDataTransferRequestStore;
mTransportManager = transportManager;
- mTransportManager.setListener(this::onReceivePermissionRestore);
+ IOnMessageReceivedListener messageListener = new IOnMessageReceivedListener() {
+ @Override
+ public void onMessageReceived(int associationId, byte[] data) throws RemoteException {
+ onReceivePermissionRestore(data);
+ }
+
+ @Override
+ public IBinder asBinder() {
+ return null;
+ }
+ };
+ mTransportManager.addListener(MESSAGE_REQUEST_PERMISSION_RESTORE, messageListener);
mPermissionControllerManager = mContext.getSystemService(PermissionControllerManager.class);
mExecutor = Executors.newSingleThreadExecutor();
}
diff --git a/services/companion/java/com/android/server/companion/securechannel/AttestationVerifier.java b/services/companion/java/com/android/server/companion/securechannel/AttestationVerifier.java
index adaee757b96a..1559a3f8fdf8 100644
--- a/services/companion/java/com/android/server/companion/securechannel/AttestationVerifier.java
+++ b/services/companion/java/com/android/server/companion/securechannel/AttestationVerifier.java
@@ -35,7 +35,7 @@ import java.util.function.BiConsumer;
/**
* Helper class to perform attestation verification synchronously.
*/
-class AttestationVerifier {
+public class AttestationVerifier {
private static final long ATTESTATION_VERIFICATION_TIMEOUT_SECONDS = 10; // 10 seconds
private static final String PARAM_OWNED_BY_SYSTEM = "android.key_owned_by_system";
diff --git a/services/companion/java/com/android/server/companion/securechannel/SecureChannel.java b/services/companion/java/com/android/server/companion/securechannel/SecureChannel.java
index 13dba84487e3..05b6022ce569 100644
--- a/services/companion/java/com/android/server/companion/securechannel/SecureChannel.java
+++ b/services/companion/java/com/android/server/companion/securechannel/SecureChannel.java
@@ -110,7 +110,7 @@ public class SecureChannel {
this(in, out, callback, null, new AttestationVerifier(context));
}
- private SecureChannel(
+ public SecureChannel(
final InputStream in,
final OutputStream out,
Callback callback,
@@ -381,9 +381,10 @@ public class SecureChannel {
private void exchangeAuthentication()
throws IOException, GeneralSecurityException, BadHandleException, CryptoException {
- if (mVerifier == null) {
+ if (mPreSharedKey != null) {
exchangePreSharedKey();
- } else {
+ }
+ if (mVerifier != null) {
exchangeAttestation();
}
}
diff --git a/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java b/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java
index 494c5a6c0779..539020519f84 100644
--- a/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java
+++ b/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java
@@ -18,51 +18,46 @@ package com.android.server.companion.transport;
import static android.Manifest.permission.DELIVER_COMPANION_MESSAGES;
+import static com.android.server.companion.transport.Transport.MESSAGE_REQUEST_PERMISSION_RESTORE;
+import static com.android.server.companion.transport.Transport.MESSAGE_REQUEST_PLATFORM_INFO;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.app.ActivityManagerInternal;
+import android.companion.AssociationInfo;
+import android.companion.IOnMessageReceivedListener;
+import android.companion.IOnTransportsChangedListener;
import android.content.Context;
import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Binder;
import android.os.Build;
+import android.os.IBinder;
import android.os.ParcelFileDescriptor;
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
import com.android.server.LocalServices;
-import com.android.server.companion.securechannel.SecureChannel;
-
-import libcore.io.IoUtils;
-import libcore.io.Streams;
-import libcore.util.EmptyArray;
+import com.android.server.companion.AssociationStore;
import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
import java.nio.ByteBuffer;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.BlockingQueue;
+import java.util.ArrayList;
+import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
-import java.util.concurrent.atomic.AtomicInteger;
@SuppressLint("LongLogTag")
public class CompanionTransportManager {
private static final String TAG = "CDM_CompanionTransportManager";
- // TODO: flip to false
- private static final boolean DEBUG = true;
-
- private static final int HEADER_LENGTH = 12;
+ private static final boolean DEBUG = false;
- private static final int MESSAGE_REQUEST_PING = 0x63807378; // ?PIN
- private static final int MESSAGE_REQUEST_PERMISSION_RESTORE = 0x63826983; // ?RES
-
- private static final int MESSAGE_RESPONSE_SUCCESS = 0x33838567; // !SUC
- private static final int MESSAGE_RESPONSE_FAILURE = 0x33706573; // !FAI
+ private static final int SECURE_CHANNEL_AVAILABLE_SDK = Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
+ private static final int NON_ANDROID = -1;
private boolean mSecureTransportEnabled = true;
@@ -74,24 +69,98 @@ public class CompanionTransportManager {
return (message & 0xFF000000) == 0x33000000;
}
- public interface Listener {
- void onRequestPermissionRestore(byte[] data);
- }
-
private final Context mContext;
+ private final AssociationStore mAssociationStore;
+ /** Association id -> Transport */
@GuardedBy("mTransports")
private final SparseArray<Transport> mTransports = new SparseArray<>();
+ @NonNull
+ private final RemoteCallbackList<IOnTransportsChangedListener> mTransportsListeners =
+ new RemoteCallbackList<>();
+ /** Message type -> IOnMessageReceivedListener */
+ @NonNull
+ private final SparseArray<IOnMessageReceivedListener> mMessageListeners = new SparseArray<>();
+
@Nullable
- private Listener mListener;
+ private Transport mTempTransport;
- public CompanionTransportManager(Context context) {
+ public CompanionTransportManager(Context context, AssociationStore associationStore) {
mContext = context;
+ mAssociationStore = associationStore;
+ }
+
+ /**
+ * Add a listener to receive callbacks when a message is received for the message type
+ */
+ @GuardedBy("mTransports")
+ public void addListener(int message, @NonNull IOnMessageReceivedListener listener) {
+ mMessageListeners.put(message, listener);
+ for (int i = 0; i < mTransports.size(); i++) {
+ mTransports.valueAt(i).addListener(message, listener);
+ }
}
- public void setListener(@NonNull Listener listener) {
- mListener = listener;
+ /**
+ * Add a listener to receive callbacks when any of the transports is changed
+ */
+ @GuardedBy("mTransports")
+ public void addListener(IOnTransportsChangedListener listener) {
+ Slog.i(TAG, "Registering OnTransportsChangedListener");
+ mTransportsListeners.register(listener);
+ List<AssociationInfo> associations = new ArrayList<>();
+ for (int i = 0; i < mTransports.size(); i++) {
+ AssociationInfo association = mAssociationStore.getAssociationById(
+ mTransports.keyAt(i));
+ if (association != null) {
+ associations.add(association);
+ }
+ }
+ mTransportsListeners.broadcast(listener1 -> {
+ // callback to the current listener with all the associations of the transports
+ // immediately
+ if (listener1 == listener) {
+ try {
+ listener.onTransportsChanged(associations);
+ } catch (RemoteException ignored) {
+ }
+ }
+ });
+ }
+
+ /**
+ * Remove the listener for receiving callbacks when any of the transports is changed
+ */
+ public void removeListener(IOnTransportsChangedListener listener) {
+ mTransportsListeners.unregister(listener);
+ }
+
+ /**
+ * Remove the listener to stop receiving calbacks when a message is received for the given type
+ */
+ public void removeListener(int messageType, IOnMessageReceivedListener listener) {
+ mMessageListeners.remove(messageType);
+ }
+
+ /**
+ * Send a message to remote devices through the transports
+ */
+ @GuardedBy("mTransports")
+ public void sendMessage(int message, byte[] data, int[] associationIds) {
+ Slog.i(TAG, "Sending message 0x" + Integer.toHexString(message)
+ + " data length " + data.length);
+ for (int i = 0; i < associationIds.length; i++) {
+ if (mTransports.contains(associationIds[i])) {
+ try {
+ mTransports.get(associationIds[i]).sendMessage(message, data);
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to send message 0x" + Integer.toHexString(message)
+ + " data length " + data.length + " to association "
+ + associationIds[i]);
+ }
+ }
+ }
}
/**
@@ -125,15 +194,9 @@ public class CompanionTransportManager {
detachSystemDataTransport(packageName, userId, associationId);
}
- final Transport transport;
- if (isSecureTransportEnabled(associationId)) {
- transport = new SecureTransport(associationId, fd);
- } else {
- transport = new RawTransport(associationId, fd);
- }
+ initializeTransport(associationId, fd);
- transport.start();
- mTransports.put(associationId, transport);
+ notifyOnTransportsChanged();
}
}
@@ -145,323 +208,144 @@ public class CompanionTransportManager {
mTransports.delete(associationId);
transport.stop();
}
- }
- }
- public Future<?> requestPermissionRestore(int associationId, byte[] data) {
- synchronized (mTransports) {
- final Transport transport = mTransports.get(associationId);
- if (transport == null) {
- return CompletableFuture.failedFuture(new IOException("Missing transport"));
- }
-
- return transport.requestForResponse(MESSAGE_REQUEST_PERMISSION_RESTORE, data);
+ notifyOnTransportsChanged();
}
}
- /**
- * @hide
- */
- public void enableSecureTransport(boolean enabled) {
- this.mSecureTransportEnabled = enabled;
- }
-
- private boolean isSecureTransportEnabled(int associationId) {
- boolean enabled = !Build.IS_DEBUGGABLE || mSecureTransportEnabled;
-
- // TODO: version comparison logic
- return enabled;
- }
-
- // TODO: Make Transport inner classes into standalone classes.
- private abstract class Transport {
- protected final int mAssociationId;
- protected final InputStream mRemoteIn;
- protected final OutputStream mRemoteOut;
-
- @GuardedBy("mPendingRequests")
- protected final SparseArray<CompletableFuture<byte[]>> mPendingRequests =
- new SparseArray<>();
- protected final AtomicInteger mNextSequence = new AtomicInteger();
-
- Transport(int associationId, ParcelFileDescriptor fd) {
- this(associationId,
- new ParcelFileDescriptor.AutoCloseInputStream(fd),
- new ParcelFileDescriptor.AutoCloseOutputStream(fd));
- }
-
- Transport(int associationId, InputStream in, OutputStream out) {
- this.mAssociationId = associationId;
- this.mRemoteIn = in;
- this.mRemoteOut = out;
- }
-
- public abstract void start();
- public abstract void stop();
-
- protected abstract void sendMessage(int message, int sequence, @NonNull byte[] data)
- throws IOException;
-
- public Future<byte[]> requestForResponse(int message, byte[] data) {
- if (DEBUG) Slog.d(TAG, "Requesting for response");
- final int sequence = mNextSequence.incrementAndGet();
- final CompletableFuture<byte[]> pending = new CompletableFuture<>();
- synchronized (mPendingRequests) {
- mPendingRequests.put(sequence, pending);
- }
-
- try {
- sendMessage(message, sequence, data);
- } catch (IOException e) {
- synchronized (mPendingRequests) {
- mPendingRequests.remove(sequence);
- }
- pending.completeExceptionally(e);
- }
-
- return pending;
- }
-
- protected final void handleMessage(int message, int sequence, @NonNull byte[] data)
- throws IOException {
- if (DEBUG) {
- Slog.d(TAG, "Received message 0x" + Integer.toHexString(message)
- + " sequence " + sequence + " length " + data.length
- + " from association " + mAssociationId);
- }
-
- if (isRequest(message)) {
- try {
- processRequest(message, sequence, data);
- } catch (IOException e) {
- Slog.w(TAG, "Failed to respond to 0x" + Integer.toHexString(message), e);
- }
- } else if (isResponse(message)) {
- processResponse(message, sequence, data);
- } else {
- Slog.w(TAG, "Unknown message 0x" + Integer.toHexString(message));
- }
- }
-
- private void processRequest(int message, int sequence, byte[] data)
- throws IOException {
- switch (message) {
- case MESSAGE_REQUEST_PING: {
- sendMessage(MESSAGE_RESPONSE_SUCCESS, sequence, data);
- break;
- }
- case MESSAGE_REQUEST_PERMISSION_RESTORE: {
- if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)
- && !Build.isDebuggable()) {
- Slog.w(TAG, "Restoring permissions only supported on watches");
- sendMessage(MESSAGE_RESPONSE_FAILURE, sequence, EmptyArray.BYTE);
- break;
- }
- try {
- mListener.onRequestPermissionRestore(data);
- sendMessage(MESSAGE_RESPONSE_SUCCESS, sequence, EmptyArray.BYTE);
- } catch (Exception e) {
- Slog.w(TAG, "Failed to restore permissions");
- sendMessage(MESSAGE_RESPONSE_FAILURE, sequence, EmptyArray.BYTE);
- }
- break;
- }
- default: {
- Slog.w(TAG, "Unknown request 0x" + Integer.toHexString(message));
- sendMessage(MESSAGE_RESPONSE_FAILURE, sequence, EmptyArray.BYTE);
- break;
- }
+ @GuardedBy("mTransports")
+ private void notifyOnTransportsChanged() {
+ List<AssociationInfo> associations = new ArrayList<>();
+ for (int i = 0; i < mTransports.size(); i++) {
+ AssociationInfo association = mAssociationStore.getAssociationById(
+ mTransports.keyAt(i));
+ if (association != null) {
+ associations.add(association);
}
}
-
- private void processResponse(int message, int sequence, byte[] data) {
- final CompletableFuture<byte[]> future;
- synchronized (mPendingRequests) {
- future = mPendingRequests.removeReturnOld(sequence);
- }
- if (future == null) {
- Slog.w(TAG, "Ignoring unknown sequence " + sequence);
- return;
- }
-
- switch (message) {
- case MESSAGE_RESPONSE_SUCCESS: {
- future.complete(data);
- break;
- }
- case MESSAGE_RESPONSE_FAILURE: {
- future.completeExceptionally(new RuntimeException("Remote failure"));
- break;
- }
- default: {
- Slog.w(TAG, "Ignoring unknown response 0x" + Integer.toHexString(message));
- }
+ mTransportsListeners.broadcast(listener -> {
+ try {
+ listener.onTransportsChanged(associations);
+ } catch (RemoteException ignored) {
}
- }
+ });
}
- private class RawTransport extends Transport {
- private volatile boolean mStopped;
-
- RawTransport(int associationId, ParcelFileDescriptor fd) {
- super(associationId, fd);
+ @GuardedBy("mTransports")
+ private void initializeTransport(int associationId, ParcelFileDescriptor fd) {
+ Slog.i(TAG, "Initializing transport");
+ if (!isSecureTransportEnabled()) {
+ Transport transport = new RawTransport(associationId, fd, mContext);
+ addMessageListenersToTransport(transport);
+ transport.start();
+ mTransports.put(associationId, transport);
+ Slog.i(TAG, "RawTransport is created");
+ return;
}
- @Override
- public void start() {
- new Thread(() -> {
- try {
- while (!mStopped) {
- receiveMessage();
- }
- } catch (IOException e) {
- if (!mStopped) {
- Slog.w(TAG, "Trouble during transport", e);
- stop();
- }
+ // Exchange platform info to decide which transport should be created
+ mTempTransport = new RawTransport(associationId, fd, mContext);
+ addMessageListenersToTransport(mTempTransport);
+ IOnMessageReceivedListener listener = new IOnMessageReceivedListener() {
+ @Override
+ public void onMessageReceived(int associationId, byte[] data) throws RemoteException {
+ synchronized (mTransports) {
+ onPlatformInfoReceived(associationId, data);
}
- }).start();
- }
-
- @Override
- public void stop() {
- mStopped = true;
-
- IoUtils.closeQuietly(mRemoteIn);
- IoUtils.closeQuietly(mRemoteOut);
- }
-
- @Override
- protected void sendMessage(int message, int sequence, @NonNull byte[] data)
- throws IOException {
- if (DEBUG) {
- Slog.d(TAG, "Sending message 0x" + Integer.toHexString(message)
- + " sequence " + sequence + " length " + data.length
- + " to association " + mAssociationId);
}
- synchronized (mRemoteOut) {
- final ByteBuffer header = ByteBuffer.allocate(HEADER_LENGTH)
- .putInt(message)
- .putInt(sequence)
- .putInt(data.length);
- mRemoteOut.write(header.array());
- mRemoteOut.write(data);
- mRemoteOut.flush();
+ @Override
+ public IBinder asBinder() {
+ return null;
}
- }
-
- private void receiveMessage() throws IOException {
- final byte[] headerBytes = new byte[HEADER_LENGTH];
- Streams.readFully(mRemoteIn, headerBytes);
- final ByteBuffer header = ByteBuffer.wrap(headerBytes);
- final int message = header.getInt();
- final int sequence = header.getInt();
- final int length = header.getInt();
- final byte[] data = new byte[length];
- Streams.readFully(mRemoteIn, data);
-
- handleMessage(message, sequence, data);
+ };
+ mTempTransport.addListener(MESSAGE_REQUEST_PLATFORM_INFO, listener);
+ mTempTransport.start();
+
+ int sdk = Build.VERSION.SDK_INT;
+ String release = Build.VERSION.RELEASE;
+ // data format: | SDK_INT (int) | release length (int) | release |
+ final ByteBuffer data = ByteBuffer.allocate(4 + 4 + release.getBytes().length)
+ .putInt(sdk)
+ .putInt(release.getBytes().length)
+ .put(release.getBytes());
+
+ // TODO: it should check if preSharedKey is given
+ try {
+ mTempTransport.sendMessage(MESSAGE_REQUEST_PLATFORM_INFO, data.array());
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to exchange platform info");
}
}
- private class SecureTransport extends Transport implements SecureChannel.Callback {
- private final SecureChannel mSecureChannel;
-
- private volatile boolean mShouldProcessRequests = false;
-
- private final BlockingQueue<byte[]> mRequestQueue = new ArrayBlockingQueue<>(100);
-
- SecureTransport(int associationId, ParcelFileDescriptor fd) {
- super(associationId, fd);
- mSecureChannel = new SecureChannel(mRemoteIn, mRemoteOut, this, mContext);
- }
-
- @Override
- public void start() {
- mSecureChannel.start();
- }
-
- @Override
- public void stop() {
- mSecureChannel.stop();
- mShouldProcessRequests = false;
+ /**
+ * Depending on the remote platform info to decide which transport should be created
+ */
+ @GuardedBy("CompanionTransportManager.this.mTransports")
+ private void onPlatformInfoReceived(int associationId, byte[] data) {
+ if (mTempTransport.getAssociationId() != associationId) {
+ return;
}
-
- @Override
- public Future<byte[]> requestForResponse(int message, byte[] data) {
- // Check if channel is secured and start securing
- if (!mShouldProcessRequests) {
- Slog.d(TAG, "Establishing secure connection.");
- try {
- mSecureChannel.establishSecureConnection();
- } catch (Exception e) {
- Slog.w(TAG, "Failed to initiate secure channel handshake.", e);
- onError(e);
- }
- }
-
- return super.requestForResponse(message, data);
+ // TODO: it should check if preSharedKey is given
+
+ ByteBuffer buffer = ByteBuffer.wrap(data);
+ int remoteSdk = buffer.getInt();
+ byte[] remoteRelease = new byte[buffer.getInt()];
+ buffer.get(remoteRelease);
+
+ Slog.i(TAG, "Remote device SDK: " + remoteSdk + ", release:" + new String(remoteRelease));
+
+ Transport transport = mTempTransport;
+ mTempTransport = null;
+
+ int sdk = Build.VERSION.SDK_INT;
+ String release = Build.VERSION.RELEASE;
+ if (remoteSdk == NON_ANDROID) {
+ // TODO: pass in a real preSharedKey
+ transport = new SecureTransport(transport.getAssociationId(), transport.getFd(),
+ mContext, null, null);
+ } else if (sdk < SECURE_CHANNEL_AVAILABLE_SDK
+ || remoteSdk < SECURE_CHANNEL_AVAILABLE_SDK) {
+ // TODO: depending on the release version, either
+ // 1) using a RawTransport for old T versions
+ // 2) or an Ukey2 handshaked transport for UKey2 backported T versions
+ } else {
+ Slog.i(TAG, "Creating a secure channel");
+ transport = new SecureTransport(transport.getAssociationId(), transport.getFd(),
+ mContext);
+ addMessageListenersToTransport(transport);
+ transport.start();
}
+ mTransports.put(transport.getAssociationId(), transport);
+ // Doesn't need to notifyTransportsChanged here, it'll be done in attachSystemDataTransport
+ }
- @Override
- protected void sendMessage(int message, int sequence, @NonNull byte[] data)
- throws IOException {
- if (DEBUG) {
- Slog.d(TAG, "Queueing message 0x" + Integer.toHexString(message)
- + " sequence " + sequence + " length " + data.length
- + " to association " + mAssociationId);
+ public Future<?> requestPermissionRestore(int associationId, byte[] data) {
+ synchronized (mTransports) {
+ final Transport transport = mTransports.get(associationId);
+ if (transport == null) {
+ return CompletableFuture.failedFuture(new IOException("Missing transport"));
}
-
- // Queue up a message to send
- mRequestQueue.add(ByteBuffer.allocate(HEADER_LENGTH + data.length)
- .putInt(message)
- .putInt(sequence)
- .putInt(data.length)
- .put(data)
- .array());
+ return transport.requestForResponse(MESSAGE_REQUEST_PERMISSION_RESTORE, data);
}
+ }
- @Override
- public void onSecureConnection() {
- mShouldProcessRequests = true;
- Slog.d(TAG, "Secure connection established.");
-
- // TODO: find a better way to handle incoming requests than a dedicated thread.
- new Thread(() -> {
- try {
- while (mShouldProcessRequests) {
- byte[] request = mRequestQueue.poll();
- if (request != null) {
- mSecureChannel.sendSecureMessage(request);
- }
- }
- } catch (IOException e) {
- onError(e);
- }
- }).start();
- }
+ /**
+ * @hide
+ */
+ public void enableSecureTransport(boolean enabled) {
+ this.mSecureTransportEnabled = enabled;
+ }
- @Override
- public void onSecureMessageReceived(byte[] data) {
- final ByteBuffer payload = ByteBuffer.wrap(data);
- final int message = payload.getInt();
- final int sequence = payload.getInt();
- final int length = payload.getInt();
- final byte[] content = new byte[length];
- payload.get(content);
+ private boolean isSecureTransportEnabled() {
+ boolean enabled = !Build.IS_DEBUGGABLE || mSecureTransportEnabled;
- try {
- handleMessage(message, sequence, content);
- } catch (IOException error) {
- onError(error);
- }
- }
+ return enabled;
+ }
- @Override
- public void onError(Throwable error) {
- mShouldProcessRequests = false;
- Slog.e(TAG, error.getMessage(), error);
+ private void addMessageListenersToTransport(Transport transport) {
+ for (int i = 0; i < mMessageListeners.size(); i++) {
+ transport.addListener(mMessageListeners.keyAt(i), mMessageListeners.valueAt(i));
}
}
}
diff --git a/services/companion/java/com/android/server/companion/transport/CryptoManager.java b/services/companion/java/com/android/server/companion/transport/CryptoManager.java
index b08354afc8ad..a15939e52936 100644
--- a/services/companion/java/com/android/server/companion/transport/CryptoManager.java
+++ b/services/companion/java/com/android/server/companion/transport/CryptoManager.java
@@ -16,51 +16,51 @@
package com.android.server.companion.transport;
-import android.security.keystore.KeyGenParameterSpec;
-import android.security.keystore.KeyProperties;
import android.util.Slog;
-import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
-import java.security.UnrecoverableEntryException;
-import java.security.cert.CertificateException;
+import java.util.Arrays;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
-import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
/**
- * This class can be used to encrypt and decrypt bytes using Android Cryptography
+ * This class uses Java Cryptography to encrypt and decrypt messages
*/
public class CryptoManager {
private static final String TAG = "CDM_CryptoManager";
+ private static final int SECRET_KEY_LENGTH = 32;
+ private static final String ALGORITHM = "AES";
+ private static final String TRANSFORMATION = "AES/CBC/PKCS7Padding";
- private static final String KEY_STORE_ALIAS = "cdm_secret";
- private static final String ALGORITHM = KeyProperties.KEY_ALGORITHM_AES;
- private static final String BLOCK_MODE = KeyProperties.BLOCK_MODE_CBC;
- private static final String PADDING = KeyProperties.ENCRYPTION_PADDING_PKCS7;
- private static final String TRANSFORMATION = ALGORITHM + "/" + BLOCK_MODE + "/" + PADDING;
+ private final byte[] mPreSharedKey;
+ private Cipher mEncryptCipher;
+ private Cipher mDecryptCipher;
- private final KeyStore mKeyStore;
+ private SecretKey mSecretKey;
- public CryptoManager() {
- // Initialize KeyStore
+ public CryptoManager(byte[] preSharedKey) {
+ if (preSharedKey == null) {
+ mPreSharedKey = Arrays.copyOf(new byte[0], SECRET_KEY_LENGTH);
+ } else {
+ mPreSharedKey = Arrays.copyOf(preSharedKey, SECRET_KEY_LENGTH);
+ }
+ mSecretKey = new SecretKeySpec(mPreSharedKey, ALGORITHM);
try {
- mKeyStore = KeyStore.getInstance("AndroidKeyStore");
- mKeyStore.load(null);
- } catch (KeyStoreException | IOException | NoSuchAlgorithmException
- | CertificateException e) {
- throw new RuntimeException(e);
+ mEncryptCipher = Cipher.getInstance(TRANSFORMATION);
+ mEncryptCipher.init(Cipher.ENCRYPT_MODE, mSecretKey);
+ mDecryptCipher = Cipher.getInstance(TRANSFORMATION);
+ } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException e) {
+ Slog.e(TAG, e.getMessage());
}
}
@@ -69,21 +69,19 @@ public class CryptoManager {
*/
public byte[] encrypt(byte[] input) {
try {
- // Encrypt using Cipher
- Cipher encryptCipher = Cipher.getInstance(TRANSFORMATION);
- encryptCipher.init(Cipher.ENCRYPT_MODE, getKey());
- byte[] encryptedBytes = encryptCipher.doFinal(input);
+ if (mEncryptCipher == null) {
+ return null;
+ }
- // Write to bytes
+ byte[] encryptedBytes = mEncryptCipher.doFinal(input);
ByteBuffer buffer = ByteBuffer.allocate(
- 4 + encryptCipher.getIV().length + 4 + encryptedBytes.length)
- .putInt(encryptCipher.getIV().length)
- .put(encryptCipher.getIV())
+ 4 + mEncryptCipher.getIV().length + 4 + encryptedBytes.length)
+ .putInt(mEncryptCipher.getIV().length)
+ .put(mEncryptCipher.getIV())
.putInt(encryptedBytes.length)
.put(encryptedBytes);
return buffer.array();
- } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
- | IllegalBlockSizeException | BadPaddingException e) {
+ } catch (IllegalBlockSizeException | BadPaddingException e) {
Slog.e(TAG, e.getMessage());
return null;
}
@@ -99,45 +97,20 @@ public class CryptoManager {
byte[] encryptedBytes = new byte[buffer.getInt()];
buffer.get(encryptedBytes);
try {
- Cipher decryptCipher = Cipher.getInstance(TRANSFORMATION);
- decryptCipher.init(Cipher.DECRYPT_MODE, getKey(), new IvParameterSpec(iv));
- return decryptCipher.doFinal(encryptedBytes);
- } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
- | InvalidAlgorithmParameterException | IllegalBlockSizeException
- | BadPaddingException e) {
+ mDecryptCipher.init(Cipher.DECRYPT_MODE, getKey(), new IvParameterSpec(iv));
+ return mDecryptCipher.doFinal(encryptedBytes);
+ } catch (InvalidKeyException | InvalidAlgorithmParameterException
+ | IllegalBlockSizeException | BadPaddingException e) {
Slog.e(TAG, e.getMessage());
return null;
}
}
private SecretKey getKey() {
- try {
- KeyStore.Entry keyEntry = mKeyStore.getEntry(KEY_STORE_ALIAS, null);
- if (keyEntry instanceof KeyStore.SecretKeyEntry
- && ((KeyStore.SecretKeyEntry) keyEntry).getSecretKey() != null) {
- return ((KeyStore.SecretKeyEntry) keyEntry).getSecretKey();
- } else {
- return createKey();
- }
- } catch (NoSuchAlgorithmException | UnrecoverableEntryException | KeyStoreException e) {
- throw new RuntimeException(e);
- }
- }
-
- private SecretKey createKey() {
- try {
- KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM);
- keyGenerator.init(
- new KeyGenParameterSpec.Builder(KEY_STORE_ALIAS,
- KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
- .setBlockModes(BLOCK_MODE)
- .setEncryptionPaddings(PADDING)
- .setUserAuthenticationRequired(false)
- .setRandomizedEncryptionRequired(true)
- .build());
- return keyGenerator.generateKey();
- } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException e) {
- throw new RuntimeException(e);
+ if (mSecretKey != null) {
+ return mSecretKey;
}
+ mSecretKey = new SecretKeySpec(mPreSharedKey, ALGORITHM);
+ return mSecretKey;
}
}
diff --git a/services/companion/java/com/android/server/companion/transport/RawTransport.java b/services/companion/java/com/android/server/companion/transport/RawTransport.java
new file mode 100644
index 000000000000..4060f6efe0ca
--- /dev/null
+++ b/services/companion/java/com/android/server/companion/transport/RawTransport.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2023 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.companion.transport;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.os.ParcelFileDescriptor;
+import android.util.Slog;
+
+import libcore.io.IoUtils;
+import libcore.io.Streams;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+class RawTransport extends Transport {
+ private volatile boolean mStopped;
+
+ RawTransport(int associationId, ParcelFileDescriptor fd, Context context) {
+ super(associationId, fd, context);
+ }
+
+ @Override
+ public void start() {
+ new Thread(() -> {
+ try {
+ while (!mStopped) {
+ receiveMessage();
+ }
+ } catch (IOException e) {
+ if (!mStopped) {
+ Slog.w(TAG, "Trouble during transport", e);
+ stop();
+ }
+ }
+ }).start();
+ }
+
+ @Override
+ public void stop() {
+ mStopped = true;
+
+ IoUtils.closeQuietly(mRemoteIn);
+ IoUtils.closeQuietly(mRemoteOut);
+ }
+
+ @Override
+ protected void sendMessage(int message, int sequence, @NonNull byte[] data)
+ throws IOException {
+ if (DEBUG) {
+ Slog.e(TAG, "Sending message 0x" + Integer.toHexString(message)
+ + " sequence " + sequence + " length " + data.length
+ + " to association " + mAssociationId);
+ }
+
+ synchronized (mRemoteOut) {
+ final ByteBuffer header = ByteBuffer.allocate(HEADER_LENGTH)
+ .putInt(message)
+ .putInt(sequence)
+ .putInt(data.length);
+ mRemoteOut.write(header.array());
+ mRemoteOut.write(data);
+ mRemoteOut.flush();
+ }
+ }
+
+ private void receiveMessage() throws IOException {
+ final byte[] headerBytes = new byte[HEADER_LENGTH];
+ Streams.readFully(mRemoteIn, headerBytes);
+ final ByteBuffer header = ByteBuffer.wrap(headerBytes);
+ final int message = header.getInt();
+ final int sequence = header.getInt();
+ final int length = header.getInt();
+ final byte[] data = new byte[length];
+ Streams.readFully(mRemoteIn, data);
+
+ handleMessage(message, sequence, data);
+ }
+}
diff --git a/services/companion/java/com/android/server/companion/transport/SecureTransport.java b/services/companion/java/com/android/server/companion/transport/SecureTransport.java
new file mode 100644
index 000000000000..cca08435c0a5
--- /dev/null
+++ b/services/companion/java/com/android/server/companion/transport/SecureTransport.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2023 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.companion.transport;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.os.ParcelFileDescriptor;
+import android.util.Slog;
+
+import com.android.server.companion.securechannel.AttestationVerifier;
+import com.android.server.companion.securechannel.SecureChannel;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Future;
+
+class SecureTransport extends Transport implements SecureChannel.Callback {
+ private final SecureChannel mSecureChannel;
+
+ private volatile boolean mShouldProcessRequests = false;
+
+ private final BlockingQueue<byte[]> mRequestQueue = new ArrayBlockingQueue<>(100);
+
+ SecureTransport(int associationId, ParcelFileDescriptor fd, Context context) {
+ super(associationId, fd, context);
+ mSecureChannel = new SecureChannel(mRemoteIn, mRemoteOut, this, context);
+ }
+
+ SecureTransport(int associationId, ParcelFileDescriptor fd, Context context,
+ byte[] preSharedKey, AttestationVerifier verifier) {
+ super(associationId, fd, context);
+ mSecureChannel = new SecureChannel(mRemoteIn, mRemoteOut, this, preSharedKey, verifier);
+ }
+
+ @Override
+ public void start() {
+ mSecureChannel.start();
+ }
+
+ @Override
+ public void stop() {
+ mSecureChannel.stop();
+ mShouldProcessRequests = false;
+ }
+
+ @Override
+ public Future<byte[]> requestForResponse(int message, byte[] data) {
+ // Check if channel is secured and start securing
+ if (!mShouldProcessRequests) {
+ Slog.d(TAG, "Establishing secure connection.");
+ try {
+ mSecureChannel.establishSecureConnection();
+ } catch (Exception e) {
+ Slog.w(TAG, "Failed to initiate secure channel handshake.", e);
+ onError(e);
+ }
+ }
+
+ return super.requestForResponse(message, data);
+ }
+
+ @Override
+ protected void sendMessage(int message, int sequence, @NonNull byte[] data)
+ throws IOException {
+ if (DEBUG) {
+ Slog.d(TAG, "Queueing message 0x" + Integer.toHexString(message)
+ + " sequence " + sequence + " length " + data.length
+ + " to association " + mAssociationId);
+ }
+
+ // Queue up a message to send
+ mRequestQueue.add(ByteBuffer.allocate(HEADER_LENGTH + data.length)
+ .putInt(message)
+ .putInt(sequence)
+ .putInt(data.length)
+ .put(data)
+ .array());
+ }
+
+ @Override
+ public void onSecureConnection() {
+ mShouldProcessRequests = true;
+ Slog.d(TAG, "Secure connection established.");
+
+ // TODO: find a better way to handle incoming requests than a dedicated thread.
+ new Thread(() -> {
+ try {
+ while (mShouldProcessRequests) {
+ byte[] request = mRequestQueue.poll();
+ if (request != null) {
+ mSecureChannel.sendSecureMessage(request);
+ }
+ }
+ } catch (IOException e) {
+ onError(e);
+ }
+ }).start();
+ }
+
+ @Override
+ public void onSecureMessageReceived(byte[] data) {
+ final ByteBuffer payload = ByteBuffer.wrap(data);
+ final int message = payload.getInt();
+ final int sequence = payload.getInt();
+ final int length = payload.getInt();
+ final byte[] content = new byte[length];
+ payload.get(content);
+
+ try {
+ handleMessage(message, sequence, content);
+ } catch (IOException error) {
+ onError(error);
+ }
+ }
+
+ @Override
+ public void onError(Throwable error) {
+ mShouldProcessRequests = false;
+ Slog.e(TAG, error.getMessage(), error);
+ }
+}
diff --git a/services/companion/java/com/android/server/companion/transport/Transport.java b/services/companion/java/com/android/server/companion/transport/Transport.java
new file mode 100644
index 000000000000..d69ce8909c74
--- /dev/null
+++ b/services/companion/java/com/android/server/companion/transport/Transport.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2023 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.companion.transport;
+
+import android.annotation.NonNull;
+import android.companion.IOnMessageReceivedListener;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.util.Slog;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.GuardedBy;
+
+import libcore.util.EmptyArray;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Future;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * This class represents the channel established between two devices.
+ */
+public abstract class Transport {
+ protected static final String TAG = "CDM_CompanionTransport";
+ protected static final boolean DEBUG = Build.IS_DEBUGGABLE;
+
+ static final int MESSAGE_REQUEST_PING = 0x63807378; // ?PIN
+ public static final int MESSAGE_REQUEST_PLATFORM_INFO = 0x63807073; // ?PFI
+ public static final int MESSAGE_REQUEST_CONTEXT_SYNC = 0x63678883; // ?CXS
+ public static final int MESSAGE_REQUEST_PERMISSION_RESTORE = 0x63826983; // ?RES
+
+ static final int MESSAGE_RESPONSE_SUCCESS = 0x33838567; // !SUC
+ static final int MESSAGE_RESPONSE_FAILURE = 0x33706573; // !FAI
+
+ protected static final int HEADER_LENGTH = 12;
+
+ protected final int mAssociationId;
+ protected final ParcelFileDescriptor mFd;
+ protected final InputStream mRemoteIn;
+ protected final OutputStream mRemoteOut;
+ protected final Context mContext;
+
+ /**
+ * Message type -> Listener
+ *
+ * For now, the transport only supports 1 listener for each message type. If there's a need in
+ * the future to allow multiple listeners to receive callbacks for the same message type, the
+ * value of the map can be a list.
+ */
+ private final Map<Integer, IOnMessageReceivedListener> mListeners;
+
+ private static boolean isRequest(int message) {
+ return (message & 0xFF000000) == 0x63000000;
+ }
+
+ private static boolean isResponse(int message) {
+ return (message & 0xFF000000) == 0x33000000;
+ }
+
+ @GuardedBy("mPendingRequests")
+ protected final SparseArray<CompletableFuture<byte[]>> mPendingRequests =
+ new SparseArray<>();
+ protected final AtomicInteger mNextSequence = new AtomicInteger();
+
+ Transport(int associationId, ParcelFileDescriptor fd, Context context) {
+ mAssociationId = associationId;
+ mFd = fd;
+ mRemoteIn = new ParcelFileDescriptor.AutoCloseInputStream(fd);
+ mRemoteOut = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
+ mContext = context;
+ mListeners = new HashMap<>();
+ }
+
+ /**
+ * Add a listener when a message is received for the message type
+ * @param message Message type
+ * @param listener Execute when a message with the type is received
+ */
+ public void addListener(int message, IOnMessageReceivedListener listener) {
+ mListeners.put(message, listener);
+ }
+
+ public int getAssociationId() {
+ return mAssociationId;
+ }
+
+ protected ParcelFileDescriptor getFd() {
+ return mFd;
+ }
+
+ public abstract void start();
+ public abstract void stop();
+ protected abstract void sendMessage(int message, int sequence, @NonNull byte[] data)
+ throws IOException;
+
+ /**
+ * Send a message
+ */
+ public void sendMessage(int message, @NonNull byte[] data) throws IOException {
+ sendMessage(message, mNextSequence.incrementAndGet(), data);
+ }
+
+ public Future<byte[]> requestForResponse(int message, byte[] data) {
+ if (DEBUG) Slog.d(TAG, "Requesting for response");
+ final int sequence = mNextSequence.incrementAndGet();
+ final CompletableFuture<byte[]> pending = new CompletableFuture<>();
+ synchronized (mPendingRequests) {
+ mPendingRequests.put(sequence, pending);
+ }
+
+ try {
+ sendMessage(message, sequence, data);
+ } catch (IOException e) {
+ synchronized (mPendingRequests) {
+ mPendingRequests.remove(sequence);
+ }
+ pending.completeExceptionally(e);
+ }
+
+ return pending;
+ }
+
+ protected final void handleMessage(int message, int sequence, @NonNull byte[] data)
+ throws IOException {
+ if (DEBUG) {
+ Slog.d(TAG, "Received message 0x" + Integer.toHexString(message)
+ + " sequence " + sequence + " length " + data.length
+ + " from association " + mAssociationId);
+ }
+
+ if (isRequest(message)) {
+ try {
+ processRequest(message, sequence, data);
+ } catch (IOException e) {
+ Slog.w(TAG, "Failed to respond to 0x" + Integer.toHexString(message), e);
+ }
+ } else if (isResponse(message)) {
+ processResponse(message, sequence, data);
+ } else {
+ Slog.w(TAG, "Unknown message 0x" + Integer.toHexString(message));
+ }
+ }
+
+ private void processRequest(int message, int sequence, byte[] data)
+ throws IOException {
+ switch (message) {
+ case MESSAGE_REQUEST_PING: {
+ sendMessage(MESSAGE_RESPONSE_SUCCESS, sequence, data);
+ break;
+ }
+ case MESSAGE_REQUEST_PLATFORM_INFO:
+ case MESSAGE_REQUEST_CONTEXT_SYNC: {
+ callback(message, data);
+ sendMessage(MESSAGE_RESPONSE_SUCCESS, sequence, EmptyArray.BYTE);
+ break;
+ }
+ case MESSAGE_REQUEST_PERMISSION_RESTORE: {
+ if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)
+ && !Build.isDebuggable()) {
+ Slog.w(TAG, "Restoring permissions only supported on watches");
+ sendMessage(MESSAGE_RESPONSE_FAILURE, sequence, EmptyArray.BYTE);
+ break;
+ }
+ try {
+ callback(message, data);
+ sendMessage(MESSAGE_RESPONSE_SUCCESS, sequence, EmptyArray.BYTE);
+ } catch (Exception e) {
+ Slog.w(TAG, "Failed to restore permissions");
+ sendMessage(MESSAGE_RESPONSE_FAILURE, sequence, EmptyArray.BYTE);
+ }
+ break;
+ }
+ default: {
+ Slog.w(TAG, "Unknown request 0x" + Integer.toHexString(message));
+ sendMessage(MESSAGE_RESPONSE_FAILURE, sequence, EmptyArray.BYTE);
+ break;
+ }
+ }
+ }
+
+ private void callback(int message, byte[] data) {
+ if (mListeners.containsKey(message)) {
+ try {
+ mListeners.get(message).onMessageReceived(getAssociationId(), data);
+ Slog.i(TAG, "Message 0x" + Integer.toHexString(message)
+ + " is received from associationId " + mAssociationId
+ + ", sending data length " + data.length + " to the listener.");
+ } catch (RemoteException ignored) {
+ }
+ }
+ }
+
+ private void processResponse(int message, int sequence, byte[] data) {
+ final CompletableFuture<byte[]> future;
+ synchronized (mPendingRequests) {
+ future = mPendingRequests.removeReturnOld(sequence);
+ }
+ if (future == null) {
+ Slog.w(TAG, "Ignoring unknown sequence " + sequence);
+ return;
+ }
+
+ switch (message) {
+ case MESSAGE_RESPONSE_SUCCESS: {
+ future.complete(data);
+ break;
+ }
+ case MESSAGE_RESPONSE_FAILURE: {
+ future.completeExceptionally(new RuntimeException("Remote failure"));
+ break;
+ }
+ default: {
+ Slog.w(TAG, "Ignoring unknown response 0x" + Integer.toHexString(message));
+ }
+ }
+ }
+}
diff --git a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
index e52f1d9c61db..1c4602803426 100644
--- a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
+++ b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
@@ -16,7 +16,6 @@
package com.android.server.companion.virtual;
-import static android.companion.virtual.VirtualDeviceParams.RECENTS_POLICY_ALLOW_IN_HOST_DEVICE_RECENTS;
import static android.content.pm.ActivityInfo.FLAG_CAN_DISPLAY_ON_REMOTE_DEVICES;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
@@ -29,7 +28,6 @@ import android.app.compat.CompatChanges;
import android.companion.virtual.VirtualDeviceManager.ActivityListener;
import android.companion.virtual.VirtualDeviceParams;
import android.companion.virtual.VirtualDeviceParams.ActivityPolicy;
-import android.companion.virtual.VirtualDeviceParams.RecentsPolicy;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
import android.content.ComponentName;
@@ -137,8 +135,8 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
new ArraySet<>();
@Nullable private final SecureWindowCallback mSecureWindowCallback;
@Nullable private final List<String> mDisplayCategories;
- @RecentsPolicy
- private final int mDefaultRecentsPolicy;
+
+ private final boolean mShowTasksInHostDeviceRecents;
/**
* Creates a window policy controller that is generic to the different use cases of virtual
@@ -166,7 +164,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
* virtual display.
* @param intentListenerCallback Callback that is called to intercept intents when matching
* passed in filters.
- * @param defaultRecentsPolicy a policy to indicate how to handle activities in recents.
+ * @param showTasksInHostDeviceRecents whether to show activities in recents on the host device.
*/
public GenericWindowPolicyController(int windowFlags, int systemWindowFlags,
@NonNull ArraySet<UserHandle> allowedUsers,
@@ -181,7 +179,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
@NonNull SecureWindowCallback secureWindowCallback,
@NonNull IntentListenerCallback intentListenerCallback,
@NonNull List<String> displayCategories,
- @RecentsPolicy int defaultRecentsPolicy) {
+ boolean showTasksInHostDeviceRecents) {
super();
mAllowedUsers = allowedUsers;
mAllowedCrossTaskNavigations = new ArraySet<>(allowedCrossTaskNavigations);
@@ -196,7 +194,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
mSecureWindowCallback = secureWindowCallback;
mIntentListenerCallback = intentListenerCallback;
mDisplayCategories = displayCategories;
- mDefaultRecentsPolicy = defaultRecentsPolicy;
+ mShowTasksInHostDeviceRecents = showTasksInHostDeviceRecents;
}
/**
@@ -337,7 +335,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
@Override
public boolean canShowTasksInHostDeviceRecents() {
- return (mDefaultRecentsPolicy & RECENTS_POLICY_ALLOW_IN_HOST_DEVICE_RECENTS) != 0;
+ return mShowTasksInHostDeviceRecents;
}
@Override
diff --git a/services/companion/java/com/android/server/companion/virtual/InputController.java b/services/companion/java/com/android/server/companion/virtual/InputController.java
index 21b51b1acef0..607439b79d91 100644
--- a/services/companion/java/com/android/server/companion/virtual/InputController.java
+++ b/services/companion/java/com/android/server/companion/virtual/InputController.java
@@ -88,7 +88,7 @@ class InputController {
*/
private static final int DEVICE_NAME_MAX_LENGTH = 80;
- final Object mLock;
+ final Object mLock = new Object();
/* Token -> file descriptor associations. */
@GuardedBy("mLock")
@@ -101,18 +101,17 @@ class InputController {
private final WindowManager mWindowManager;
private final DeviceCreationThreadVerifier mThreadVerifier;
- InputController(@NonNull Object lock, @NonNull Handler handler,
+ InputController(@NonNull Handler handler,
@NonNull WindowManager windowManager) {
- this(lock, new NativeWrapper(), handler, windowManager,
+ this(new NativeWrapper(), handler, windowManager,
// Verify that virtual devices are not created on the handler thread.
() -> !handler.getLooper().isCurrentThread());
}
@VisibleForTesting
- InputController(@NonNull Object lock, @NonNull NativeWrapper nativeWrapper,
+ InputController(@NonNull NativeWrapper nativeWrapper,
@NonNull Handler handler, @NonNull WindowManager windowManager,
@NonNull DeviceCreationThreadVerifier threadVerifier) {
- mLock = lock;
mHandler = handler;
mNativeWrapper = nativeWrapper;
mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
diff --git a/services/companion/java/com/android/server/companion/virtual/SensorController.java b/services/companion/java/com/android/server/companion/virtual/SensorController.java
index 7804ebf1583d..864fe0f5edc1 100644
--- a/services/companion/java/com/android/server/companion/virtual/SensorController.java
+++ b/services/companion/java/com/android/server/companion/virtual/SensorController.java
@@ -22,8 +22,11 @@ import android.companion.virtual.sensor.IVirtualSensorCallback;
import android.companion.virtual.sensor.VirtualSensor;
import android.companion.virtual.sensor.VirtualSensorConfig;
import android.companion.virtual.sensor.VirtualSensorEvent;
+import android.hardware.SensorDirectChannel;
import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
+import android.os.SharedMemory;
import android.util.ArrayMap;
import android.util.Slog;
@@ -36,6 +39,7 @@ import java.io.PrintWriter;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
+import java.util.concurrent.atomic.AtomicInteger;
/** Controls virtual sensors, including their lifecycle and sensor event dispatch. */
public class SensorController {
@@ -47,6 +51,8 @@ public class SensorController {
private static final int UNKNOWN_ERROR = (-2147483647 - 1); // INT32_MIN value
private static final int BAD_VALUE = -22;
+ private static AtomicInteger sNextDirectChannelHandle = new AtomicInteger(1);
+
private final Object mLock;
private final int mVirtualDeviceId;
@GuardedBy("mLock")
@@ -57,8 +63,6 @@ public class SensorController {
private final SensorManagerInternal mSensorManagerInternal;
private final VirtualDeviceManagerInternal mVdmInternal;
-
-
public SensorController(@NonNull Object lock, int virtualDeviceId,
@Nullable IVirtualSensorCallback virtualSensorCallback) {
mLock = lock;
@@ -97,7 +101,7 @@ public class SensorController {
throws SensorCreationException {
final int handle = mSensorManagerInternal.createRuntimeSensor(mVirtualDeviceId,
config.getType(), config.getName(),
- config.getVendor() == null ? "" : config.getVendor(),
+ config.getVendor() == null ? "" : config.getVendor(), config.getFlags(),
mRuntimeSensorCallback);
if (handle <= 0) {
throw new SensorCreationException("Received an invalid virtual sensor handle.");
@@ -212,6 +216,66 @@ public class SensorController {
}
return OK;
}
+
+ @Override
+ public int onDirectChannelCreated(ParcelFileDescriptor fd) {
+ if (mCallback == null) {
+ Slog.e(TAG, "No sensor callback for virtual deviceId " + mVirtualDeviceId);
+ return BAD_VALUE;
+ } else if (fd == null) {
+ Slog.e(TAG, "Received invalid ParcelFileDescriptor");
+ return BAD_VALUE;
+ }
+ final int channelHandle = sNextDirectChannelHandle.getAndIncrement();
+ SharedMemory sharedMemory = SharedMemory.fromFileDescriptor(fd);
+ try {
+ mCallback.onDirectChannelCreated(channelHandle, sharedMemory);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to call sensor callback: " + e);
+ return UNKNOWN_ERROR;
+ }
+ return channelHandle;
+ }
+
+ @Override
+ public void onDirectChannelDestroyed(int channelHandle) {
+ if (mCallback == null) {
+ Slog.e(TAG, "No sensor callback for virtual deviceId " + mVirtualDeviceId);
+ return;
+ }
+ try {
+ mCallback.onDirectChannelDestroyed(channelHandle);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to call sensor callback: " + e);
+ }
+ }
+
+ @Override
+ public int onDirectChannelConfigured(int channelHandle, int sensorHandle,
+ @SensorDirectChannel.RateLevel int rateLevel) {
+ if (mCallback == null) {
+ Slog.e(TAG, "No runtime sensor callback configured.");
+ return BAD_VALUE;
+ }
+ VirtualSensor sensor = mVdmInternal.getVirtualSensor(mVirtualDeviceId, sensorHandle);
+ if (sensor == null) {
+ Slog.e(TAG, "No sensor found for deviceId=" + mVirtualDeviceId
+ + " and sensor handle=" + sensorHandle);
+ return BAD_VALUE;
+ }
+ try {
+ mCallback.onDirectChannelConfigured(channelHandle, sensor, rateLevel, sensorHandle);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to call sensor callback: " + e);
+ return UNKNOWN_ERROR;
+ }
+ if (rateLevel == SensorDirectChannel.RATE_STOP) {
+ return OK;
+ } else {
+ // Use the sensor handle as a report token, i.e. a unique identifier of the sensor.
+ return sensorHandle;
+ }
+ }
}
@VisibleForTesting
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
index b4dcf43c2e1a..2d010cf66e9b 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
@@ -51,6 +51,10 @@ import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.graphics.PointF;
import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManagerGlobal;
+import android.hardware.display.DisplayManagerInternal;
+import android.hardware.display.IVirtualDisplayCallback;
+import android.hardware.display.VirtualDisplayConfig;
import android.hardware.input.VirtualDpadConfig;
import android.hardware.input.VirtualKeyEvent;
import android.hardware.input.VirtualKeyboardConfig;
@@ -82,6 +86,7 @@ import android.widget.Toast;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.BlockedAppStreamingActivity;
+import com.android.server.LocalServices;
import com.android.server.companion.virtual.GenericWindowPolicyController.RunningAppsChangedListener;
import com.android.server.companion.virtual.audio.VirtualAudioController;
@@ -100,6 +105,14 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
private static final String TAG = "VirtualDeviceImpl";
+ private static final int DEFAULT_VIRTUAL_DISPLAY_FLAGS =
+ DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC
+ | DisplayManager.VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT
+ | DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY
+ | DisplayManager.VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL
+ | DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH
+ | DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_FOCUS;
+
/**
* Timeout until {@link #launchPendingIntent} stops waiting for an activity to be launched.
*/
@@ -109,21 +122,29 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
private final Context mContext;
private final AssociationInfo mAssociationInfo;
+ private final VirtualDeviceManagerService mService;
private final PendingTrampolineCallback mPendingTrampolineCallback;
private final int mOwnerUid;
private final int mDeviceId;
+ // Thou shall not hold the mVirtualDeviceLock over the mInputController calls.
+ // Holding the lock can lead to lock inversion with GlobalWindowManagerLock.
+ // 1. After display is created the window manager calls into VDM during construction
+ // of display specific context to fetch device id corresponding to the display.
+ // mVirtualDeviceLock will be held while this is done.
+ // 2. InputController interactions result in calls to DisplayManager (to set IME,
+ // possibly more indirect calls), and those attempt to lock GlobalWindowManagerLock which
+ // creates lock inversion.
private final InputController mInputController;
private final SensorController mSensorController;
private final CameraAccessController mCameraAccessController;
private VirtualAudioController mVirtualAudioController;
- @VisibleForTesting
- final ArraySet<Integer> mVirtualDisplayIds = new ArraySet<>();
- private final OnDeviceCloseListener mOnDeviceCloseListener;
private final IBinder mAppToken;
private final VirtualDeviceParams mParams;
- private final Map<Integer, PowerManager.WakeLock> mPerDisplayWakelocks = new ArrayMap<>();
+ @GuardedBy("mVirtualDeviceLock")
+ private final SparseArray<VirtualDisplayWrapper> mVirtualDisplays = new SparseArray<>();
private final IVirtualDeviceActivityListener mActivityListener;
private final IVirtualDeviceSoundEffectListener mSoundEffectListener;
+ private final DisplayManagerGlobal mDisplayManager;
@GuardedBy("mVirtualDeviceLock")
private final Map<IBinder, IntentFilter> mIntentInterceptors = new ArrayMap<>();
@NonNull
@@ -174,21 +195,14 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
};
}
- /**
- * A mapping from the virtual display ID to its corresponding
- * {@link GenericWindowPolicyController}.
- */
- private final SparseArray<GenericWindowPolicyController> mWindowPolicyControllers =
- new SparseArray<>();
-
VirtualDeviceImpl(
Context context,
AssociationInfo associationInfo,
+ VirtualDeviceManagerService service,
IBinder token,
int ownerUid,
int deviceId,
CameraAccessController cameraAccessController,
- OnDeviceCloseListener onDeviceCloseListener,
PendingTrampolineCallback pendingTrampolineCallback,
IVirtualDeviceActivityListener activityListener,
IVirtualDeviceSoundEffectListener soundEffectListener,
@@ -197,40 +211,43 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
this(
context,
associationInfo,
+ service,
token,
ownerUid,
deviceId,
/* inputController= */ null,
/* sensorController= */ null,
cameraAccessController,
- onDeviceCloseListener,
pendingTrampolineCallback,
activityListener,
soundEffectListener,
runningAppsChangedCallback,
- params);
+ params,
+ DisplayManagerGlobal.getInstance());
}
@VisibleForTesting
VirtualDeviceImpl(
Context context,
AssociationInfo associationInfo,
+ VirtualDeviceManagerService service,
IBinder token,
int ownerUid,
int deviceId,
InputController inputController,
SensorController sensorController,
CameraAccessController cameraAccessController,
- OnDeviceCloseListener onDeviceCloseListener,
PendingTrampolineCallback pendingTrampolineCallback,
IVirtualDeviceActivityListener activityListener,
IVirtualDeviceSoundEffectListener soundEffectListener,
Consumer<ArraySet<Integer>> runningAppsChangedCallback,
- VirtualDeviceParams params) {
+ VirtualDeviceParams params,
+ DisplayManagerGlobal displayManager) {
super(PermissionEnforcer.fromContext(context));
UserHandle ownerUserHandle = UserHandle.getUserHandleForUid(ownerUid);
mContext = context.createContextAsUser(ownerUserHandle, 0);
mAssociationInfo = associationInfo;
+ mService = service;
mPendingTrampolineCallback = pendingTrampolineCallback;
mActivityListener = activityListener;
mSoundEffectListener = soundEffectListener;
@@ -239,9 +256,9 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
mDeviceId = deviceId;
mAppToken = token;
mParams = params;
+ mDisplayManager = displayManager;
if (inputController == null) {
mInputController = new InputController(
- mVirtualDeviceLock,
context.getMainThreadHandler(),
context.getSystemService(WindowManager.class));
} else {
@@ -259,7 +276,6 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
}
mCameraAccessController = cameraAccessController;
mCameraAccessController.startObservingIfNeeded();
- mOnDeviceCloseListener = onDeviceCloseListener;
try {
token.linkToDeath(this, 0);
} catch (RemoteException e) {
@@ -272,7 +288,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
* device.
*/
int getBaseVirtualDisplayFlags() {
- int flags = 0;
+ int flags = DEFAULT_VIRTUAL_DISPLAY_FLAGS;
if (mParams.getLockState() == VirtualDeviceParams.LOCK_STATE_ALWAYS_UNLOCKED) {
flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED;
}
@@ -331,9 +347,11 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
@Override // Binder call
public void launchPendingIntent(int displayId, PendingIntent pendingIntent,
ResultReceiver resultReceiver) {
- if (!mVirtualDisplayIds.contains(displayId)) {
- throw new SecurityException("Display ID " + displayId
- + " not found for this virtual device");
+ synchronized (mVirtualDeviceLock) {
+ if (!mVirtualDisplays.contains(displayId)) {
+ throw new SecurityException("Display ID " + displayId
+ + " not found for this virtual device");
+ }
}
if (pendingIntent.isActivity()) {
try {
@@ -383,24 +401,34 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
@EnforcePermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
public void close() {
super.close_enforcePermission();
+ // Remove about-to-be-closed virtual device from the service before butchering it.
+ mService.removeVirtualDevice(mDeviceId);
+
+ VirtualDisplayWrapper[] virtualDisplaysToBeReleased;
synchronized (mVirtualDeviceLock) {
- if (!mPerDisplayWakelocks.isEmpty()) {
- mPerDisplayWakelocks.forEach((displayId, wakeLock) -> {
- Slog.w(TAG, "VirtualDisplay " + displayId + " owned by UID " + mOwnerUid
- + " was not properly released");
- wakeLock.release();
- });
- mPerDisplayWakelocks.clear();
- }
if (mVirtualAudioController != null) {
mVirtualAudioController.stopListening();
mVirtualAudioController = null;
}
mLocaleList = null;
+ virtualDisplaysToBeReleased = new VirtualDisplayWrapper[mVirtualDisplays.size()];
+ for (int i = 0; i < mVirtualDisplays.size(); i++) {
+ virtualDisplaysToBeReleased[i] = mVirtualDisplays.valueAt(i);
+ }
+ mVirtualDisplays.clear();
mVirtualSensorList = null;
mVirtualSensors.clear();
}
- mOnDeviceCloseListener.onClose(mDeviceId);
+ // Destroy the display outside locked section.
+ for (VirtualDisplayWrapper virtualDisplayWrapper : virtualDisplaysToBeReleased) {
+ mDisplayManager.releaseVirtualDisplay(virtualDisplayWrapper.getToken());
+ // The releaseVirtualDisplay call above won't trigger
+ // VirtualDeviceImpl.onVirtualDisplayRemoved callback because we already removed the
+ // virtual device from the service - we release the other display-tied resources here
+ // with the guarantee it will be done exactly once.
+ releaseOwnedVirtualDisplayResources(virtualDisplayWrapper);
+ }
+
mAppToken.unlinkToDeath(this, 0);
mCameraAccessController.stopObservingIfNeeded();
@@ -429,11 +457,6 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
return mVirtualAudioController;
}
- @VisibleForTesting
- SparseArray<GenericWindowPolicyController> getWindowPolicyControllersForTesting() {
- return mWindowPolicyControllers;
- }
-
@Override // Binder call
@EnforcePermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
public void onAudioSessionStarting(int displayId,
@@ -441,7 +464,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
@Nullable IAudioConfigChangedCallback configChangedCallback) {
super.onAudioSessionStarting_enforcePermission();
synchronized (mVirtualDeviceLock) {
- if (!mVirtualDisplayIds.contains(displayId)) {
+ if (!mVirtualDisplays.contains(displayId)) {
throw new SecurityException(
"Cannot start audio session for a display not associated with this virtual "
+ "device");
@@ -449,7 +472,8 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
if (mVirtualAudioController == null) {
mVirtualAudioController = new VirtualAudioController(mContext);
- GenericWindowPolicyController gwpc = mWindowPolicyControllers.get(displayId);
+ GenericWindowPolicyController gwpc = mVirtualDisplays.get(
+ displayId).getWindowPolicyController();
mVirtualAudioController.startListening(gwpc, routingCallback,
configChangedCallback);
}
@@ -473,7 +497,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
public void createVirtualDpad(VirtualDpadConfig config, @NonNull IBinder deviceToken) {
super.createVirtualDpad_enforcePermission();
synchronized (mVirtualDeviceLock) {
- if (!mVirtualDisplayIds.contains(config.getAssociatedDisplayId())) {
+ if (!mVirtualDisplays.contains(config.getAssociatedDisplayId())) {
throw new SecurityException(
"Cannot create a virtual dpad for a display not associated with "
+ "this virtual device");
@@ -493,7 +517,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
public void createVirtualKeyboard(VirtualKeyboardConfig config, @NonNull IBinder deviceToken) {
super.createVirtualKeyboard_enforcePermission();
synchronized (mVirtualDeviceLock) {
- if (!mVirtualDisplayIds.contains(config.getAssociatedDisplayId())) {
+ if (!mVirtualDisplays.contains(config.getAssociatedDisplayId())) {
throw new SecurityException(
"Cannot create a virtual keyboard for a display not associated with "
+ "this virtual device");
@@ -515,7 +539,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
public void createVirtualMouse(VirtualMouseConfig config, @NonNull IBinder deviceToken) {
super.createVirtualMouse_enforcePermission();
synchronized (mVirtualDeviceLock) {
- if (!mVirtualDisplayIds.contains(config.getAssociatedDisplayId())) {
+ if (!mVirtualDisplays.contains(config.getAssociatedDisplayId())) {
throw new SecurityException(
"Cannot create a virtual mouse for a display not associated with this "
+ "virtual device");
@@ -536,7 +560,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
@NonNull IBinder deviceToken) {
super.createVirtualTouchscreen_enforcePermission();
synchronized (mVirtualDeviceLock) {
- if (!mVirtualDisplayIds.contains(config.getAssociatedDisplayId())) {
+ if (!mVirtualDisplays.contains(config.getAssociatedDisplayId())) {
throw new SecurityException(
"Cannot create a virtual touchscreen for a display not associated with "
+ "this virtual device");
@@ -566,7 +590,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
@NonNull IBinder deviceToken) {
super.createVirtualNavigationTouchpad_enforcePermission();
synchronized (mVirtualDeviceLock) {
- if (!mVirtualDisplayIds.contains(config.getAssociatedDisplayId())) {
+ if (!mVirtualDisplays.contains(config.getAssociatedDisplayId())) {
throw new SecurityException(
"Cannot create a virtual navigation touchpad for a display not associated "
+ "with this virtual device");
@@ -704,7 +728,8 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
try {
synchronized (mVirtualDeviceLock) {
mDefaultShowPointerIcon = showPointerIcon;
- for (int displayId : mVirtualDisplayIds) {
+ for (int i = 0; i < mVirtualDisplays.size(); i++) {
+ final int displayId = mVirtualDisplays.keyAt(i);
mInputController.setShowPointerIcon(mDefaultShowPointerIcon, displayId);
}
}
@@ -795,8 +820,8 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
fout.println(" mParams: " + mParams);
fout.println(" mVirtualDisplayIds: ");
synchronized (mVirtualDeviceLock) {
- for (int id : mVirtualDisplayIds) {
- fout.println(" " + id);
+ for (int i = 0; i < mVirtualDisplays.size(); i++) {
+ fout.println(" " + mVirtualDisplays.keyAt(i));
}
fout.println(" mDefaultShowPointerIcon: " + mDefaultShowPointerIcon);
}
@@ -804,61 +829,77 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
mSensorController.dump(fout);
}
- GenericWindowPolicyController createWindowPolicyController(
+ private GenericWindowPolicyController createWindowPolicyController(
@NonNull List<String> displayCategories) {
- synchronized (mVirtualDeviceLock) {
- final GenericWindowPolicyController gwpc =
- new GenericWindowPolicyController(FLAG_SECURE,
- SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
- getAllowedUserHandles(),
- mParams.getAllowedCrossTaskNavigations(),
- mParams.getBlockedCrossTaskNavigations(),
- mParams.getAllowedActivities(),
- mParams.getBlockedActivities(),
- mParams.getDefaultActivityPolicy(),
- createListenerAdapter(),
- this::onEnteringPipBlocked,
- this::onActivityBlocked,
- this::onSecureWindowShown,
- this::shouldInterceptIntent,
- displayCategories,
- mParams.getDefaultRecentsPolicy());
- gwpc.registerRunningAppsChangedListener(/* listener= */ this);
- return gwpc;
- }
+ final GenericWindowPolicyController gwpc =
+ new GenericWindowPolicyController(FLAG_SECURE,
+ SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
+ getAllowedUserHandles(),
+ mParams.getAllowedCrossTaskNavigations(),
+ mParams.getBlockedCrossTaskNavigations(),
+ mParams.getAllowedActivities(),
+ mParams.getBlockedActivities(),
+ mParams.getDefaultActivityPolicy(),
+ createListenerAdapter(),
+ this::onEnteringPipBlocked,
+ this::onActivityBlocked,
+ this::onSecureWindowShown,
+ this::shouldInterceptIntent,
+ displayCategories,
+ mParams.getDevicePolicy(
+ VirtualDeviceParams.POLICY_TYPE_RECENTS)
+ == VirtualDeviceParams.DEVICE_POLICY_DEFAULT);
+ gwpc.registerRunningAppsChangedListener(/* listener= */ this);
+ return gwpc;
}
- void onVirtualDisplayCreatedLocked(GenericWindowPolicyController gwpc, int displayId) {
+ int createVirtualDisplay(@NonNull VirtualDisplayConfig virtualDisplayConfig,
+ @NonNull IVirtualDisplayCallback callback, String packageName) {
+ GenericWindowPolicyController gwpc = createWindowPolicyController(
+ virtualDisplayConfig.getDisplayCategories());
+ DisplayManagerInternal displayManager = LocalServices.getService(
+ DisplayManagerInternal.class);
+ int displayId;
+ displayId = displayManager.createVirtualDisplay(virtualDisplayConfig, callback,
+ this, gwpc, packageName);
+ gwpc.setDisplayId(displayId);
+
synchronized (mVirtualDeviceLock) {
- if (displayId == Display.INVALID_DISPLAY) {
- return;
- }
- if (mVirtualDisplayIds.contains(displayId)) {
+ if (mVirtualDisplays.contains(displayId)) {
+ gwpc.unregisterRunningAppsChangedListener(this);
throw new IllegalStateException(
"Virtual device already has a virtual display with ID " + displayId);
}
- mVirtualDisplayIds.add(displayId);
- gwpc.setDisplayId(displayId);
- mWindowPolicyControllers.put(displayId, gwpc);
+ PowerManager.WakeLock wakeLock = createAndAcquireWakeLockForDisplay(displayId);
+ mVirtualDisplays.put(displayId, new VirtualDisplayWrapper(callback, gwpc, wakeLock));
+ }
+ final long token = Binder.clearCallingIdentity();
+ try {
mInputController.setShowPointerIcon(mDefaultShowPointerIcon, displayId);
mInputController.setPointerAcceleration(1f, displayId);
mInputController.setDisplayEligibilityForPointerCapture(/* isEligible= */ false,
displayId);
mInputController.setLocalIme(displayId);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ return displayId;
+ }
- if (mPerDisplayWakelocks.containsKey(displayId)) {
- Slog.e(TAG, "Not creating wakelock for displayId " + displayId);
- return;
- }
+ private PowerManager.WakeLock createAndAcquireWakeLockForDisplay(int displayId) {
+ final long token = Binder.clearCallingIdentity();
+ try {
PowerManager powerManager = mContext.getSystemService(PowerManager.class);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(
PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
TAG + ":" + displayId, displayId);
- mPerDisplayWakelocks.put(displayId, wakeLock);
wakeLock.acquire();
+ return wakeLock;
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
}
@@ -872,8 +913,10 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
}
private void onSecureWindowShown(int displayId, int uid) {
- if (!mVirtualDisplayIds.contains(displayId)) {
- return;
+ synchronized (mVirtualDeviceLock) {
+ if (!mVirtualDisplays.contains(displayId)) {
+ return;
+ }
}
// If a virtual display isn't secure, the screen can't be captured. Show a warning toast
@@ -888,55 +931,102 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
private ArraySet<UserHandle> getAllowedUserHandles() {
ArraySet<UserHandle> result = new ArraySet<>();
- DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
- UserManager userManager = mContext.getSystemService(UserManager.class);
- for (UserHandle profile : userManager.getAllProfiles()) {
- int nearbyAppStreamingPolicy = dpm.getNearbyAppStreamingPolicy(profile.getIdentifier());
- if (nearbyAppStreamingPolicy == NEARBY_STREAMING_ENABLED
- || nearbyAppStreamingPolicy == NEARBY_STREAMING_NOT_CONTROLLED_BY_POLICY) {
- result.add(profile);
- } else if (nearbyAppStreamingPolicy == NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY) {
- if (mParams.getUsersWithMatchingAccounts().contains(profile)) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
+ UserManager userManager = mContext.getSystemService(UserManager.class);
+ for (UserHandle profile : userManager.getAllProfiles()) {
+ int nearbyAppStreamingPolicy = dpm.getNearbyAppStreamingPolicy(
+ profile.getIdentifier());
+ if (nearbyAppStreamingPolicy == NEARBY_STREAMING_ENABLED
+ || nearbyAppStreamingPolicy == NEARBY_STREAMING_NOT_CONTROLLED_BY_POLICY) {
result.add(profile);
+ } else if (nearbyAppStreamingPolicy == NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY) {
+ if (mParams.getUsersWithMatchingAccounts().contains(profile)) {
+ result.add(profile);
+ }
}
}
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
return result;
}
- void onVirtualDisplayRemovedLocked(int displayId) {
+
+ void onVirtualDisplayRemoved(int displayId) {
+ /* This is callback invoked by VirtualDeviceManagerService when VirtualDisplay was released
+ * by DisplayManager (most probably caused by someone calling VirtualDisplay.close()).
+ * At this point, the display is already released, but we still need to release the
+ * corresponding wakeLock and unregister the RunningAppsChangedListener from corresponding
+ * WindowPolicyController.
+ *
+ * Note that when the display is destroyed during VirtualDeviceImpl.close() call,
+ * this callback won't be invoked because the display is removed from
+ * VirtualDeviceManagerService before any resources are released.
+ */
+ VirtualDisplayWrapper virtualDisplayWrapper;
synchronized (mVirtualDeviceLock) {
- if (!mVirtualDisplayIds.contains(displayId)) {
- throw new IllegalStateException(
- "Virtual device doesn't have a virtual display with ID " + displayId);
- }
- PowerManager.WakeLock wakeLock = mPerDisplayWakelocks.get(displayId);
- if (wakeLock != null) {
- wakeLock.release();
- mPerDisplayWakelocks.remove(displayId);
- }
- GenericWindowPolicyController gwpc = mWindowPolicyControllers.get(displayId);
- if (gwpc != null) {
- gwpc.unregisterRunningAppsChangedListener(/* listener= */ this);
- }
- mVirtualDisplayIds.remove(displayId);
- mWindowPolicyControllers.remove(displayId);
+ virtualDisplayWrapper = mVirtualDisplays.removeReturnOld(displayId);
+ }
+
+ if (virtualDisplayWrapper == null) {
+ throw new IllegalStateException(
+ "Virtual device doesn't have a virtual display with ID " + displayId);
}
+
+ releaseOwnedVirtualDisplayResources(virtualDisplayWrapper);
+
+ }
+
+ /**
+ * Release resources tied to virtual display owned by this VirtualDevice instance.
+ *
+ * Note that this method won't release the virtual display itself.
+ *
+ * @param virtualDisplayWrapper - VirtualDisplayWrapper to release resources for.
+ */
+ private void releaseOwnedVirtualDisplayResources(VirtualDisplayWrapper virtualDisplayWrapper) {
+ virtualDisplayWrapper.getWakeLock().release();
+ virtualDisplayWrapper.getWindowPolicyController().unregisterRunningAppsChangedListener(
+ this);
}
int getOwnerUid() {
return mOwnerUid;
}
+ ArraySet<Integer> getDisplayIds() {
+ synchronized (mVirtualDeviceLock) {
+ final int size = mVirtualDisplays.size();
+ ArraySet<Integer> arraySet = new ArraySet<>(size);
+ for (int i = 0; i < size; i++) {
+ arraySet.append(mVirtualDisplays.keyAt(i));
+ }
+ return arraySet;
+ }
+ }
+
+ @VisibleForTesting
+ GenericWindowPolicyController getDisplayWindowPolicyControllerForTest(int displayId) {
+ VirtualDisplayWrapper virtualDisplayWrapper;
+ synchronized (mVirtualDeviceLock) {
+ virtualDisplayWrapper = mVirtualDisplays.get(displayId);
+ }
+ return virtualDisplayWrapper != null ? virtualDisplayWrapper.getWindowPolicyController()
+ : null;
+ }
+
/**
* Returns true if an app with the given {@code uid} is currently running on this virtual
* device.
*/
boolean isAppRunningOnVirtualDevice(int uid) {
- final int size = mWindowPolicyControllers.size();
- for (int i = 0; i < size; i++) {
- if (mWindowPolicyControllers.valueAt(i).containsUid(uid)) {
- return true;
+ synchronized (mVirtualDeviceLock) {
+ for (int i = 0; i < mVirtualDisplays.size(); i++) {
+ if (mVirtualDisplays.valueAt(i).getWindowPolicyController().containsUid(uid)) {
+ return true;
+ }
}
}
return false;
@@ -957,11 +1047,9 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
Looper looper) {
synchronized (mVirtualDeviceLock) {
DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
- final int size = mWindowPolicyControllers.size();
- for (int i = 0; i < size; i++) {
- if (mWindowPolicyControllers.valueAt(i).containsUid(uid)) {
- int displayId = mWindowPolicyControllers.keyAt(i);
- Display display = displayManager.getDisplay(displayId);
+ for (int i = 0; i < mVirtualDisplays.size(); i++) {
+ if (mVirtualDisplays.valueAt(i).getWindowPolicyController().containsUid(uid)) {
+ Display display = displayManager.getDisplay(mVirtualDisplays.keyAt(i));
if (display != null && display.isValid()) {
Toast.makeText(mContext.createDisplayContext(display), looper, text,
duration).show();
@@ -972,7 +1060,9 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
}
boolean isDisplayOwnedByVirtualDevice(int displayId) {
- return mVirtualDisplayIds.contains(displayId);
+ synchronized (mVirtualDeviceLock) {
+ return mVirtualDisplays.contains(displayId);
+ }
}
void onEnteringPipBlocked(int uid) {
@@ -1016,10 +1106,6 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
}
}
- interface OnDeviceCloseListener {
- void onClose(int deviceId);
- }
-
interface PendingTrampolineCallback {
/**
* Called when the callback should start waiting for the given pending trampoline.
@@ -1073,4 +1159,31 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
+ ", displayId=" + mDisplayId + "}";
}
}
+
+ /** Data class wrapping resources tied to single virtual display. */
+ private static final class VirtualDisplayWrapper {
+ private final IVirtualDisplayCallback mToken;
+ private final GenericWindowPolicyController mWindowPolicyController;
+ private final PowerManager.WakeLock mWakeLock;
+
+ VirtualDisplayWrapper(@NonNull IVirtualDisplayCallback token,
+ @NonNull GenericWindowPolicyController windowPolicyController,
+ @NonNull PowerManager.WakeLock wakeLock) {
+ mToken = Objects.requireNonNull(token);
+ mWindowPolicyController = Objects.requireNonNull(windowPolicyController);
+ mWakeLock = Objects.requireNonNull(wakeLock);
+ }
+
+ GenericWindowPolicyController getWindowPolicyController() {
+ return mWindowPolicyController;
+ }
+
+ PowerManager.WakeLock getWakeLock() {
+ return mWakeLock;
+ }
+
+ IVirtualDisplayCallback getToken() {
+ return mToken;
+ }
+ }
}
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
index 9bb05a6bfe5d..3b1983f55fb6 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
@@ -37,7 +37,6 @@ import android.companion.virtual.VirtualDeviceParams;
import android.companion.virtual.sensor.VirtualSensor;
import android.content.Context;
import android.content.Intent;
-import android.hardware.display.DisplayManagerInternal;
import android.hardware.display.IVirtualDisplayCallback;
import android.hardware.display.VirtualDisplayConfig;
import android.os.Binder;
@@ -85,7 +84,7 @@ public class VirtualDeviceManagerService extends SystemService {
private final PendingTrampolineMap mPendingTrampolines = new PendingTrampolineMap(mHandler);
private static AtomicInteger sNextUniqueIndex = new AtomicInteger(
- VirtualDeviceManager.DEVICE_ID_DEFAULT + 1);
+ Context.DEVICE_ID_DEFAULT + 1);
/**
* Mapping from device IDs to virtual devices.
@@ -108,26 +107,26 @@ public class VirtualDeviceManagerService extends SystemService {
private final ActivityInterceptorCallback mActivityInterceptorCallback =
new ActivityInterceptorCallback() {
- @Nullable
- @Override
- public ActivityInterceptResult onInterceptActivityLaunch(@NonNull
- ActivityInterceptorInfo info) {
- if (info.getCallingPackage() == null) {
- return null;
- }
- PendingTrampoline pt = mPendingTrampolines.remove(info.getCallingPackage());
- if (pt == null) {
- return null;
- }
- pt.mResultReceiver.send(VirtualDeviceManager.LAUNCH_SUCCESS, null);
- ActivityOptions options = info.getCheckedOptions();
- if (options == null) {
- options = ActivityOptions.makeBasic();
- }
- return new ActivityInterceptResult(
- info.getIntent(), options.setLaunchDisplayId(pt.mDisplayId));
- }
- };
+ @Nullable
+ @Override
+ public ActivityInterceptResult onInterceptActivityLaunch(@NonNull
+ ActivityInterceptorInfo info) {
+ if (info.getCallingPackage() == null) {
+ return null;
+ }
+ PendingTrampoline pt = mPendingTrampolines.remove(info.getCallingPackage());
+ if (pt == null) {
+ return null;
+ }
+ pt.mResultReceiver.send(VirtualDeviceManager.LAUNCH_SUCCESS, null);
+ ActivityOptions options = info.getCheckedOptions();
+ if (options == null) {
+ options = ActivityOptions.makeBasic();
+ }
+ return new ActivityInterceptResult(
+ info.getIntent(), options.setLaunchDisplayId(pt.mDisplayId));
+ }
+ };
@Override
public void onStart() {
@@ -146,8 +145,8 @@ public class VirtualDeviceManagerService extends SystemService {
CharSequence deviceName = mVirtualDevices.valueAt(i).getDisplayName();
mVirtualDevices.valueAt(i).showToastWhereUidIsRunning(appUid,
getContext().getString(
- com.android.internal.R.string.vdm_camera_access_denied,
- deviceName),
+ com.android.internal.R.string.vdm_camera_access_denied,
+ deviceName),
Toast.LENGTH_LONG, Looper.myLooper());
}
}
@@ -193,34 +192,46 @@ public class VirtualDeviceManagerService extends SystemService {
}
}
- @VisibleForTesting
void removeVirtualDevice(int deviceId) {
synchronized (mVirtualDeviceManagerLock) {
mAppsOnVirtualDevices.remove(deviceId);
mVirtualDevices.remove(deviceId);
}
+
+ Intent i = new Intent(VirtualDeviceManager.ACTION_VIRTUAL_DEVICE_REMOVED);
+ i.putExtra(VirtualDeviceManager.EXTRA_VIRTUAL_DEVICE_ID, deviceId);
+ i.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ getContext().sendBroadcastAsUser(i, UserHandle.ALL);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
class VirtualDeviceManagerImpl extends IVirtualDeviceManager.Stub {
private final VirtualDeviceImpl.PendingTrampolineCallback mPendingTrampolineCallback =
new VirtualDeviceImpl.PendingTrampolineCallback() {
- @Override
- public void startWaitingForPendingTrampoline(PendingTrampoline pendingTrampoline) {
- PendingTrampoline existing = mPendingTrampolines.put(
- pendingTrampoline.mPendingIntent.getCreatorPackage(),
- pendingTrampoline);
- if (existing != null) {
- existing.mResultReceiver.send(
- VirtualDeviceManager.LAUNCH_FAILURE_NO_ACTIVITY, null);
- }
- }
+ @Override
+ public void startWaitingForPendingTrampoline(
+ PendingTrampoline pendingTrampoline) {
+ PendingTrampoline existing = mPendingTrampolines.put(
+ pendingTrampoline.mPendingIntent.getCreatorPackage(),
+ pendingTrampoline);
+ if (existing != null) {
+ existing.mResultReceiver.send(
+ VirtualDeviceManager.LAUNCH_FAILURE_NO_ACTIVITY, null);
+ }
+ }
- @Override
- public void stopWaitingForPendingTrampoline(PendingTrampoline pendingTrampoline) {
- mPendingTrampolines.remove(pendingTrampoline.mPendingIntent.getCreatorPackage());
- }
- };
+ @Override
+ public void stopWaitingForPendingTrampoline(
+ PendingTrampoline pendingTrampoline) {
+ mPendingTrampolines.remove(
+ pendingTrampoline.mPendingIntent.getCreatorPackage());
+ }
+ };
@Override // Binder call
public IVirtualDevice createVirtualDevice(
@@ -251,8 +262,9 @@ public class VirtualDeviceManagerService extends SystemService {
final Consumer<ArraySet<Integer>> runningAppsChangedCallback =
runningUids -> notifyRunningAppsChanged(deviceId, runningUids);
VirtualDeviceImpl virtualDevice = new VirtualDeviceImpl(getContext(),
- associationInfo, token, callingUid, deviceId, cameraAccessController,
- this::onDeviceClosed, mPendingTrampolineCallback, activityListener,
+ associationInfo, VirtualDeviceManagerService.this, token, callingUid,
+ deviceId, cameraAccessController,
+ mPendingTrampolineCallback, activityListener,
soundEffectListener, runningAppsChangedCallback, params);
mVirtualDevices.put(deviceId, virtualDevice);
return virtualDevice;
@@ -281,26 +293,9 @@ public class VirtualDeviceManagerService extends SystemService {
"uid " + callingUid
+ " is not the owner of the supplied VirtualDevice");
}
- GenericWindowPolicyController gwpc;
- final long token = Binder.clearCallingIdentity();
- try {
- gwpc = virtualDeviceImpl.createWindowPolicyController(
- virtualDisplayConfig.getDisplayCategories());
- } finally {
- Binder.restoreCallingIdentity(token);
- }
-
- DisplayManagerInternal displayManager = getLocalService(
- DisplayManagerInternal.class);
- int displayId = displayManager.createVirtualDisplay(virtualDisplayConfig, callback,
- virtualDevice, gwpc, packageName);
- final long tokenTwo = Binder.clearCallingIdentity();
- try {
- virtualDeviceImpl.onVirtualDisplayCreatedLocked(gwpc, displayId);
- } finally {
- Binder.restoreCallingIdentity(tokenTwo);
- }
+ int displayId = virtualDeviceImpl.createVirtualDisplay(virtualDisplayConfig, callback,
+ packageName);
mLocalService.onVirtualDisplayCreated(displayId);
return displayId;
}
@@ -332,7 +327,7 @@ public class VirtualDeviceManagerService extends SystemService {
@Override // Binder call
public int getDeviceIdForDisplayId(int displayId) {
if (displayId == Display.INVALID_DISPLAY || displayId == Display.DEFAULT_DISPLAY) {
- return VirtualDeviceManager.DEVICE_ID_DEFAULT;
+ return Context.DEVICE_ID_DEFAULT;
}
synchronized (mVirtualDeviceManagerLock) {
for (int i = 0; i < mVirtualDevices.size(); i++) {
@@ -342,7 +337,7 @@ public class VirtualDeviceManagerService extends SystemService {
}
}
}
- return VirtualDeviceManager.DEVICE_ID_DEFAULT;
+ return Context.DEVICE_ID_DEFAULT;
}
// Binder call
@@ -412,19 +407,6 @@ public class VirtualDeviceManagerService extends SystemService {
return null;
}
- private void onDeviceClosed(int deviceId) {
- removeVirtualDevice(deviceId);
- Intent i = new Intent(VirtualDeviceManager.ACTION_VIRTUAL_DEVICE_REMOVED);
- i.putExtra(VirtualDeviceManager.EXTRA_VIRTUAL_DEVICE_ID, deviceId);
- i.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- final long identity = Binder.clearCallingIdentity();
- try {
- getContext().sendBroadcastAsUser(i, UserHandle.ALL);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
@@ -512,9 +494,14 @@ public class VirtualDeviceManagerService extends SystemService {
@Override
public void onVirtualDisplayRemoved(IVirtualDevice virtualDevice, int displayId) {
final VirtualDisplayListener[] listeners;
+ VirtualDeviceImpl virtualDeviceImpl;
synchronized (mVirtualDeviceManagerLock) {
- ((VirtualDeviceImpl) virtualDevice).onVirtualDisplayRemovedLocked(displayId);
listeners = mVirtualDisplayListeners.toArray(new VirtualDisplayListener[0]);
+ virtualDeviceImpl = mVirtualDevices.get(
+ ((VirtualDeviceImpl) virtualDevice).getDeviceId());
+ }
+ if (virtualDeviceImpl != null) {
+ virtualDeviceImpl.onVirtualDisplayRemoved(displayId);
}
mHandler.post(() -> {
for (VirtualDisplayListener listener : listeners) {
@@ -599,16 +586,11 @@ public class VirtualDeviceManagerService extends SystemService {
@Override
public @NonNull ArraySet<Integer> getDisplayIdsForDevice(int deviceId) {
+ VirtualDeviceImpl virtualDevice;
synchronized (mVirtualDeviceManagerLock) {
- int size = mVirtualDevices.size();
- for (int i = 0; i < size; i++) {
- VirtualDeviceImpl device = mVirtualDevices.valueAt(i);
- if (device.getDeviceId() == deviceId) {
- return new ArraySet<>(device.mVirtualDisplayIds);
- }
- }
+ virtualDevice = mVirtualDevices.get(deviceId);
}
- return new ArraySet<>();
+ return virtualDevice == null ? new ArraySet<>() : virtualDevice.getDisplayIds();
}
@Override
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index 08ee6d76f284..61fc32d5fa15 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -169,6 +169,7 @@ public final class ContentCaptureManagerService extends
@GuardedBy("mLock") int mDevCfgTextChangeFlushingFrequencyMs;
@GuardedBy("mLock") int mDevCfgLogHistorySize;
@GuardedBy("mLock") int mDevCfgIdleUnbindTimeoutMs;
+ @GuardedBy("mLock") boolean mDevCfgDisableFlushForViewTreeAppearing;
private final Executor mDataShareExecutor = Executors.newCachedThreadPool();
private final Handler mHandler = new Handler(Looper.getMainLooper());
@@ -359,6 +360,8 @@ public final class ContentCaptureManagerService extends
case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE:
case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_TEXT_CHANGE_FLUSH_FREQUENCY:
case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_UNBIND_TIMEOUT:
+ case ContentCaptureManager
+ .DEVICE_CONFIG_PROPERTY_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING:
setFineTuneParamsFromDeviceConfig();
return;
default:
@@ -388,13 +391,20 @@ public final class ContentCaptureManagerService extends
DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_UNBIND_TIMEOUT,
(int) AbstractRemoteService.PERMANENT_BOUND_TIMEOUT_MS);
+ mDevCfgDisableFlushForViewTreeAppearing = DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
+ ContentCaptureManager
+ .DEVICE_CONFIG_PROPERTY_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING,
+ false);
if (verbose) {
Slog.v(TAG, "setFineTuneParamsFromDeviceConfig(): "
+ "bufferSize=" + mDevCfgMaxBufferSize
+ ", idleFlush=" + mDevCfgIdleFlushingFrequencyMs
+ ", textFluxh=" + mDevCfgTextChangeFlushingFrequencyMs
+ ", logHistory=" + mDevCfgLogHistorySize
- + ", idleUnbindTimeoutMs=" + mDevCfgIdleUnbindTimeoutMs);
+ + ", idleUnbindTimeoutMs=" + mDevCfgIdleUnbindTimeoutMs
+ + ", disableFlushForViewTreeAppearing="
+ + mDevCfgDisableFlushForViewTreeAppearing);
}
}
}
@@ -629,6 +639,7 @@ public final class ContentCaptureManagerService extends
}
@Override // from AbstractMasterSystemService
+ @GuardedBy("mLock")
protected void dumpLocked(String prefix, PrintWriter pw) {
super.dumpLocked(prefix, pw);
@@ -646,6 +657,8 @@ public final class ContentCaptureManagerService extends
pw.print(prefix2); pw.print("logHistorySize: "); pw.println(mDevCfgLogHistorySize);
pw.print(prefix2); pw.print("idleUnbindTimeoutMs: ");
pw.println(mDevCfgIdleUnbindTimeoutMs);
+ pw.print(prefix2); pw.print("disableFlushForViewTreeAppearing: ");
+ pw.println(mDevCfgDisableFlushForViewTreeAppearing);
pw.print(prefix); pw.println("Global Options:");
mGlobalContentCaptureOptions.dump(prefix2, pw);
}
@@ -1005,12 +1018,15 @@ public final class ContentCaptureManagerService extends
return null;
}
- final ContentCaptureOptions options = new ContentCaptureOptions(mDevCfgLoggingLevel,
- mDevCfgMaxBufferSize, mDevCfgIdleFlushingFrequencyMs,
- mDevCfgTextChangeFlushingFrequencyMs, mDevCfgLogHistorySize,
- whitelistedComponents);
- if (verbose) Slog.v(TAG, "getOptionsForPackage(" + packageName + "): " + options);
- return options;
+ synchronized (mLock) {
+ final ContentCaptureOptions options = new ContentCaptureOptions(mDevCfgLoggingLevel,
+ mDevCfgMaxBufferSize, mDevCfgIdleFlushingFrequencyMs,
+ mDevCfgTextChangeFlushingFrequencyMs, mDevCfgLogHistorySize,
+ mDevCfgDisableFlushForViewTreeAppearing,
+ whitelistedComponents);
+ if (verbose) Slog.v(TAG, "getOptionsForPackage(" + packageName + "): " + options);
+ return options;
+ }
}
@Override
diff --git a/services/core/java/android/os/BatteryStatsInternal.java b/services/core/java/android/os/BatteryStatsInternal.java
index 17ef9a232401..c6f63dd73a25 100644
--- a/services/core/java/android/os/BatteryStatsInternal.java
+++ b/services/core/java/android/os/BatteryStatsInternal.java
@@ -38,11 +38,13 @@ public abstract class BatteryStatsInternal {
public static final int CPU_WAKEUP_SUBSYSTEM_UNKNOWN = -1;
public static final int CPU_WAKEUP_SUBSYSTEM_ALARM = 1;
+ public static final int CPU_WAKEUP_SUBSYSTEM_WIFI = 2;
/** @hide */
@IntDef(prefix = {"CPU_WAKEUP_SUBSYSTEM_"}, value = {
CPU_WAKEUP_SUBSYSTEM_UNKNOWN,
CPU_WAKEUP_SUBSYSTEM_ALARM,
+ CPU_WAKEUP_SUBSYSTEM_WIFI,
})
@Retention(RetentionPolicy.SOURCE)
@interface CpuWakeupSubsystem {
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 669dcfc7424c..e9a7f205c519 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -153,6 +153,8 @@ public final class BatteryService extends SystemService {
private int mLastMaxChargingCurrent;
private int mLastMaxChargingVoltage;
private int mLastChargeCounter;
+ private int mLastBatteryCycleCount;
+ private int mLastCharingState;
private int mSequence = 1;
@@ -190,20 +192,21 @@ public final class BatteryService extends SystemService {
private ArrayDeque<Bundle> mBatteryLevelsEventQueue;
private long mLastBatteryLevelChangedSentMs;
- private Bundle mBatteryChangedOptions = BroadcastOptions.makeRemovingMatchingFilter(
- new IntentFilter(Intent.ACTION_BATTERY_CHANGED)).setDeferUntilActive(true)
+ private Bundle mBatteryChangedOptions = BroadcastOptions.makeBasic()
+ .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
+ .setDeferUntilActive(true)
.toBundle();
- private Bundle mPowerConnectedOptions = BroadcastOptions.makeRemovingMatchingFilter(
- new IntentFilter(Intent.ACTION_POWER_DISCONNECTED)).setDeferUntilActive(true)
+ /** Used for both connected/disconnected, so match using key */
+ private Bundle mPowerOptions = BroadcastOptions.makeBasic()
+ .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
+ .setDeliveryGroupMatchingKey("android", Intent.ACTION_POWER_CONNECTED)
+ .setDeferUntilActive(true)
.toBundle();
- private Bundle mPowerDisconnectedOptions = BroadcastOptions.makeRemovingMatchingFilter(
- new IntentFilter(Intent.ACTION_POWER_CONNECTED)).setDeferUntilActive(true)
- .toBundle();
- private Bundle mBatteryLowOptions = BroadcastOptions.makeRemovingMatchingFilter(
- new IntentFilter(Intent.ACTION_BATTERY_OKAY)).setDeferUntilActive(true)
- .toBundle();
- private Bundle mBatteryOkayOptions = BroadcastOptions.makeRemovingMatchingFilter(
- new IntentFilter(Intent.ACTION_BATTERY_LOW)).setDeferUntilActive(true)
+ /** Used for both low/okay, so match using key */
+ private Bundle mBatteryOptions = BroadcastOptions.makeBasic()
+ .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
+ .setDeliveryGroupMatchingKey("android", Intent.ACTION_BATTERY_OKAY)
+ .setDeferUntilActive(true)
.toBundle();
private MetricsLogger mMetricsLogger;
@@ -523,7 +526,9 @@ public final class BatteryService extends SystemService {
|| mHealthInfo.maxChargingCurrentMicroamps != mLastMaxChargingCurrent
|| mHealthInfo.maxChargingVoltageMicrovolts != mLastMaxChargingVoltage
|| mHealthInfo.batteryChargeCounterUah != mLastChargeCounter
- || mInvalidCharger != mLastInvalidCharger)) {
+ || mInvalidCharger != mLastInvalidCharger
+ || mHealthInfo.batteryCycleCount != mLastBatteryCycleCount
+ || mHealthInfo.chargingState != mLastCharingState)) {
if (mPlugType != mLastPlugType) {
if (mLastPlugType == BATTERY_PLUGGED_NONE) {
@@ -632,7 +637,7 @@ public final class BatteryService extends SystemService {
@Override
public void run() {
mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL, null,
- mPowerConnectedOptions);
+ mPowerOptions);
}
});
}
@@ -644,7 +649,7 @@ public final class BatteryService extends SystemService {
@Override
public void run() {
mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL, null,
- mPowerDisconnectedOptions);
+ mPowerOptions);
}
});
}
@@ -658,7 +663,7 @@ public final class BatteryService extends SystemService {
@Override
public void run() {
mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL, null,
- mBatteryLowOptions);
+ mBatteryOptions);
}
});
} else if (mSentLowBatteryBroadcast &&
@@ -671,7 +676,7 @@ public final class BatteryService extends SystemService {
@Override
public void run() {
mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL, null,
- mBatteryOkayOptions);
+ mBatteryOptions);
}
});
}
@@ -705,6 +710,8 @@ public final class BatteryService extends SystemService {
mLastChargeCounter = mHealthInfo.batteryChargeCounterUah;
mLastBatteryLevelCritical = mBatteryLevelCritical;
mLastInvalidCharger = mInvalidCharger;
+ mLastBatteryCycleCount = mHealthInfo.batteryCycleCount;
+ mLastCharingState = mHealthInfo.chargingState;
}
}
@@ -736,6 +743,8 @@ public final class BatteryService extends SystemService {
BatteryManager.EXTRA_MAX_CHARGING_VOLTAGE,
mHealthInfo.maxChargingVoltageMicrovolts);
intent.putExtra(BatteryManager.EXTRA_CHARGE_COUNTER, mHealthInfo.batteryChargeCounterUah);
+ intent.putExtra(BatteryManager.EXTRA_CYCLE_COUNT, mHealthInfo.batteryCycleCount);
+ intent.putExtra(BatteryManager.EXTRA_CHARGING_STATUS, mHealthInfo.chargingState);
if (DEBUG) {
Slog.d(TAG, "Sending ACTION_BATTERY_CHANGED. scale:" + BATTERY_SCALE
+ ", info:" + mHealthInfo.toString());
@@ -760,6 +769,8 @@ public final class BatteryService extends SystemService {
event.putInt(BatteryManager.EXTRA_TEMPERATURE, mHealthInfo.batteryTemperatureTenthsCelsius);
event.putInt(BatteryManager.EXTRA_CHARGE_COUNTER, mHealthInfo.batteryChargeCounterUah);
event.putLong(BatteryManager.EXTRA_EVENT_TIMESTAMP, now);
+ event.putInt(BatteryManager.EXTRA_CYCLE_COUNT, mHealthInfo.batteryCycleCount);
+ event.putInt(BatteryManager.EXTRA_CHARGING_STATUS, mHealthInfo.chargingState);
boolean queueWasEmpty = mBatteryLevelsEventQueue.isEmpty();
mBatteryLevelsEventQueue.add(event);
@@ -1200,6 +1211,11 @@ public final class BatteryService extends SystemService {
}
private final class Led {
+ // must match: config_notificationsBatteryLowBehavior in config.xml
+ static final int LOW_BATTERY_BEHAVIOR_DEFAULT = 0;
+ static final int LOW_BATTERY_BEHAVIOR_SOLID = 1;
+ static final int LOW_BATTERY_BEHAVIOR_FLASHING = 2;
+
private final LogicalLight mBatteryLight;
private final int mBatteryLowARGB;
@@ -1207,6 +1223,7 @@ public final class BatteryService extends SystemService {
private final int mBatteryFullARGB;
private final int mBatteryLedOn;
private final int mBatteryLedOff;
+ private final int mBatteryLowBehavior;
public Led(Context context, LightsManager lights) {
mBatteryLight = lights.getLight(LightsManager.LIGHT_ID_BATTERY);
@@ -1223,6 +1240,8 @@ public final class BatteryService extends SystemService {
com.android.internal.R.integer.config_notificationsBatteryLedOff);
mBatteryNearlyFullLevel = context.getResources().getInteger(
com.android.internal.R.integer.config_notificationsBatteryNearlyFullLevel);
+ mBatteryLowBehavior = context.getResources().getInteger(
+ com.android.internal.R.integer.config_notificationsBatteryLowBehavior);
}
/**
@@ -1235,13 +1254,26 @@ public final class BatteryService extends SystemService {
final int level = mHealthInfo.batteryLevel;
final int status = mHealthInfo.batteryStatus;
if (level < mLowBatteryWarningLevel) {
- if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
- // Solid red when battery is charging
- mBatteryLight.setColor(mBatteryLowARGB);
- } else {
- // Flash red when battery is low and not charging
- mBatteryLight.setFlashing(mBatteryLowARGB, LogicalLight.LIGHT_FLASH_TIMED,
- mBatteryLedOn, mBatteryLedOff);
+ switch (mBatteryLowBehavior) {
+ case LOW_BATTERY_BEHAVIOR_SOLID:
+ // Solid red when low battery
+ mBatteryLight.setColor(mBatteryLowARGB);
+ break;
+ case LOW_BATTERY_BEHAVIOR_FLASHING:
+ // Flash red when battery is low and not charging
+ mBatteryLight.setFlashing(mBatteryLowARGB, LogicalLight.LIGHT_FLASH_TIMED,
+ mBatteryLedOn, mBatteryLedOff);
+ break;
+ default:
+ if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
+ // Solid red when battery is charging
+ mBatteryLight.setColor(mBatteryLowARGB);
+ } else {
+ // Flash red when battery is low and not charging
+ mBatteryLight.setFlashing(mBatteryLowARGB,
+ LogicalLight.LIGHT_FLASH_TIMED, mBatteryLedOn, mBatteryLedOff);
+ }
+ break;
}
} else if (status == BatteryManager.BATTERY_STATUS_CHARGING
|| status == BatteryManager.BATTERY_STATUS_FULL) {
@@ -1278,11 +1310,20 @@ public final class BatteryService extends SystemService {
}
}
- // Reduced IBatteryPropertiesRegistrar that only implements getProperty for usage
- // in BatteryManager.
+ // Reduced IBatteryPropertiesRegistrar that implements getProperty for usage
+ // in BatteryManager and enforce permissions.
private final class BatteryPropertiesRegistrar extends IBatteryPropertiesRegistrar.Stub {
@Override
public int getProperty(int id, final BatteryProperty prop) throws RemoteException {
+ switch (id) {
+ case BatteryManager.BATTERY_PROPERTY_MANUFACTURING_DATE:
+ case BatteryManager.BATTERY_PROPERTY_FIRST_USAGE_DATE:
+ case BatteryManager.BATTERY_PROPERTY_CHARGING_POLICY:
+ case BatteryManager.BATTERY_PROPERTY_STATE_OF_HEALTH:
+ mContext.enforceCallingPermission(
+ android.Manifest.permission.BATTERY_STATS, null);
+ break;
+ }
return mHealthServiceWrapper.getProperty(id, prop);
}
@Override
diff --git a/services/core/java/com/android/server/BinaryTransparencyService.java b/services/core/java/com/android/server/BinaryTransparencyService.java
index 2992bf92e0a6..3ecf93328219 100644
--- a/services/core/java/com/android/server/BinaryTransparencyService.java
+++ b/services/core/java/com/android/server/BinaryTransparencyService.java
@@ -34,7 +34,6 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApexStagedEvent;
import android.content.pm.ApplicationInfo;
-import android.content.pm.Checksum;
import android.content.pm.IBackgroundInstallControlService;
import android.content.pm.IPackageManagerNative;
import android.content.pm.IStagedApexObserver;
@@ -117,14 +116,17 @@ public class BinaryTransparencyService extends SystemService {
@VisibleForTesting
static final String BINARY_HASH_ERROR = "SHA256HashError";
- static final int MEASURE_APEX_AND_MODULES = 1;
- static final int MEASURE_PRELOADS = 2;
- static final int MEASURE_NEW_MBAS = 3;
-
static final long RECORD_MEASUREMENTS_COOLDOWN_MS = 24 * 60 * 60 * 1000;
static final String APEX_PRELOAD_LOCATION_ERROR = "could-not-be-determined";
+ // Copy from the atom. Consistent for both ApexInfoGathered and MobileBundledAppInfoGathered.
+ static final int DIGEST_ALGORITHM_UNKNOWN = 0;
+ static final int DIGEST_ALGORITHM_CHUNKED_SHA256 = 1;
+ static final int DIGEST_ALGORITHM_CHUNKED_SHA512 = 2;
+ static final int DIGEST_ALGORITHM_VERITY_CHUNKED_SHA256 = 3;
+ static final int DIGEST_ALGORITHM_SHA256 = 4;
+
// used for indicating any type of error during MBA measurement
static final int MBA_STATUS_ERROR = 0;
// used for indicating factory condition preloads
@@ -226,9 +228,9 @@ public class BinaryTransparencyService extends SystemService {
appInfo.mbaStatus = mbaStatus;
// Only digest and split name are different between splits.
- Checksum checksum = measureApk(split.getPath());
- appInfo.digest = checksum.getValue();
- appInfo.digestAlgorithm = checksum.getType();
+ Digest digest = measureApk(split.getPath());
+ appInfo.digest = digest.value;
+ appInfo.digestAlgorithm = digest.algorithm;
results.add(appInfo);
}
@@ -260,10 +262,9 @@ public class BinaryTransparencyService extends SystemService {
* Perform basic measurement (i.e. content digest) on a given APK.
*
* @param apkPath The APK (or APEX, since it's also an APK) file to be measured.
- * @return a {@link android.content.pm.Checksum} with preferred digest algorithm type and
- * the checksum.
+ * @return a {@link #Digest} with preferred digest algorithm type and the value.
*/
- private @Nullable Checksum measureApk(@NonNull String apkPath) {
+ private @Nullable Digest measureApk(@NonNull String apkPath) {
// compute content digest
Map<Integer, byte[]> contentDigests = computeApkContentDigest(apkPath);
if (contentDigests == null) {
@@ -274,20 +275,20 @@ public class BinaryTransparencyService extends SystemService {
// And only one of them will be available per package.
if (contentDigests.containsKey(
ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA256)) {
- return new Checksum(
- Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256,
+ return new Digest(
+ DIGEST_ALGORITHM_CHUNKED_SHA256,
contentDigests.get(ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA256));
} else if (contentDigests.containsKey(
ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA512)) {
- return new Checksum(
- Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA512,
+ return new Digest(
+ DIGEST_ALGORITHM_CHUNKED_SHA512,
contentDigests.get(ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA512));
}
}
// When something went wrong, fall back to simple sha256.
byte[] digest = PackageUtils.computeSha256DigestForLargeFileAsBytes(apkPath,
PackageUtils.createLargeFileBuffer());
- return new Checksum(Checksum.TYPE_WHOLE_SHA256, digest);
+ return new Digest(DIGEST_ALGORITHM_SHA256, digest);
}
@@ -350,7 +351,7 @@ public class BinaryTransparencyService extends SystemService {
// lastly measure all newly installed MBAs
List<IBinaryTransparencyService.AppInfo> allMbaInfo =
collectAllSilentInstalledMbaInfo(packagesMeasured);
- for (IBinaryTransparencyService.AppInfo appInfo : allUpdatedPreloadInfo) {
+ for (IBinaryTransparencyService.AppInfo appInfo : allMbaInfo) {
packagesMeasured.putBoolean(appInfo.packageName, true);
writeAppInfoToLog(appInfo);
}
@@ -381,7 +382,7 @@ public class BinaryTransparencyService extends SystemService {
Slog.w(TAG, "Skipping the missing APK in " + pkg.getPath());
continue;
}
- Checksum apexChecksum = measureApk(pkg.getPath());
+ Digest apexChecksum = measureApk(pkg.getPath());
if (apexChecksum == null) {
Slog.w(TAG, "Skipping the missing APEX in " + pkg.getPath());
continue;
@@ -390,8 +391,8 @@ public class BinaryTransparencyService extends SystemService {
var apexInfo = new IBinaryTransparencyService.ApexInfo();
apexInfo.packageName = packageState.getPackageName();
apexInfo.longVersion = packageState.getVersionCode();
- apexInfo.digest = apexChecksum.getValue();
- apexInfo.digestAlgorithm = apexChecksum.getType();
+ apexInfo.digest = apexChecksum.value;
+ apexInfo.digestAlgorithm = apexChecksum.algorithm;
apexInfo.signerDigests =
computePackageSignerSha256Digests(packageState.getSigningInfo());
@@ -1691,4 +1692,14 @@ public class BinaryTransparencyService extends SystemService {
}
return slice.getList();
}
+
+ private static class Digest {
+ public int algorithm;
+ public byte[] value;
+
+ Digest(int algorithm, byte[] value) {
+ this.algorithm = algorithm;
+ this.value = value;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/DropBoxManagerService.java b/services/core/java/com/android/server/DropBoxManagerService.java
index 725ea5c1b3dd..19e5cb142cfd 100644
--- a/services/core/java/com/android/server/DropBoxManagerService.java
+++ b/services/core/java/com/android/server/DropBoxManagerService.java
@@ -79,6 +79,7 @@ import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.zip.GZIPOutputStream;
@@ -105,6 +106,10 @@ public final class DropBoxManagerService extends SystemService {
// Size beyond which to force-compress newly added entries.
private static final long COMPRESS_THRESHOLD_BYTES = 16_384;
+ // Tags that we should drop by default.
+ private static final List<String> DISABLED_BY_DEFAULT_TAGS =
+ List.of("data_app_wtf", "system_app_wtf", "system_server_wtf");
+
// TODO: This implementation currently uses one file per entry, which is
// inefficient for smallish entries -- consider using a single queue file
// per tag (or even globally) instead.
@@ -549,8 +554,13 @@ public final class DropBoxManagerService extends SystemService {
public boolean isTagEnabled(String tag) {
final long token = Binder.clearCallingIdentity();
try {
- return !"disabled".equals(Settings.Global.getString(
+ if (DISABLED_BY_DEFAULT_TAGS.contains(tag)) {
+ return "enabled".equals(Settings.Global.getString(
+ mContentResolver, Settings.Global.DROPBOX_TAG_PREFIX + tag));
+ } else {
+ return !"disabled".equals(Settings.Global.getString(
mContentResolver, Settings.Global.DROPBOX_TAG_PREFIX + tag));
+ }
} finally {
Binder.restoreCallingIdentity(token);
}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 02524925326e..e0d1c1e70b34 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -2753,6 +2753,8 @@ class StorageManagerService extends IStorageManager.Stub
enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
try {
+ int avgWriteAmount = 0;
+ int targetDirtyRatio = mTargetDirtyRatio;
int latestWrite = mVold.getWriteAmount();
if (latestWrite == -1) {
Slog.w(TAG, "Failed to get storage write record");
@@ -2765,11 +2767,12 @@ class StorageManagerService extends IStorageManager.Stub
// (first boot after OTA), We skip the smart idle maintenance
if (!needsCheckpoint() || !supportsBlockCheckpoint()) {
if (!refreshLifetimeConstraint() || !checkChargeStatus()) {
- return;
+ Slog.i(TAG, "Turn off gc_urgent based on checking lifetime and charge status");
+ targetDirtyRatio = 100;
+ } else {
+ avgWriteAmount = getAverageWriteAmount();
}
- int avgWriteAmount = getAverageWriteAmount();
-
Slog.i(TAG, "Set smart idle maintenance: " + "latest write amount: " +
latestWrite + ", average write amount: " + avgWriteAmount +
", min segment threshold: " + mMinSegmentsThreshold +
@@ -2777,10 +2780,10 @@ class StorageManagerService extends IStorageManager.Stub
", segment reclaim weight: " + mSegmentReclaimWeight +
", period(min): " + sSmartIdleMaintPeriod +
", min gc sleep time(ms): " + mMinGCSleepTime +
- ", target dirty ratio: " + mTargetDirtyRatio);
+ ", target dirty ratio: " + targetDirtyRatio);
mVold.setGCUrgentPace(avgWriteAmount, mMinSegmentsThreshold, mDirtyReclaimRate,
mSegmentReclaimWeight, sSmartIdleMaintPeriod,
- mMinGCSleepTime, mTargetDirtyRatio);
+ mMinGCSleepTime, targetDirtyRatio);
} else {
Slog.i(TAG, "Skipping smart idle maintenance - block based checkpoint in progress");
}
diff --git a/services/core/java/com/android/server/TEST_MAPPING b/services/core/java/com/android/server/TEST_MAPPING
index c5b0f0509c2b..c3dda71fdaaa 100644
--- a/services/core/java/com/android/server/TEST_MAPPING
+++ b/services/core/java/com/android/server/TEST_MAPPING
@@ -23,6 +23,18 @@
"file_patterns": ["NotificationManagerService\\.java"]
},
{
+ "name": "CtsScopedStorageCoreHostTest",
+ "file_patterns": ["StorageManagerService\\.java"]
+ },
+ {
+ "name": "CtsScopedStorageHostTest",
+ "file_patterns": ["StorageManagerService\\.java"]
+ },
+ {
+ "name": "CtsScopedStorageDeviceOnlyTest",
+ "file_patterns": ["StorageManagerService\\.java"]
+ },
+ {
"name": "FrameworksMockingServicesTests",
"options": [
{
@@ -63,18 +75,6 @@
],
"presubmit-large": [
{
- "name": "CtsScopedStorageCoreHostTest",
- "file_patterns": ["StorageManagerService\\.java"]
- },
- {
- "name": "CtsScopedStorageHostTest",
- "file_patterns": ["StorageManagerService\\.java"]
- },
- {
- "name": "CtsScopedStorageDeviceOnlyTest",
- "file_patterns": ["StorageManagerService\\.java"]
- },
- {
"name": "CtsContentTestCases",
"options": [
{
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index c16314b6a117..225afea3d1b7 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -38,6 +38,7 @@ import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.AppOpsManager;
+import android.app.BroadcastOptions;
import android.app.INotificationManager;
import android.app.Notification;
import android.app.NotificationManager;
@@ -195,6 +196,9 @@ public class AccountManagerService
private final IAccountAuthenticatorCache mAuthenticatorCache;
private static final String PRE_N_DATABASE_NAME = "accounts.db";
private static final Intent ACCOUNTS_CHANGED_INTENT;
+ private static final Bundle ACCOUNTS_CHANGED_OPTIONS = new BroadcastOptions()
+ .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
+ .toBundle();
private static final int SIGNATURE_CHECK_MISMATCH = 0;
private static final int SIGNATURE_CHECK_MATCH = 1;
@@ -1075,7 +1079,8 @@ public class AccountManagerService
Log.i(TAG, "the accountType= " + (accountType == null ? "" : accountType)
+ " changed with useCase=" + useCase + " for userId=" + userId
+ ", sending broadcast of " + ACCOUNTS_CHANGED_INTENT.getAction());
- mContext.sendBroadcastAsUser(ACCOUNTS_CHANGED_INTENT, new UserHandle(userId));
+ mContext.sendBroadcastAsUser(ACCOUNTS_CHANGED_INTENT, new UserHandle(userId),
+ null /* receiverPermission */, ACCOUNTS_CHANGED_OPTIONS);
}
private void sendAccountRemovedBroadcast(
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 3a93cb3052de..f90a3ce76e71 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -137,6 +137,7 @@ import android.app.PendingIntent;
import android.app.RemoteServiceException.ForegroundServiceDidNotStartInTimeException;
import android.app.Service;
import android.app.ServiceStartArgs;
+import android.app.StartForegroundCalledOnStoppedServiceException;
import android.app.admin.DevicePolicyEventLogger;
import android.app.compat.CompatChanges;
import android.app.usage.UsageEvents;
@@ -522,6 +523,7 @@ public final class ActiveServices {
final ArrayList<ServiceRecord> mStartingBackground = new ArrayList<>();
final ArrayMap<String, ActiveForegroundApp> mActiveForegroundApps = new ArrayMap<>();
+ final ArrayList<String> mPendingRemoveForegroundApps = new ArrayList<>();
boolean mActiveForegroundAppsChanged;
@@ -746,10 +748,13 @@ public final class ActiveServices {
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, boolean fgRequired, String callingPackage,
- @Nullable String callingFeatureId, final int userId)
+ @Nullable String callingFeatureId, final int userId, boolean isSdkSandboxService,
+ int sdkSandboxClientAppUid, String sdkSandboxClientAppPackage, String instanceName)
throws TransactionTooLargeException {
return startServiceLocked(caller, service, resolvedType, callingPid, callingUid, fgRequired,
- callingPackage, callingFeatureId, userId, BackgroundStartPrivileges.NONE);
+ callingPackage, callingFeatureId, userId, BackgroundStartPrivileges.NONE,
+ isSdkSandboxService, sdkSandboxClientAppUid, sdkSandboxClientAppPackage,
+ instanceName);
}
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
@@ -757,6 +762,17 @@ public final class ActiveServices {
String callingPackage, @Nullable String callingFeatureId, final int userId,
BackgroundStartPrivileges backgroundStartPrivileges)
throws TransactionTooLargeException {
+ return startServiceLocked(caller, service, resolvedType, callingPid, callingUid, fgRequired,
+ callingPackage, callingFeatureId, userId, backgroundStartPrivileges,
+ false /* isSdkSandboxService */, INVALID_UID, null, null);
+ }
+
+ ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
+ int callingPid, int callingUid, boolean fgRequired,
+ String callingPackage, @Nullable String callingFeatureId, final int userId,
+ BackgroundStartPrivileges backgroundStartPrivileges, boolean isSdkSandboxService,
+ int sdkSandboxClientAppUid, String sdkSandboxClientAppPackage, String instanceName)
+ throws TransactionTooLargeException {
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "startService: " + service
+ " type=" + resolvedType + " args=" + service.getExtras());
@@ -774,9 +790,9 @@ public final class ActiveServices {
callerFg = true;
}
- ServiceLookupResult res =
- retrieveServiceLocked(service, null, resolvedType, callingPackage,
- callingPid, callingUid, userId, true, callerFg, false, false, false);
+ ServiceLookupResult res = retrieveServiceLocked(service, instanceName, isSdkSandboxService,
+ sdkSandboxClientAppUid, sdkSandboxClientAppPackage, resolvedType, callingPackage,
+ callingPid, callingUid, userId, true, callerFg, false, false, null, false);
if (res == null) {
return null;
}
@@ -785,13 +801,17 @@ public final class ActiveServices {
? res.permission : "private to package");
}
-
- // TODO(short-service): This is inside startService() / startForegroundService().
- // Consider if there's anything special we have to do if these are called on an already-
- // running short-FGS... But given these APIs shouldn't change the FGS type, we likely
- // don't need to do anything. (If they would change the FGS type, we'd have to stop
- // the timeout)
ServiceRecord r = res.record;
+ // Note, when startService() or startForegroundService() is called on an already
+ // running SHORT_SERVICE FGS, the call will succeed (i.e. we won't throw
+ // ForegroundServiceStartNotAllowedException), even when the service is alerady timed
+ // out. This is because these APIs will essnetially only change the "started" state
+ // of the service, and it won't afect "the foreground-ness" of the service, or the type
+ // of the FGS.
+ // However, this call will still _not_ extend the SHORT_SERVICE timeout either.
+ // Also, if the app tries to change the type of the FGS later (using
+ // Service.startForeground()), at that point we will consult the BFSL check and the timeout
+ // and make the necessary decisions.
setFgsRestrictionLocked(callingPackage, callingPid, callingUid, service, r, userId,
backgroundStartPrivileges, false /* isBindService */);
@@ -800,16 +820,30 @@ public final class ActiveServices {
return null;
}
+ // For the SDK sandbox, we start the service on behalf of the client app.
+ final int appUid = isSdkSandboxService ? sdkSandboxClientAppUid : r.appInfo.uid;
+ final String appPackageName =
+ isSdkSandboxService ? sdkSandboxClientAppPackage : r.packageName;
+ int appTargetSdkVersion = r.appInfo.targetSdkVersion;
+ if (isSdkSandboxService) {
+ try {
+ appTargetSdkVersion = AppGlobals.getPackageManager().getApplicationInfo(
+ appPackageName, ActivityManagerService.STOCK_PM_FLAGS,
+ userId).targetSdkVersion;
+ } catch (RemoteException ignored) {
+ }
+ }
+
// If we're starting indirectly (e.g. from PendingIntent), figure out whether
// we're launching into an app in a background state. This keys off of the same
// idleness state tracking as e.g. O+ background service start policy.
- final boolean bgLaunch = !mAm.isUidActiveLOSP(r.appInfo.uid);
+ final boolean bgLaunch = !mAm.isUidActiveLOSP(appUid);
// If the app has strict background restrictions, we treat any bg service
// start analogously to the legacy-app forced-restrictions case, regardless
// of its target SDK version.
boolean forcedStandby = false;
- if (bgLaunch && appRestrictedAnyInBackground(r.appInfo.uid, r.packageName)) {
+ if (bgLaunch && appRestrictedAnyInBackground(appUid, appPackageName)) {
if (DEBUG_FOREGROUND_SERVICE) {
Slog.d(TAG, "Forcing bg-only service start only for " + r.shortInstanceName
+ " : bgLaunch=" + bgLaunch + " callerFg=" + callerFg);
@@ -839,7 +873,7 @@ public final class ActiveServices {
boolean forceSilentAbort = false;
if (fgRequired) {
final int mode = mAm.getAppOpsManager().checkOpNoThrow(
- AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName);
+ AppOpsManager.OP_START_FOREGROUND, appUid, appPackageName);
switch (mode) {
case AppOpsManager.MODE_ALLOWED:
case AppOpsManager.MODE_DEFAULT:
@@ -861,12 +895,12 @@ public final class ActiveServices {
}
// If this isn't a direct-to-foreground start, check our ability to kick off an
- // arbitrary service
+ // arbitrary service.
if (forcedStandby || (!r.startRequested && !fgRequired)) {
// Before going further -- if this app is not allowed to start services in the
// background, then at this point we aren't going to let it period.
- final int allowed = mAm.getAppStartModeLOSP(r.appInfo.uid, r.packageName,
- r.appInfo.targetSdkVersion, callingPid, false, false, forcedStandby);
+ final int allowed = mAm.getAppStartModeLOSP(appUid, appPackageName, appTargetSdkVersion,
+ callingPid, false, false, forcedStandby);
if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
Slog.w(TAG, "Background start not allowed: service "
+ service + " to " + r.shortInstanceName
@@ -890,7 +924,7 @@ public final class ActiveServices {
}
// This app knows it is in the new model where this operation is not
// allowed, so tell it what has happened.
- UidRecord uidRec = mAm.mProcessList.getUidRecordLOSP(r.appInfo.uid);
+ UidRecord uidRec = mAm.mProcessList.getUidRecordLOSP(appUid);
return new ComponentName("?", "app is in background uid " + uidRec);
}
}
@@ -899,10 +933,10 @@ public final class ActiveServices {
// an ordinary startService() or a startForegroundService(). Now, only require that
// the app follow through on the startForegroundService() -> startForeground()
// contract if it actually targets O+.
- if (r.appInfo.targetSdkVersion < Build.VERSION_CODES.O && fgRequired) {
+ if (appTargetSdkVersion < Build.VERSION_CODES.O && fgRequired) {
if (DEBUG_BACKGROUND_CHECK || DEBUG_FOREGROUND_SERVICE) {
Slog.i(TAG, "startForegroundService() but host targets "
- + r.appInfo.targetSdkVersion + " - not requiring startForeground()");
+ + appTargetSdkVersion + " - not requiring startForeground()");
}
fgRequired = false;
}
@@ -1376,7 +1410,8 @@ public final class ActiveServices {
}
int stopServiceLocked(IApplicationThread caller, Intent service,
- String resolvedType, int userId) {
+ String resolvedType, int userId, boolean isSdkSandboxService,
+ int sdkSandboxClientAppUid, String sdkSandboxClientAppPackage, String instanceName) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "stopService: " + service
+ " type=" + resolvedType);
@@ -1389,9 +1424,10 @@ public final class ActiveServices {
}
// If this service is active, make sure it is stopped.
- ServiceLookupResult r = retrieveServiceLocked(service, null, resolvedType, null,
+ ServiceLookupResult r = retrieveServiceLocked(service, instanceName, isSdkSandboxService,
+ sdkSandboxClientAppUid, sdkSandboxClientAppPackage, resolvedType, null,
Binder.getCallingPid(), Binder.getCallingUid(), userId, false, false, false, false,
- false);
+ null, false);
if (r != null) {
if (r.record != null) {
final long origId = Binder.clearCallingIdentity();
@@ -1657,13 +1693,14 @@ public final class ActiveServices {
if (smap != null) {
if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "Updating foreground apps for user "
+ smap.mUserId);
+ smap.mPendingRemoveForegroundApps.clear();
for (int i = smap.mActiveForegroundApps.size()-1; i >= 0; i--) {
ActiveForegroundApp aa = smap.mActiveForegroundApps.valueAt(i);
if (aa.mEndTime != 0) {
boolean canRemove = foregroundAppShownEnoughLocked(aa, now);
if (canRemove) {
// This was up for longer than the timeout, so just remove immediately.
- smap.mActiveForegroundApps.removeAt(i);
+ smap.mPendingRemoveForegroundApps.add(smap.mActiveForegroundApps.keyAt(i));
smap.mActiveForegroundAppsChanged = true;
continue;
}
@@ -1688,6 +1725,9 @@ public final class ActiveServices {
}
}
}
+ for(int i = smap.mPendingRemoveForegroundApps.size() - 1; i >= 0; i--) {
+ smap.mActiveForegroundApps.remove(smap.mPendingRemoveForegroundApps.get(i));
+ }
smap.removeMessages(ServiceMap.MSG_UPDATE_FOREGROUND_APPS);
if (nextUpdateTime < Long.MAX_VALUE) {
if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "Next update time in: "
@@ -2000,8 +2040,7 @@ public final class ActiveServices {
// suddenly disallow it.
// However, this would be very problematic if used with a short-FGS, so we
// explicitly disallow this combination.
- // TODO(short-service): Change to another exception type?
- throw new IllegalStateException(
+ throw new StartForegroundCalledOnStoppedServiceException(
"startForeground(SHORT_SERVICE) called on a service that's not"
+ " started.");
}
@@ -2029,6 +2068,9 @@ public final class ActiveServices {
foregroundServiceType == FOREGROUND_SERVICE_TYPE_SHORT_SERVICE;
final boolean isOldTypeShortFgsAndTimedOut = r.shouldTriggerShortFgsTimeout();
+ // If true, we skip the BFSL check.
+ boolean bypassBfslCheck = false;
+
if (r.isForeground && (isOldTypeShortFgs || isNewTypeShortFgs)) {
if (DEBUG_SHORT_SERVICE) {
Slog.i(TAG_SERVICE, String.format(
@@ -2059,9 +2101,6 @@ public final class ActiveServices {
if (isNewTypeShortFgs) {
// Only in this case, we extend the SHORT_SERVICE time out.
extendShortServiceTimeout = true;
- if (DEBUG_SHORT_SERVICE) {
- Slog.i(TAG_SERVICE, "Extending SHORT_SERVICE time out: " + r);
- }
} else {
// FGS type is changing from SHORT_SERVICE to another type when
// an app is allowed to start FGS, so this will succeed.
@@ -2069,8 +2108,20 @@ public final class ActiveServices {
// maybeUpdateShortFgsTrackingLocked().
}
} else {
- // We catch this case later, in the
- // "if (r.mAllowStartForeground == REASON_DENIED...)" block below.
+ if (isNewTypeShortFgs) {
+ // startForeground(SHORT_SERVICE) is called on an already running
+ // SHORT_SERVICE FGS, when BFSL is not allowed.
+ // In this case, the call should succeed
+ // (== ForegroundServiceStartNotAllowedException shouldn't be
+ // thrown), but the short service timeout shouldn't extend
+ // (== extendShortServiceTimeout should be false).
+ // We still do everything else -- e.g. we still need to update
+ // the notification.
+ bypassBfslCheck = true;
+ } else {
+ // We catch this case later, in the
+ // "if (r.mAllowStartForeground == REASON_DENIED...)" block below.
+ }
}
} else if (r.mStartForegroundCount == 0) {
@@ -2125,23 +2176,25 @@ public final class ActiveServices {
+ "location/camera/microphone access: service "
+ r.shortInstanceName);
}
- logFgsBackgroundStart(r);
- if (r.mAllowStartForeground == REASON_DENIED
- && isBgFgsRestrictionEnabledForService) {
- final String msg = "Service.startForeground() not allowed due to "
- + "mAllowStartForeground false: service "
- + r.shortInstanceName
- + (isOldTypeShortFgs ? " (Called on SHORT_SERVICE)" : "");
- Slog.w(TAG, msg);
- showFgsBgRestrictedNotificationLocked(r);
- updateServiceForegroundLocked(psr, true);
- ignoreForeground = true;
- logFGSStateChangeLocked(r,
- FOREGROUND_SERVICE_STATE_CHANGED__STATE__DENIED,
- 0, FGS_STOP_REASON_UNKNOWN, FGS_TYPE_POLICY_CHECK_UNKNOWN);
- if (CompatChanges.isChangeEnabled(FGS_START_EXCEPTION_CHANGE_ID,
- r.appInfo.uid)) {
- throw new ForegroundServiceStartNotAllowedException(msg);
+ if (!bypassBfslCheck) {
+ logFgsBackgroundStart(r);
+ if (r.mAllowStartForeground == REASON_DENIED
+ && isBgFgsRestrictionEnabledForService) {
+ final String msg = "Service.startForeground() not allowed due to "
+ + "mAllowStartForeground false: service "
+ + r.shortInstanceName
+ + (isOldTypeShortFgs ? " (Called on SHORT_SERVICE)" : "");
+ Slog.w(TAG, msg);
+ showFgsBgRestrictedNotificationLocked(r);
+ updateServiceForegroundLocked(psr, true);
+ ignoreForeground = true;
+ logFGSStateChangeLocked(r,
+ FOREGROUND_SERVICE_STATE_CHANGED__STATE__DENIED,
+ 0, FGS_STOP_REASON_UNKNOWN, FGS_TYPE_POLICY_CHECK_UNKNOWN);
+ if (CompatChanges.isChangeEnabled(FGS_START_EXCEPTION_CHANGE_ID,
+ r.appInfo.uid)) {
+ throw new ForegroundServiceStartNotAllowedException(msg);
+ }
}
}
@@ -2192,10 +2245,6 @@ public final class ActiveServices {
cancelForegroundNotificationLocked(r);
r.foregroundId = id;
}
-
- // TODO(short-service): Stop the short service timeout, if the type is changing
- // from short to non-short. (should we do it earlier?)
-
notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
r.foregroundNoti = notification;
r.foregroundServiceType = foregroundServiceType;
@@ -3084,11 +3133,17 @@ public final class ActiveServices {
unscheduleShortFgsTimeoutLocked(sr);
return;
}
- if (DEBUG_SHORT_SERVICE) {
- Slog.i(TAG_SERVICE, "Short FGS started: " + sr);
- }
- if (extendTimeout || !sr.hasShortFgsInfo()) {
+ final boolean isAlreadyShortFgs = sr.hasShortFgsInfo();
+
+ if (extendTimeout || !isAlreadyShortFgs) {
+ if (DEBUG_SHORT_SERVICE) {
+ if (isAlreadyShortFgs) {
+ Slog.i(TAG_SERVICE, "Extending SHORT_SERVICE time out: " + sr);
+ } else {
+ Slog.i(TAG_SERVICE, "Short FGS started: " + sr);
+ }
+ }
sr.setShortFgsInfo(SystemClock.uptimeMillis());
// We'll restart the timeout.
@@ -3098,6 +3153,10 @@ public final class ActiveServices {
ActivityManagerService.SERVICE_SHORT_FGS_TIMEOUT_MSG, sr);
mAm.mHandler.sendMessageAtTime(msg, sr.getShortFgsInfo().getTimeoutTime());
} else {
+ if (DEBUG_SHORT_SERVICE) {
+ Slog.w(TAG_SERVICE, "NOT extending SHORT_SERVICE time out: " + sr);
+ }
+
// We only (potentially) update the start command, start count, but not the timeout
// time.
// In this case, we keep the existing timeout running.
@@ -3131,7 +3190,7 @@ public final class ActiveServices {
try {
sr.app.getThread().scheduleTimeoutService(sr, sr.getShortFgsInfo().getStartId());
} catch (RemoteException e) {
- // TODO(short-service): Anything to do here?
+ Slog.w(TAG_SERVICE, "Exception from scheduleTimeoutService: " + e.toString());
}
// Schedule the procstate demotion timeout and ANR timeout.
{
@@ -3203,8 +3262,9 @@ public final class ActiveServices {
}
mAm.appNotResponding(sr.app, tr);
- // TODO(short-service): Make sure, if the FGS stops after this, the ANR dialog
- // disappears.
+ // TODO: Can we close the ANR dialog here, if it's still shown? Currently, the ANR
+ // dialog really doesn't remember the "cause" (especially if there have been multiple
+ // ANRs), so it's not doable.
}
}
@@ -3219,8 +3279,8 @@ public final class ActiveServices {
}
}
- // TODO(short-service): Hmm what is it? Should we stop the timeout here?
private void stopServiceAndUpdateAllowlistManagerLocked(ServiceRecord service) {
+ maybeStopShortFgsTimeoutLocked(service);
final ProcessServiceRecord psr = service.app.mServices;
psr.stopService(service);
psr.updateBoundClientUids();
@@ -5347,8 +5407,6 @@ public final class ActiveServices {
// Check to see if the service had been started as foreground, but being
// brought down before actually showing a notification. That is not allowed.
- // TODO(short-service): This is unlikely related to short-FGS, but I'm curious why it's
- // not allowed. Look into it.
if (r.fgRequired) {
Slog.w(TAG_SERVICE, "Bringing down service while still waiting for start foreground: "
+ r);
@@ -5419,6 +5477,7 @@ public final class ActiveServices {
cancelForegroundNotificationLocked(r);
final boolean exitingFg = r.isForeground;
if (exitingFg) {
+ maybeStopShortFgsTimeoutLocked(r);
decActiveForegroundAppLocked(smap, r);
synchronized (mAm.mProcessStats.mLock) {
ServiceState stracker = r.getTracker();
@@ -5442,8 +5501,6 @@ public final class ActiveServices {
mFGSLogger.logForegroundServiceStop(r.appInfo.uid, r);
}
mAm.updateForegroundServiceUsageStats(r.name, r.userId, false);
-
- // TODO(short-service): Make sure we stop the timeout by here.
}
r.isForeground = false;
@@ -7763,7 +7820,7 @@ public final class ActiveServices {
final int callerTargetSdkVersion = r.mRecentCallerApplicationInfo != null
? r.mRecentCallerApplicationInfo.targetSdkVersion : 0;
- // TODO(short-service): Log BFSL too.
+ // TODO(short-service): Log the UID capabilities (for BFSL) too, and also the procstate?
FrameworkStatsLog.write(FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED,
r.appInfo.uid,
r.shortInstanceName,
@@ -7813,7 +7870,8 @@ public final class ActiveServices {
r.mFgsNotificationShown ? 1 : 0,
durationMs,
r.mStartForegroundCount,
- fgsStopReasonToString(fgsStopReason));
+ fgsStopReasonToString(fgsStopReason),
+ r.foregroundServiceType);
}
private void updateNumForegroundServicesLocked() {
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index 44f475f92517..e3f00ded026f 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -129,6 +129,7 @@ final class ActivityManagerConstants extends ContentObserver {
static final String KEY_KILL_BG_RESTRICTED_CACHED_IDLE = "kill_bg_restricted_cached_idle";
static final String KEY_KILL_BG_RESTRICTED_CACHED_IDLE_SETTLE_TIME =
"kill_bg_restricted_cached_idle_settle_time";
+ static final String KEY_MAX_PREVIOUS_TIME = "max_previous_time";
/**
* Note this key is on {@link DeviceConfig#NAMESPACE_ACTIVITY_MANAGER_COMPONENT_ALIAS}.
* @see #mEnableComponentAlias
@@ -145,6 +146,9 @@ final class ActivityManagerConstants extends ContentObserver {
*/
static final String KEY_NETWORK_ACCESS_TIMEOUT_MS = "network_access_timeout_ms";
+ static final String KEY_USE_TIERED_CACHED_ADJ = "use_tiered_cached_adj";
+ static final String KEY_TIERED_CACHED_ADJ_DECAY_TIME = "tiered_cached_adj_decay_time";
+
private static final int DEFAULT_MAX_CACHED_PROCESSES = 32;
private static final boolean DEFAULT_PRIORITIZE_ALARM_BROADCASTS = true;
private static final long DEFAULT_FGSERVICE_MIN_SHOWN_TIME = 2*1000;
@@ -192,6 +196,7 @@ final class ActivityManagerConstants extends ContentObserver {
private static final float DEFAULT_FGS_START_DENIED_LOG_SAMPLE_RATE = 1; // 100%
private static final long DEFAULT_PROCESS_KILL_TIMEOUT_MS = 10 * 1000;
private static final long DEFAULT_NETWORK_ACCESS_TIMEOUT_MS = 200; // 0.2 sec
+ private static final long DEFAULT_MAX_PREVIOUS_TIME = 60 * 1000; // 60s
static final long DEFAULT_BACKGROUND_SETTLE_TIME = 60 * 1000;
static final long DEFAULT_KILL_BG_RESTRICTED_CACHED_IDLE_SETTLE_TIME_MS = 60 * 1000;
@@ -199,6 +204,9 @@ final class ActivityManagerConstants extends ContentObserver {
static final int DEFAULT_MAX_SERVICE_CONNECTIONS_PER_PROCESS = 3000;
+ private static final boolean DEFAULT_USE_TIERED_CACHED_ADJ = false;
+ private static final long DEFAULT_TIERED_CACHED_ADJ_DECAY_TIME = 60 * 1000;
+
/**
* Same as {@link TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED}
*/
@@ -534,6 +542,9 @@ final class ActivityManagerConstants extends ContentObserver {
public long TOP_TO_ALMOST_PERCEPTIBLE_GRACE_DURATION =
DEFAULT_TOP_TO_ALMOST_PERCEPTIBLE_GRACE_DURATION;
+ // How long a process can remain at previous oom_adj before dropping to cached
+ public static long MAX_PREVIOUS_TIME = DEFAULT_MAX_PREVIOUS_TIME;
+
/**
* The minimum time we allow between crashes, for us to consider this
* application to be bad and stop its services and reject broadcasts.
@@ -984,7 +995,7 @@ final class ActivityManagerConstants extends ContentObserver {
private static final String KEY_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION =
"enable_wait_for_finish_attach_application";
- private static final boolean DEFAULT_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION = false;
+ private static final boolean DEFAULT_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION = true;
/** @see #KEY_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION */
public volatile boolean mEnableWaitForFinishAttachApplication =
@@ -1006,6 +1017,12 @@ final class ActivityManagerConstants extends ContentObserver {
public volatile long mShortFgsAnrExtraWaitDuration =
DEFAULT_SHORT_FGS_ANR_EXTRA_WAIT_DURATION;
+ /** @see #KEY_USE_TIERED_CACHED_ADJ */
+ public boolean USE_TIERED_CACHED_ADJ = DEFAULT_USE_TIERED_CACHED_ADJ;
+
+ /** @see #KEY_TIERED_CACHED_ADJ_DECAY_TIME */
+ public long TIERED_CACHED_ADJ_DECAY_TIME = DEFAULT_TIERED_CACHED_ADJ_DECAY_TIME;
+
private final OnPropertiesChangedListener mOnDeviceConfigChangedListener =
new OnPropertiesChangedListener() {
@Override
@@ -1171,6 +1188,13 @@ final class ActivityManagerConstants extends ContentObserver {
case KEY_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION:
updateEnableWaitForFinishAttachApplication();
break;
+ case KEY_MAX_PREVIOUS_TIME:
+ updateMaxPreviousTime();
+ break;
+ case KEY_USE_TIERED_CACHED_ADJ:
+ case KEY_TIERED_CACHED_ADJ_DECAY_TIME:
+ updateUseTieredCachedAdj();
+ break;
default:
break;
}
@@ -1825,6 +1849,7 @@ final class ActivityManagerConstants extends ContentObserver {
DEFAULT_LOW_SWAP_THRESHOLD_PERCENT);
}
+
private void updateTopToFgsGraceDuration() {
TOP_TO_FGS_GRACE_DURATION = DeviceConfig.getLong(
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
@@ -1832,6 +1857,13 @@ final class ActivityManagerConstants extends ContentObserver {
DEFAULT_TOP_TO_FGS_GRACE_DURATION);
}
+ private void updateMaxPreviousTime() {
+ MAX_PREVIOUS_TIME = DeviceConfig.getLong(
+ DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ KEY_MAX_PREVIOUS_TIME,
+ DEFAULT_MAX_PREVIOUS_TIME);
+ }
+
private void updateMinAssocLogDuration() {
MIN_ASSOC_LOG_DURATION = DeviceConfig.getLong(
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_MIN_ASSOC_LOG_DURATION,
@@ -1908,6 +1940,17 @@ final class ActivityManagerConstants extends ContentObserver {
DEFAULT_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION);
}
+ private void updateUseTieredCachedAdj() {
+ USE_TIERED_CACHED_ADJ = DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ KEY_USE_TIERED_CACHED_ADJ,
+ DEFAULT_USE_TIERED_CACHED_ADJ);
+ TIERED_CACHED_ADJ_DECAY_TIME = DeviceConfig.getLong(
+ DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ KEY_TIERED_CACHED_ADJ_DECAY_TIME,
+ DEFAULT_TIERED_CACHED_ADJ_DECAY_TIME);
+ }
+
@NeverCompile // Avoid size overhead of debugging code.
void dump(PrintWriter pw) {
pw.println("ACTIVITY MANAGER SETTINGS (dumpsys activity settings) "
@@ -2092,6 +2135,11 @@ final class ActivityManagerConstants extends ContentObserver {
pw.print(" "); pw.print(KEY_SHORT_FGS_ANR_EXTRA_WAIT_DURATION);
pw.print("="); pw.println(mShortFgsAnrExtraWaitDuration);
+ pw.print(" "); pw.print(KEY_USE_TIERED_CACHED_ADJ);
+ pw.print("="); pw.println(USE_TIERED_CACHED_ADJ);
+ pw.print(" "); pw.print(KEY_TIERED_CACHED_ADJ_DECAY_TIME);
+ pw.print("="); pw.println(TIERED_CACHED_ADJ_DECAY_TIME);
+
pw.println();
if (mOverrideMaxCachedProcesses >= 0) {
pw.print(" mOverrideMaxCachedProcesses="); pw.println(mOverrideMaxCachedProcesses);
diff --git a/services/core/java/com/android/server/am/ActivityManagerLocal.java b/services/core/java/com/android/server/am/ActivityManagerLocal.java
index 3f0699002b1c..928af3fa4e81 100644
--- a/services/core/java/com/android/server/am/ActivityManagerLocal.java
+++ b/services/core/java/com/android/server/am/ActivityManagerLocal.java
@@ -17,8 +17,10 @@
package com.android.server.am;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Context.BindServiceFlags;
import android.content.Context.BindServiceFlagsBits;
@@ -68,9 +70,53 @@ public interface ActivityManagerLocal {
void tempAllowWhileInUsePermissionInFgs(int uid, long durationMs);
/**
- * Binds to a sdk sandbox service, creating it if needed. You can through the arguments
- * here have the system bring up multiple concurrent processes hosting their own instance of
- * that service. The {@code processName} you provide here identifies the different instances.
+ * Requests that an SDK sandbox service be started. If this service is not already running,
+ * it will be instantiated and started (creating a process for it if needed). You can through
+ * the arguments here have the system bring up multiple concurrent processes hosting their own
+ * instance of that service. Each instance is identified by the {@code processName} provided
+ * here.
+ *
+ * @param service Identifies the sdk sandbox process service to connect to. The Intent must
+ * specify an explicit component name. This value cannot be null.
+ * @param clientAppUid Uid of the app for which the sdk sandbox process needs to be spawned.
+ * @param clientAppPackage Package of the app for which the sdk sandbox process needs to
+ * be spawned. This package must belong to the clientAppUid.
+ * @param processName Unique identifier for the service instance. Each unique name here will
+ * result in a different service instance being created. Identifiers must only contain
+ * ASCII letters, digits, underscores, and periods.
+ *
+ * @throws RemoteException If the service could not be started.
+ * @return If the service is being started or is already running, the {@link ComponentName} of
+ * the actual service that was started is returned; else if the service does not exist null is
+ * returned.
+ */
+ @Nullable
+ @SuppressLint("RethrowRemoteException")
+ ComponentName startSdkSandboxService(@NonNull Intent service, int clientAppUid,
+ @NonNull String clientAppPackage, @NonNull String processName)
+ throws RemoteException;
+
+ // TODO(b/269592470): What if the sandbox is stopped while there is an active binding to it?
+ /**
+ * Requests that an SDK sandbox service with a given {@code processName} be stopped.
+ *
+ * @param service Identifies the sdk sandbox process service to connect to. The Intent must
+ * specify an explicit component name. This value cannot be null.
+ * @param clientAppUid Uid of the app for which the sdk sandbox process needs to be stopped.
+ * @param clientAppPackage Package of the app for which the sdk sandbox process needs to
+ * be stopped. This package must belong to the clientAppUid.
+ * @param processName Unique identifier for the service instance. Each unique name here will
+ * result in a different service instance being created. Identifiers must only contain
+ * ASCII letters, digits, underscores, and periods.
+ *
+ * @return If there is a service matching the given Intent that is already running, then it is
+ * stopped and true is returned; else false is returned.
+ */
+ boolean stopSdkSandboxService(@NonNull Intent service, int clientAppUid,
+ @NonNull String clientAppPackage, @NonNull String processName);
+
+ /**
+ * Binds to an SDK sandbox service for a given client application.
*
* @param service Identifies the sdk sandbox process service to connect to. The Intent must
* specify an explicit component name. This value cannot be null.
@@ -90,7 +136,7 @@ public interface ActivityManagerLocal {
* service that your client has permission to bind to; {@code false}
* if the system couldn't find the service or if your client doesn't
* have permission to bind to it.
- * @throws RemoteException If the service could not be brought up.
+ * @throws RemoteException If the service could not be bound to.
* @see Context#bindService(Intent, ServiceConnection, int)
*/
@SuppressLint("RethrowRemoteException")
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 2045cca8be16..1960c330cc73 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -32,7 +32,6 @@ import static android.app.ActivityManager.INSTR_FLAG_DISABLE_TEST_API_CHECKS;
import static android.app.ActivityManager.INSTR_FLAG_NO_RESTART;
import static android.app.ActivityManager.INTENT_SENDER_ACTIVITY;
import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL;
-import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
import static android.app.ActivityManager.PROCESS_STATE_TOP;
@@ -215,6 +214,7 @@ import android.app.PendingIntent;
import android.app.PendingIntentStats;
import android.app.ProcessMemoryState;
import android.app.ProfilerInfo;
+import android.app.ServiceStartNotAllowedException;
import android.app.SyncNotedAppOp;
import android.app.WaitResult;
import android.app.assist.ActivityId;
@@ -344,6 +344,7 @@ import android.util.FeatureFlagUtils;
import android.util.IndentingPrintWriter;
import android.util.IntArray;
import android.util.Log;
+import android.util.LogWriter;
import android.util.Pair;
import android.util.PrintWriterPrinter;
import android.util.Slog;
@@ -484,9 +485,11 @@ import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.BiFunction;
@@ -3327,7 +3330,6 @@ public class ActivityManagerService extends IActivityManager.Stub
}
mBatteryStatsService.noteProcessDied(app.info.uid, pid);
- mOomAdjuster.updateShortFgsOwner(app.info.uid, pid, false);
if (!app.isKilled()) {
if (!fromBinderDied) {
@@ -3523,7 +3525,7 @@ public class ActivityManagerService extends IActivityManager.Stub
// We'll take the stack crawls of just the top apps using CPU.
final int workingStatsNumber = processCpuTracker.countWorkingStats();
- for (int i = 0; i < workingStatsNumber && extraPids.size() < 5; i++) {
+ for (int i = 0; i < workingStatsNumber && extraPids.size() < 2; i++) {
ProcessCpuTracker.Stats stats = processCpuTracker.getWorkingStats(i);
if (lastPids.indexOfKey(stats.pid) >= 0) {
if (DEBUG_ANR) {
@@ -4926,14 +4928,8 @@ public class ActivityManagerService extends IActivityManager.Stub
EventLogTags.writeAmProcBound(app.userId, pid, app.processName);
synchronized (mProcLock) {
- app.mState.setCurAdj(ProcessList.INVALID_ADJ);
- app.mState.setSetAdj(ProcessList.INVALID_ADJ);
- app.mState.setVerifiedAdj(ProcessList.INVALID_ADJ);
- mOomAdjuster.setAttachingSchedGroupLSP(app);
- app.mState.setForcingToImportant(null);
+ mOomAdjuster.setAttachingProcessStatesLSP(app);
clearProcessForegroundLocked(app);
- app.mState.setHasShownUi(false);
- app.mState.setCached(false);
app.setDebugging(false);
app.setKilledByAm(false);
app.setKilled(false);
@@ -5101,8 +5097,14 @@ public class ActivityManagerService extends IActivityManager.Stub
app.makeActive(thread, mProcessStats);
checkTime(startTime, "attachApplicationLocked: immediately after bindApplication");
}
+ app.setPendingFinishAttach(true);
+
updateLruProcessLocked(app, false, null);
checkTime(startTime, "attachApplicationLocked: after updateLruProcessLocked");
+
+ updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_PROCESS_BEGIN);
+ checkTime(startTime, "attachApplicationLocked: after updateOomAdjLocked");
+
final long now = SystemClock.uptimeMillis();
synchronized (mAppProfiler.mProfilerLock) {
app.mProfile.setLastRequestedGc(now);
@@ -5118,8 +5120,6 @@ public class ActivityManagerService extends IActivityManager.Stub
if (!mConstants.mEnableWaitForFinishAttachApplication) {
finishAttachApplicationInner(startSeq, callingUid, pid);
- } else {
- app.setPendingFinishAttach(true);
}
} catch (Exception e) {
// We need kill the process group here. (b/148588589)
@@ -7001,36 +7001,6 @@ public class ActivityManagerService extends IActivityManager.Stub
}
/**
- * Allows apps to retrieve the MIME type of a URI.
- * If an app is in the same user as the ContentProvider, or if it is allowed to interact across
- * users, then it does not need permission to access the ContentProvider.
- * Either, it needs cross-user uri grants.
- *
- * CTS tests for this functionality can be run with "runtest cts-appsecurity".
- *
- * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
- * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
- *
- * @deprecated -- use getProviderMimeTypeAsync.
- */
- @Deprecated
- @Override
- public String getProviderMimeType(Uri uri, int userId) {
- return mCpHelper.getProviderMimeType(uri, userId);
- }
-
- /**
- * Allows apps to retrieve the MIME type of a URI.
- * If an app is in the same user as the ContentProvider, or if it is allowed to interact across
- * users, then it does not need permission to access the ContentProvider.
- * Either way, it needs cross-user uri grants.
- */
- @Override
- public void getProviderMimeTypeAsync(Uri uri, int userId, RemoteCallback resultCallback) {
- mCpHelper.getProviderMimeTypeAsync(uri, userId, resultCallback);
- }
-
- /**
* Filters calls to getType based on permission. If the caller has required permission,
* then it returns the contentProvider#getType.
* Else, it returns the contentProvider#getTypeAnonymous, which does not
@@ -13156,6 +13126,15 @@ public class ActivityManagerService extends IActivityManager.Stub
String resolvedType, boolean requireForeground, String callingPackage,
String callingFeatureId, int userId)
throws TransactionTooLargeException {
+ return startService(caller, service, resolvedType, requireForeground, callingPackage,
+ callingFeatureId, userId, false /* isSdkSandboxService */, INVALID_UID, null, null);
+ }
+
+ private ComponentName startService(IApplicationThread caller, Intent service,
+ String resolvedType, boolean requireForeground, String callingPackage,
+ String callingFeatureId, int userId, boolean isSdkSandboxService,
+ int sdkSandboxClientAppUid, String sdkSandboxClientAppPackage, String instanceName)
+ throws TransactionTooLargeException {
enforceNotIsolatedCaller("startService");
enforceAllowedToStartOrBindServiceIfSdkSandbox(service);
// Refuse possible leaked file descriptors
@@ -13167,6 +13146,11 @@ public class ActivityManagerService extends IActivityManager.Stub
throw new IllegalArgumentException("callingPackage cannot be null");
}
+ if (isSdkSandboxService && instanceName == null) {
+ throw new IllegalArgumentException("No instance name provided for SDK sandbox process");
+ }
+ validateServiceInstanceName(instanceName);
+
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
"*** startService: " + service + " type=" + resolvedType + " fg=" + requireForeground);
final int callingPid = Binder.getCallingPid();
@@ -13182,7 +13166,9 @@ public class ActivityManagerService extends IActivityManager.Stub
synchronized (this) {
res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid,
- requireForeground, callingPackage, callingFeatureId, userId);
+ requireForeground, callingPackage, callingFeatureId, userId,
+ isSdkSandboxService, sdkSandboxClientAppUid, sdkSandboxClientAppPackage,
+ instanceName);
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
@@ -13191,9 +13177,26 @@ public class ActivityManagerService extends IActivityManager.Stub
return res;
}
+ private void validateServiceInstanceName(String instanceName) {
+ // Ensure that instanceName, which is caller provided, does not contain
+ // unusual characters.
+ if (instanceName != null) {
+ if (!instanceName.matches("[a-zA-Z0-9_.]+")) {
+ throw new IllegalArgumentException("Illegal instanceName");
+ }
+ }
+ }
+
@Override
public int stopService(IApplicationThread caller, Intent service,
String resolvedType, int userId) {
+ return stopService(caller, service, resolvedType, userId, false /* isSdkSandboxService */,
+ INVALID_UID, null, null);
+ }
+
+ private int stopService(IApplicationThread caller, Intent service, String resolvedType,
+ int userId, boolean isSdkSandboxService,
+ int sdkSandboxClientAppUid, String sdkSandboxClientAppPackage, String instanceName) {
enforceNotIsolatedCaller("stopService");
// Refuse possible leaked file descriptors
if (service != null && service.hasFileDescriptors() == true) {
@@ -13205,7 +13208,9 @@ public class ActivityManagerService extends IActivityManager.Stub
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "stopService: " + service);
}
synchronized (this) {
- return mServices.stopServiceLocked(caller, service, resolvedType, userId);
+ return mServices.stopServiceLocked(caller, service, resolvedType, userId,
+ isSdkSandboxService, sdkSandboxClientAppUid, sdkSandboxClientAppPackage,
+ instanceName);
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
@@ -13364,17 +13369,7 @@ public class ActivityManagerService extends IActivityManager.Stub
throw new IllegalArgumentException("No instance name provided for isolated process");
}
- // Ensure that instanceName, which is caller provided, does not contain
- // unusual characters.
- if (instanceName != null) {
- for (int i = 0; i < instanceName.length(); ++i) {
- char c = instanceName.charAt(i);
- if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
- || (c >= '0' && c <= '9') || c == '_' || c == '.')) {
- throw new IllegalArgumentException("Illegal instanceName");
- }
- }
- }
+ validateServiceInstanceName(instanceName);
try {
if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
@@ -14511,7 +14506,7 @@ public class ActivityManagerService extends IActivityManager.Stub
brOptions.setDeferUntilActive(true);
}
- if (ordered && brOptions != null && brOptions.isDeferUntilActive()) {
+ if (mEnableModernQueue && ordered && brOptions != null && brOptions.isDeferUntilActive()) {
throw new IllegalArgumentException("Ordered broadcasts can't be deferred until active");
}
@@ -14687,9 +14682,6 @@ public class ActivityManagerService extends IActivityManager.Stub
sendPackageBroadcastLocked(cmd,
new String[] {ssp}, userId);
if (fullUninstall) {
- mAppOpsService.packageRemoved(
- intent.getIntExtra(Intent.EXTRA_UID, -1), ssp);
-
// Remove all permissions granted from/to this package
mUgmInternal.removeUriPermissionsForPackage(ssp, userId,
true, false);
@@ -16309,6 +16301,7 @@ public class ActivityManagerService extends IActivityManager.Stub
// TODO(b/111541062): This method is only used for updating OOM adjustments. We need to update
// the logic there and in mBatteryStatsService to make them aware of multiple resumed activities
+ @Nullable
ProcessRecord getTopApp() {
final WindowProcessController wpc = mAtmInternal != null ? mAtmInternal.getTopApp() : null;
final ProcessRecord r = wpc != null ? (ProcessRecord) wpc.mOwner : null;
@@ -17274,6 +17267,53 @@ public class ActivityManagerService extends IActivityManager.Stub
}
@Override
+ public ComponentName startSdkSandboxService(Intent service, int clientAppUid,
+ String clientAppPackage, String processName) throws RemoteException {
+ validateSdkSandboxParams(service, clientAppUid, clientAppPackage, processName);
+ // TODO(b/269598719): Is passing the application thread of the system_server alright?
+ // e.g. the sandbox getting privileged access due to this.
+ ComponentName cn = ActivityManagerService.this.startService(
+ mContext.getIApplicationThread(), service,
+ service.resolveTypeIfNeeded(mContext.getContentResolver()), false,
+ mContext.getOpPackageName(), mContext.getAttributionTag(),
+ UserHandle.getUserId(clientAppUid), true, clientAppUid, clientAppPackage,
+ processName);
+ if (cn != null) {
+ if (cn.getPackageName().equals("!")) {
+ throw new SecurityException(
+ "Not allowed to start service " + service
+ + " without permission " + cn.getClassName());
+ } else if (cn.getPackageName().equals("!!")) {
+ throw new SecurityException(
+ "Unable to start service " + service
+ + ": " + cn.getClassName());
+ } else if (cn.getPackageName().equals("?")) {
+ throw ServiceStartNotAllowedException.newInstance(false,
+ "Not allowed to start service " + service + ": "
+ + cn.getClassName());
+ }
+ }
+
+ return cn;
+ }
+
+ @Override
+ public boolean stopSdkSandboxService(Intent service, int clientAppUid,
+ String clientAppPackage, String processName) {
+ validateSdkSandboxParams(service, clientAppUid, clientAppPackage, processName);
+ int res = ActivityManagerService.this.stopService(
+ mContext.getIApplicationThread(), service,
+ service.resolveTypeIfNeeded(mContext.getContentResolver()),
+ UserHandle.getUserId(clientAppUid), true, clientAppUid, clientAppPackage,
+ processName);
+ if (res < 0) {
+ throw new SecurityException(
+ "Not allowed to stop service " + service);
+ }
+ return res != 0;
+ }
+
+ @Override
public boolean bindSdkSandboxService(Intent service, ServiceConnection conn,
int clientAppUid, IBinder clientApplicationThread, String clientAppPackage,
String processName, int flags)
@@ -17295,27 +17335,10 @@ public class ActivityManagerService extends IActivityManager.Stub
int clientAppUid, IBinder clientApplicationThread, String clientAppPackage,
String processName, long flags)
throws RemoteException {
- if (service == null) {
- throw new IllegalArgumentException("intent is null");
- }
+ validateSdkSandboxParams(service, clientAppUid, clientAppPackage, processName);
if (conn == null) {
throw new IllegalArgumentException("connection is null");
}
- if (clientAppPackage == null) {
- throw new IllegalArgumentException("clientAppPackage is null");
- }
- if (processName == null) {
- throw new IllegalArgumentException("processName is null");
- }
- if (service.getComponent() == null) {
- throw new IllegalArgumentException("service must specify explicit component");
- }
- if (!UserHandle.isApp(clientAppUid)) {
- throw new IllegalArgumentException("uid is not within application range");
- }
- if (mAppOpsService.checkPackage(clientAppUid, clientAppPackage) != MODE_ALLOWED) {
- throw new IllegalArgumentException("uid does not belong to provided package");
- }
Handler handler = mContext.getMainThreadHandler();
IApplicationThread clientApplicationThreadVerified = null;
@@ -17348,6 +17371,28 @@ public class ActivityManagerService extends IActivityManager.Stub
UserHandle.getUserId(clientAppUid)) != 0;
}
+ private void validateSdkSandboxParams(Intent service, int clientAppUid,
+ String clientAppPackage, String processName) {
+ if (service == null) {
+ throw new IllegalArgumentException("intent is null");
+ }
+ if (clientAppPackage == null) {
+ throw new IllegalArgumentException("clientAppPackage is null");
+ }
+ if (processName == null) {
+ throw new IllegalArgumentException("processName is null");
+ }
+ if (service.getComponent() == null) {
+ throw new IllegalArgumentException("service must specify explicit component");
+ }
+ if (!UserHandle.isApp(clientAppUid)) {
+ throw new IllegalArgumentException("uid is not within application range");
+ }
+ if (mAppOpsService.checkPackage(clientAppUid, clientAppPackage) != MODE_ALLOWED) {
+ throw new IllegalArgumentException("uid does not belong to provided package");
+ }
+ }
+
@Override
public boolean bindSdkSandboxService(Intent service, ServiceConnection conn,
int clientAppUid, String clientAppPackage, String processName, int flags)
@@ -18112,8 +18157,9 @@ public class ActivityManagerService extends IActivityManager.Stub
bOptions.setTemporaryAppAllowlist(mInternal.getBootTimeTempAllowListDuration(),
TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
PowerExemptionManager.REASON_LOCALE_CHANGED, "");
- bOptions.setRemoveMatchingFilter(
- new IntentFilter(Intent.ACTION_LOCALE_CHANGED));
+ bOptions.setDeliveryGroupPolicy(
+ BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT);
+ bOptions.setDeferUntilActive(true);
broadcastIntentLocked(null, null, null, intent, null, null, 0, null, null, null,
null, null, OP_NONE, bOptions.toBundle(), false, false, MY_PID,
SYSTEM_UID, Binder.getCallingUid(), Binder.getCallingPid(),
@@ -18672,23 +18718,6 @@ public class ActivityManagerService extends IActivityManager.Stub
}
@Override
- public boolean canHoldWakeLocksInDeepDoze(int uid, int procstate) {
- // This method is called with the PowerManager lock held. Do not hold AM here.
-
- // If the procstate is high enough, it's always allowed.
- if (procstate <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
- return true;
- }
- // IF it's too low, it's not allowed.
- if (procstate > PROCESS_STATE_IMPORTANT_FOREGROUND) {
- return false;
- }
- // If it's PROCESS_STATE_IMPORTANT_FOREGROUND, then we allow it only wheen the UID
- // has a SHORT_FGS.
- return mOomAdjuster.hasUidShortForegroundService(uid);
- }
-
- @Override
public boolean startProfileEvenWhenDisabled(@UserIdInt int userId) {
return mUserController.startProfile(userId, /* evenWhenDisabled= */ true,
/* unlockListener= */ null);
@@ -18839,10 +18868,11 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public void waitForBroadcastBarrier() {
- waitForBroadcastBarrier(/* printWriter= */ null, false);
+ waitForBroadcastBarrier(/* printWriter= */ null, false, false);
}
- public void waitForBroadcastBarrier(@Nullable PrintWriter pw, boolean flushBroadcastLoopers) {
+ public void waitForBroadcastBarrier(@Nullable PrintWriter pw,
+ boolean flushBroadcastLoopers, boolean flushApplicationThreads) {
enforceCallingPermission(permission.DUMP, "waitForBroadcastBarrier()");
if (flushBroadcastLoopers) {
BroadcastLoopers.waitForBarrier(pw);
@@ -18850,6 +18880,76 @@ public class ActivityManagerService extends IActivityManager.Stub
for (BroadcastQueue queue : mBroadcastQueues) {
queue.waitForBarrier(pw);
}
+ if (flushApplicationThreads) {
+ waitForApplicationBarrier(pw);
+ }
+ }
+
+ /**
+ * Wait for all pending {@link IApplicationThread} events to be processed in
+ * all currently running apps.
+ */
+ public void waitForApplicationBarrier(@Nullable PrintWriter pw) {
+ if (pw == null) {
+ pw = new PrintWriter(new LogWriter(Log.VERBOSE, TAG));
+ }
+
+ final CountDownLatch finishedLatch = new CountDownLatch(1);
+ final AtomicInteger pingCount = new AtomicInteger(0);
+ final AtomicInteger pongCount = new AtomicInteger(0);
+ final RemoteCallback pongCallback = new RemoteCallback((result) -> {
+ if (pongCount.incrementAndGet() == pingCount.get()) {
+ finishedLatch.countDown();
+ }
+ });
+
+ // Insert an extra "ping" as a sentinel value to guard us from finishing
+ // too quickly in parallel below
+ pingCount.incrementAndGet();
+
+ synchronized (mProcLock) {
+ final ArrayMap<String, SparseArray<ProcessRecord>> pmap =
+ mProcessList.getProcessNamesLOSP().getMap();
+ final int numProc = pmap.size();
+ for (int iProc = 0; iProc < numProc; iProc++) {
+ final SparseArray<ProcessRecord> apps = pmap.valueAt(iProc);
+ for (int iApp = 0, numApps = apps.size(); iApp < numApps; iApp++) {
+ final ProcessRecord app = apps.valueAt(iApp);
+ final IApplicationThread thread = app.getOnewayThread();
+ if (thread != null) {
+ mOomAdjuster.mCachedAppOptimizer.unfreezeTemporarily(app,
+ OomAdjuster.OOM_ADJ_REASON_NONE);
+ pingCount.incrementAndGet();
+ try {
+ thread.schedulePing(pongCallback);
+ } catch (RemoteException ignored) {
+ // When we failed to ping remote process, pretend as
+ // if we received the expected pong
+ pongCallback.sendResult(null);
+ }
+ }
+ }
+ }
+ }
+
+ // Now that we've dispatched all "ping" events above, we can send our
+ // "pong" sentinel value
+ pongCallback.sendResult(null);
+
+ // Wait for any remaining "pong" events to trickle in
+ for (int i = 0; i < 30; i++) {
+ try {
+ if (finishedLatch.await(1, TimeUnit.SECONDS)) {
+ pw.println("Finished application barriers!");
+ return;
+ } else {
+ pw.println("Waiting for application barriers, at " + pongCount.get() + " of "
+ + pingCount.get() + "...");
+ }
+ } catch (InterruptedException ignored) {
+ }
+ }
+ pw.println("Gave up waiting for application barriers!");
}
void setIgnoreDeliveryGroupPolicy(@NonNull String broadcastAction) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index aa9d4ccc61ab..523ed6923b26 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -19,7 +19,7 @@ package com.android.server.am;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
-import static android.app.ActivityManager.PROCESS_CAPABILITY_NETWORK;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
import static android.app.ActivityManagerInternal.ALLOW_NON_FULL;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM;
@@ -146,6 +146,7 @@ import java.util.Locale;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
@@ -358,6 +359,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
return runWaitForBroadcastIdle(pw);
case "wait-for-broadcast-barrier":
return runWaitForBroadcastBarrier(pw);
+ case "wait-for-application-barrier":
+ return runWaitForApplicationBarrier(pw);
case "set-ignore-delivery-group-policy":
return runSetIgnoreDeliveryGroupPolicy(pw);
case "clear-ignore-delivery-group-policy":
@@ -595,10 +598,14 @@ final class ActivityManagerShellCommand extends ShellCommand {
return 1;
}
- String mimeType = intent.getType();
- if (mimeType == null && intent.getData() != null
+ AtomicReference<String> mimeType = new AtomicReference<>(intent.getType());
+
+ if (mimeType.get() == null && intent.getData() != null
&& "content".equals(intent.getData().getScheme())) {
- mimeType = mInterface.getProviderMimeType(intent.getData(), mUserId);
+ mInterface.getMimeTypeFilterAsync(intent.getData(), mUserId,
+ new RemoteCallback(result -> {
+ mimeType.set(result.getPairValue());
+ }));
}
do {
@@ -611,8 +618,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
int userIdForQuery = mInternal.mUserController.handleIncomingUser(
Binder.getCallingPid(), Binder.getCallingUid(), mUserId, false,
ALLOW_NON_FULL, "ActivityManagerShellCommand", null);
- List<ResolveInfo> activities = mPm.queryIntentActivities(intent, mimeType, 0,
- userIdForQuery).getList();
+ List<ResolveInfo> activities = mPm.queryIntentActivities(intent, mimeType.get(),
+ 0, userIdForQuery).getList();
if (activities == null || activities.size() <= 0) {
getErrPrintWriter().println("Error: Intent does not match any activities: "
+ intent);
@@ -708,12 +715,12 @@ final class ActivityManagerShellCommand extends ShellCommand {
}
if (mWaitOption) {
result = mInternal.startActivityAndWait(null, SHELL_PACKAGE_NAME, null, intent,
- mimeType, null, null, 0, mStartFlags, profilerInfo,
+ mimeType.get(), null, null, 0, mStartFlags, profilerInfo,
options != null ? options.toBundle() : null, mUserId);
res = result.result;
} else {
res = mInternal.startActivityAsUserWithFeature(null, SHELL_PACKAGE_NAME, null,
- intent, mimeType, null, null, 0, mStartFlags, profilerInfo,
+ intent, mimeType.get(), null, null, 0, mStartFlags, profilerInfo,
options != null ? options.toBundle() : null, mUserId);
}
final long endTime = SystemClock.uptimeMillis();
@@ -2009,7 +2016,7 @@ final class ActivityManagerShellCommand extends ShellCommand {
int mask = PROCESS_CAPABILITY_FOREGROUND_LOCATION
| PROCESS_CAPABILITY_FOREGROUND_CAMERA
| PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
- | PROCESS_CAPABILITY_NETWORK;
+ | PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
while ((opt=getNextOption()) != null) {
if (opt.equals("--oom")) {
@@ -3327,16 +3334,24 @@ final class ActivityManagerShellCommand extends ShellCommand {
int runWaitForBroadcastBarrier(PrintWriter pw) throws RemoteException {
boolean flushBroadcastLoopers = false;
+ boolean flushApplicationThreads = false;
String opt;
while ((opt = getNextOption()) != null) {
if (opt.equals("--flush-broadcast-loopers")) {
flushBroadcastLoopers = true;
+ } else if (opt.equals("--flush-application-threads")) {
+ flushApplicationThreads = true;
} else {
getErrPrintWriter().println("Error: Unknown option: " + opt);
return -1;
}
}
- mInternal.waitForBroadcastBarrier(pw, flushBroadcastLoopers);
+ mInternal.waitForBroadcastBarrier(pw, flushBroadcastLoopers, flushApplicationThreads);
+ return 0;
+ }
+
+ int runWaitForApplicationBarrier(PrintWriter pw) throws RemoteException {
+ mInternal.waitForApplicationBarrier(pw);
return 0;
}
@@ -3531,9 +3546,14 @@ final class ActivityManagerShellCommand extends ShellCommand {
if (foregroundActivities) {
try {
int prcState = mIam.getUidProcessState(uid, "android");
- int topPid = mInternal.getTopApp().getPid();
- if (prcState == ProcessStateEnum.TOP && topPid == pid) {
- mPw.println("New foreground process: " + pid);
+ ProcessRecord topApp = mInternal.getTopApp();
+ if (topApp == null) {
+ mPw.println("No top app found");
+ } else {
+ int topPid = topApp.getPid();
+ if (prcState == ProcessStateEnum.TOP && topPid == pid) {
+ mPw.println("New foreground process: " + pid);
+ }
}
mPw.flush();
} catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/am/AnrHelper.java b/services/core/java/com/android/server/am/AnrHelper.java
index 463a2f84aa6b..16219cd5b2ea 100644
--- a/services/core/java/com/android/server/am/AnrHelper.java
+++ b/services/core/java/com/android/server/am/AnrHelper.java
@@ -49,7 +49,7 @@ class AnrHelper {
* this time, the information might be outdated. So we only the dump the unresponsive process
* instead of including other processes to avoid making the system more busy.
*/
- private static final long EXPIRED_REPORT_TIME_MS = TimeUnit.MINUTES.toMillis(1);
+ private static final long EXPIRED_REPORT_TIME_MS = TimeUnit.SECONDS.toMillis(10);
/**
* If the last ANR occurred within this given time, consider it's anomaly.
diff --git a/services/core/java/com/android/server/am/AppBatteryTracker.java b/services/core/java/com/android/server/am/AppBatteryTracker.java
index 661902579317..c2326f600dbb 100644
--- a/services/core/java/com/android/server/am/AppBatteryTracker.java
+++ b/services/core/java/com/android/server/am/AppBatteryTracker.java
@@ -1388,7 +1388,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
final int mDefaultBgCurrentDrainPowerComponent;
/**
- * Default value to {@link #mBgCurrentDrainExmptedTypes}.
+ * Default value to {@link #mBgCurrentDrainExemptedTypes}.
**/
final int mDefaultBgCurrentDrainExemptedTypes;
diff --git a/services/core/java/com/android/server/am/AppExitInfoTracker.java b/services/core/java/com/android/server/am/AppExitInfoTracker.java
index 32d20718c192..1ba326680fc2 100644
--- a/services/core/java/com/android/server/am/AppExitInfoTracker.java
+++ b/services/core/java/com/android/server/am/AppExitInfoTracker.java
@@ -674,7 +674,7 @@ public final class AppExitInfoTracker {
break;
}
}
- } catch (IOException | IllegalArgumentException | WireTypeMismatchException e) {
+ } catch (Exception e) {
Slog.w(TAG, "Error in loading historical app exit info from persistent storage: " + e);
} finally {
if (fin != null) {
diff --git a/services/core/java/com/android/server/am/AppProfiler.java b/services/core/java/com/android/server/am/AppProfiler.java
index 050ac194616f..ac2c725ce80d 100644
--- a/services/core/java/com/android/server/am/AppProfiler.java
+++ b/services/core/java/com/android/server/am/AppProfiler.java
@@ -1892,15 +1892,11 @@ public class AppProfiler {
}
long getCpuTimeForPid(int pid) {
- synchronized (mProcessCpuTracker) {
- return mProcessCpuTracker.getCpuTimeForPid(pid);
- }
+ return mProcessCpuTracker.getCpuTimeForPid(pid);
}
long getCpuDelayTimeForPid(int pid) {
- synchronized (mProcessCpuTracker) {
- return mProcessCpuTracker.getCpuDelayTimeForPid(pid);
- }
+ return mProcessCpuTracker.getCpuDelayTimeForPid(pid);
}
List<ProcessCpuTracker.Stats> getCpuStats(Predicate<ProcessCpuTracker.Stats> predicate) {
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 160756616907..0ee883f745ca 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -23,6 +23,7 @@ import static android.Manifest.permission.NETWORK_STACK;
import static android.Manifest.permission.POWER_SAVER;
import static android.Manifest.permission.UPDATE_DEVICE_STATS;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE;
@@ -479,9 +480,29 @@ public final class BatteryStatsService extends IBatteryStats.Stub
BatteryStatsService.this.noteJobsDeferred(uid, numDeferred, sinceLast);
}
+ private int transportToSubsystem(NetworkCapabilities nc) {
+ if (nc.hasTransport(TRANSPORT_WIFI)) {
+ return CPU_WAKEUP_SUBSYSTEM_WIFI;
+ }
+ return CPU_WAKEUP_SUBSYSTEM_UNKNOWN;
+ }
+
@Override
public void noteCpuWakingNetworkPacket(Network network, long elapsedMillis, int uid) {
- Slog.d(TAG, "Wakeup due to incoming packet on network " + network + " to uid " + uid);
+ if (uid < 0) {
+ Slog.e(TAG, "Invalid uid for waking network packet: " + uid);
+ return;
+ }
+ final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
+ final NetworkCapabilities nc = cm.getNetworkCapabilities(network);
+ final int subsystem = transportToSubsystem(nc);
+
+ if (subsystem == CPU_WAKEUP_SUBSYSTEM_UNKNOWN) {
+ Slog.wtf(TAG, "Could not map transport for network: " + network
+ + " while attributing wakeup by packet sent to uid: " + uid);
+ return;
+ }
+ noteCpuWakingActivity(subsystem, elapsedMillis, uid);
}
@Override
diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
index b942f4b96b21..841b61e8e81f 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
@@ -597,18 +597,6 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
final int cookie = traceBegin("enqueueBroadcast");
r.applySingletonPolicy(mService);
- final IntentFilter removeMatchingFilter = (r.options != null)
- ? r.options.getRemoveMatchingFilter() : null;
- if (removeMatchingFilter != null) {
- final Predicate<Intent> removeMatching = removeMatchingFilter.asPredicate();
- forEachMatchingBroadcast(QUEUE_PREDICATE_ANY, (testRecord, testIndex) -> {
- // We only allow caller to remove broadcasts they enqueued
- return (r.callingUid == testRecord.callingUid)
- && (r.userId == testRecord.userId)
- && removeMatching.test(testRecord.intent);
- }, mBroadcastConsumerSkipAndCanceled, true);
- }
-
applyDeliveryGroupPolicy(r);
r.enqueueTime = SystemClock.uptimeMillis();
@@ -909,6 +897,10 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
final IApplicationThread thread = app.getOnewayThread();
if (thread != null) {
try {
+ if (r.shareIdentity) {
+ mService.mPackageManagerInt.grantImplicitAccess(r.userId, r.intent,
+ UserHandle.getAppId(app.uid), r.callingUid, true);
+ }
if (receiver instanceof BroadcastFilter) {
notifyScheduleRegisteredReceiver(app, r, (BroadcastFilter) receiver);
thread.scheduleRegisteredReceiver(
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index 913f15149646..f4685f0f6125 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -1921,9 +1921,26 @@ public final class CachedAppOptimizer {
public void handleMessage(Message msg) {
switch (msg.what) {
case SET_FROZEN_PROCESS_MSG:
+ {
+ ProcessRecord proc = (ProcessRecord) msg.obj;
+ int pid = proc.getPid();
+ final String name = proc.processName;
synchronized (mAm) {
- freezeProcess((ProcessRecord) msg.obj);
+ freezeProcess(proc);
+ }
+ try {
+ // post-check to prevent deadlock
+ mProcLocksReader.handleBlockingFileLocks(this);
+ } catch (Exception e) {
+ Slog.e(TAG_AM, "Unable to check file locks for "
+ + name + "(" + pid + "): " + e);
+ synchronized (mAm) {
+ synchronized (mProcLock) {
+ unfreezeAppLSP(proc, OomAdjuster.OOM_ADJ_REASON_NONE);
+ }
+ }
}
+ }
break;
case REPORT_UNFREEZE_MSG:
int pid = msg.arg1;
@@ -2057,16 +2074,6 @@ public final class CachedAppOptimizer {
}
});
}
-
- try {
- // post-check to prevent deadlock
- mProcLocksReader.handleBlockingFileLocks(this);
- } catch (Exception e) {
- Slog.e(TAG_AM, "Unable to check file locks for " + name + "(" + pid + "): " + e);
- synchronized (mProcLock) {
- unfreezeAppLSP(proc, OomAdjuster.OOM_ADJ_REASON_NONE);
- }
- }
}
private void reportUnfreeze(int pid, int frozenDuration, String processName,
@@ -2123,22 +2130,25 @@ public final class CachedAppOptimizer {
if (DEBUG_FREEZER) {
Slog.d(TAG_AM, "Blocking file lock found: " + pids);
}
- synchronized (mProcLock) {
- int pid = pids.get(0);
- ProcessRecord app = mFrozenProcesses.get(pid);
- ProcessRecord pr;
- if (app != null) {
- for (int i = 1; i < pids.size(); i++) {
- int blocked = pids.get(i);
- synchronized (mAm.mPidsSelfLocked) {
- pr = mAm.mPidsSelfLocked.get(blocked);
- }
- if (pr != null && pr.mState.getCurAdj() < ProcessList.CACHED_APP_MIN_ADJ) {
- Slog.d(TAG_AM, app.processName + " (" + pid + ") blocks "
- + pr.processName + " (" + blocked + ")");
- // Found at least one blocked non-cached process
- unfreezeAppLSP(app, OomAdjuster.OOM_ADJ_REASON_NONE);
- break;
+ synchronized (mAm) {
+ synchronized (mProcLock) {
+ int pid = pids.get(0);
+ ProcessRecord app = mFrozenProcesses.get(pid);
+ ProcessRecord pr;
+ if (app != null) {
+ for (int i = 1; i < pids.size(); i++) {
+ int blocked = pids.get(i);
+ synchronized (mAm.mPidsSelfLocked) {
+ pr = mAm.mPidsSelfLocked.get(blocked);
+ }
+ if (pr != null
+ && pr.mState.getCurAdj() < ProcessList.CACHED_APP_MIN_ADJ) {
+ Slog.d(TAG_AM, app.processName + " (" + pid + ") blocks "
+ + pr.processName + " (" + blocked + ")");
+ // Found at least one blocked non-cached process
+ unfreezeAppLSP(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+ break;
+ }
}
}
}
diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java
index f721d69958f5..48df1494fbe8 100644
--- a/services/core/java/com/android/server/am/ContentProviderHelper.java
+++ b/services/core/java/com/android/server/am/ContentProviderHelper.java
@@ -969,122 +969,6 @@ public class ContentProviderHelper {
}
/**
- * Allows apps to retrieve the MIME type of a URI.
- * If an app is in the same user as the ContentProvider, or if it is allowed to interact across
- * users, then it does not need permission to access the ContentProvider.
- * Either, it needs cross-user uri grants.
- *
- * CTS tests for this functionality can be run with "runtest cts-appsecurity".
- *
- * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
- * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
- *
- * @deprecated -- use getProviderMimeTypeAsync.
- */
- @Deprecated
- String getProviderMimeType(Uri uri, int userId) {
- mService.enforceNotIsolatedCaller("getProviderMimeType");
- final String name = uri.getAuthority();
- final int callingUid = Binder.getCallingUid();
- final int callingPid = Binder.getCallingPid();
- final int safeUserId = mService.mUserController.unsafeConvertIncomingUser(userId);
- final long ident = canClearIdentity(callingPid, callingUid, safeUserId)
- ? Binder.clearCallingIdentity() : 0;
- final ContentProviderHolder holder;
- try {
- holder = getContentProviderExternalUnchecked(name, null /* token */, callingUid,
- "*getmimetype*", safeUserId);
- } finally {
- if (ident != 0) {
- Binder.restoreCallingIdentity(ident);
- }
- }
- try {
- if (isHolderVisibleToCaller(holder, callingUid, safeUserId)) {
- final IBinder providerConnection = holder.connection;
- final ComponentName providerName = holder.info.getComponentName();
- // Note: creating a new Runnable instead of using a lambda here since lambdas in
- // java provide no guarantee that there will be a new instance returned every call.
- // Hence, it's possible that a cached copy is returned and the ANR is executed on
- // the incorrect provider.
- final Runnable providerNotResponding = new Runnable() {
- @Override
- public void run() {
- Log.w(TAG, "Provider " + providerName + " didn't return from getType().");
- appNotRespondingViaProvider(providerConnection);
- }
- };
- mService.mHandler.postDelayed(providerNotResponding, 1000);
- try {
- final String type = holder.provider.getType(uri);
- return type;
- } finally {
- mService.mHandler.removeCallbacks(providerNotResponding);
- // We need to clear the identity to call removeContentProviderExternalUnchecked
- final long token = Binder.clearCallingIdentity();
- try {
- removeContentProviderExternalUnchecked(name, null /* token */, safeUserId);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
- }
- } catch (RemoteException e) {
- Log.w(TAG, "Content provider dead retrieving " + uri, e);
- return null;
- } catch (Exception e) {
- Log.w(TAG, "Exception while determining type of " + uri, e);
- return null;
- }
-
- return null;
- }
-
- /**
- * Allows apps to retrieve the MIME type of a URI.
- * If an app is in the same user as the ContentProvider, or if it is allowed to interact across
- * users, then it does not need permission to access the ContentProvider.
- * Either way, it needs cross-user uri grants.
- */
- void getProviderMimeTypeAsync(Uri uri, int userId, RemoteCallback resultCallback) {
- mService.enforceNotIsolatedCaller("getProviderMimeTypeAsync");
- final String name = uri.getAuthority();
- final int callingUid = Binder.getCallingUid();
- final int callingPid = Binder.getCallingPid();
- final int safeUserId = mService.mUserController.unsafeConvertIncomingUser(userId);
- final long ident = canClearIdentity(callingPid, callingUid, safeUserId)
- ? Binder.clearCallingIdentity() : 0;
- final ContentProviderHolder holder;
- try {
- holder = getContentProviderExternalUnchecked(name, null /* token */, callingUid,
- "*getmimetype*", safeUserId);
- } finally {
- if (ident != 0) {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
- try {
- if (isHolderVisibleToCaller(holder, callingUid, safeUserId)) {
- holder.provider.getTypeAsync(uri, new RemoteCallback(result -> {
- final long identity = Binder.clearCallingIdentity();
- try {
- removeContentProviderExternalUnchecked(name, null, safeUserId);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- resultCallback.sendResult(result);
- }));
- } else {
- resultCallback.sendResult(Bundle.EMPTY);
- }
- } catch (RemoteException e) {
- Log.w(TAG, "Content provider dead retrieving " + uri, e);
- resultCallback.sendResult(Bundle.EMPTY);
- }
- }
-
- /**
* Filters calls to getType based on permission. If the caller has required permission,
* then it returns the contentProvider#getType.
* Else, it returns the contentProvider#getTypeAnonymous, which does not
diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags
index 1534ff5651de..50841ae4488c 100644
--- a/services/core/java/com/android/server/am/EventLogTags.logtags
+++ b/services/core/java/com/android/server/am/EventLogTags.logtags
@@ -122,9 +122,9 @@ option java_package com.android.server.am
30091 um_user_visibility_changed (userId|1|5),(visible|1)
# Foreground service start/stop events.
-30100 am_foreground_service_start (User|1|5),(Component Name|3),(allowWhileInUse|1),(startReasonCode|3),(targetSdk|1|1),(callerTargetSdk|1|1),(notificationWasDeferred|1),(notificationShown|1),(durationMs|1|3),(startForegroundCount|1|1),(stopReason|3)
-30101 am_foreground_service_denied (User|1|5),(Component Name|3),(allowWhileInUse|1),(startReasonCode|3),(targetSdk|1|1),(callerTargetSdk|1|1),(notificationWasDeferred|1),(notificationShown|1),(durationMs|1|3),(startForegroundCount|1|1),(stopReason|3)
-30102 am_foreground_service_stop (User|1|5),(Component Name|3),(allowWhileInUse|1),(startReasonCode|3),(targetSdk|1|1),(callerTargetSdk|1|1),(notificationWasDeferred|1),(notificationShown|1),(durationMs|1|3),(startForegroundCount|1|1),(stopReason|3)
+30100 am_foreground_service_start (User|1|5),(Component Name|3),(allowWhileInUse|1),(startReasonCode|3),(targetSdk|1|1),(callerTargetSdk|1|1),(notificationWasDeferred|1),(notificationShown|1),(durationMs|1|3),(startForegroundCount|1|1),(stopReason|3),(fgsType|1)
+30101 am_foreground_service_denied (User|1|5),(Component Name|3),(allowWhileInUse|1),(startReasonCode|3),(targetSdk|1|1),(callerTargetSdk|1|1),(notificationWasDeferred|1),(notificationShown|1),(durationMs|1|3),(startForegroundCount|1|1),(stopReason|3),(fgsType|1)
+30102 am_foreground_service_stop (User|1|5),(Component Name|3),(allowWhileInUse|1),(startReasonCode|3),(targetSdk|1|1),(callerTargetSdk|1|1),(notificationWasDeferred|1),(notificationShown|1),(durationMs|1|3),(startForegroundCount|1|1),(stopReason|3),(fgsType|1)
# Intent Sender redirect for UserHandle.USER_CURRENT
30110 am_intent_sender_redirect_user (userId|1|5)
diff --git a/services/core/java/com/android/server/am/ForegroundServiceTypeLoggerModule.java b/services/core/java/com/android/server/am/ForegroundServiceTypeLoggerModule.java
index c0cb7d9f69e3..993595b4870d 100644
--- a/services/core/java/com/android/server/am/ForegroundServiceTypeLoggerModule.java
+++ b/services/core/java/com/android/server/am/ForegroundServiceTypeLoggerModule.java
@@ -316,6 +316,10 @@ public class ForegroundServiceTypeLoggerModule {
// then we should care, otherwise we assume
// it's not related to any FGS
UidState uidState = mUids.get(uid);
+ if (uidState == null) {
+ Log.w(TAG, "API event end called before start!");
+ return -1;
+ }
if (uidState.mOpenWithFgsCount.contains(apiType)) {
// are there any calls that started with an FGS?
if (uidState.mOpenWithFgsCount.get(apiType) != 0) {
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 32db33d3047d..712142185863 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -22,8 +22,8 @@ import static android.app.ActivityManager.PROCESS_CAPABILITY_BFSL;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
-import static android.app.ActivityManager.PROCESS_CAPABILITY_NETWORK;
import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
@@ -117,6 +117,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.ServiceInfo;
+import android.net.NetworkPolicyManager;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManagerInternal;
@@ -127,7 +128,6 @@ import android.os.Trace;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
-import android.util.SparseSetArray;
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.CompositeRWLock;
@@ -207,7 +207,8 @@ public class OomAdjuster {
return AppProtoEnums.OOM_ADJ_REASON_PROCESS_BEGIN;
case OOM_ADJ_REASON_PROCESS_END:
return AppProtoEnums.OOM_ADJ_REASON_PROCESS_END;
- case OOM_ADJ_REASON_SHORT_FGS_TIMEOUT: // TODO(short-service) add value to AppProtoEnums
+ case OOM_ADJ_REASON_SHORT_FGS_TIMEOUT:
+ return AppProtoEnums.OOM_ADJ_REASON_SHORT_FGS_TIMEOUT;
default:
return AppProtoEnums.OOM_ADJ_REASON_UNKNOWN_TO_PROTO;
}
@@ -366,19 +367,6 @@ public class OomAdjuster {
@GuardedBy("mService")
private boolean mPendingFullOomAdjUpdate = false;
- /**
- * PIDs that has a SHORT_SERVICE. We need to access it with the PowerManager lock held,
- * so we use a fine-grained lock here.
- */
- @GuardedBy("mPidsWithShortFgs")
- private final ArraySet<Integer> mPidsWithShortFgs = new ArraySet<>();
-
- /**
- * UIDs -> PIDs map, used with mPidsWithShortFgs.
- */
- @GuardedBy("mPidsWithShortFgs")
- private final SparseSetArray<Integer> mUidsToPidsWithShortFgs = new SparseSetArray<>();
-
/** Overrideable by a test */
@VisibleForTesting
protected boolean isChangeEnabled(@CachedCompatChangeId int cachedCompatChangeId,
@@ -1073,135 +1061,165 @@ public class OomAdjuster {
@GuardedBy({"mService", "mProcLock"})
private void assignCachedAdjIfNecessary(ArrayList<ProcessRecord> lruList) {
final int numLru = lruList.size();
-
- // First update the OOM adjustment for each of the
- // application processes based on their current state.
- int curCachedAdj = CACHED_APP_MIN_ADJ;
- int nextCachedAdj = curCachedAdj + (CACHED_APP_IMPORTANCE_LEVELS * 2);
- int curCachedImpAdj = 0;
- int curEmptyAdj = CACHED_APP_MIN_ADJ + CACHED_APP_IMPORTANCE_LEVELS;
- int nextEmptyAdj = curEmptyAdj + (CACHED_APP_IMPORTANCE_LEVELS * 2);
-
- final int emptyProcessLimit = mConstants.CUR_MAX_EMPTY_PROCESSES;
- final int cachedProcessLimit = mConstants.CUR_MAX_CACHED_PROCESSES
- - emptyProcessLimit;
- // Let's determine how many processes we have running vs.
- // how many slots we have for background processes; we may want
- // to put multiple processes in a slot of there are enough of
- // them.
- int numEmptyProcs = numLru - mNumNonCachedProcs - mNumCachedHiddenProcs;
- if (numEmptyProcs > cachedProcessLimit) {
- // If there are more empty processes than our limit on cached
- // processes, then use the cached process limit for the factor.
- // This ensures that the really old empty processes get pushed
- // down to the bottom, so if we are running low on memory we will
- // have a better chance at keeping around more cached processes
- // instead of a gazillion empty processes.
- numEmptyProcs = cachedProcessLimit;
- }
- int cachedFactor = (mNumCachedHiddenProcs > 0 ? (mNumCachedHiddenProcs + mNumSlots - 1) : 1)
- / mNumSlots;
- if (cachedFactor < 1) cachedFactor = 1;
-
- int emptyFactor = (numEmptyProcs + mNumSlots - 1) / mNumSlots;
- if (emptyFactor < 1) emptyFactor = 1;
-
- int stepCached = -1;
- int stepEmpty = -1;
- int lastCachedGroup = 0;
- int lastCachedGroupImportance = 0;
- int lastCachedGroupUid = 0;
-
- for (int i = numLru - 1; i >= 0; i--) {
- ProcessRecord app = lruList.get(i);
- final ProcessStateRecord state = app.mState;
- // If we haven't yet assigned the final cached adj
- // to the process, do that now.
- if (!app.isKilledByAm() && app.getThread() != null && state.getCurAdj()
+ if (mConstants.USE_TIERED_CACHED_ADJ) {
+ final long now = SystemClock.uptimeMillis();
+ for (int i = numLru - 1; i >= 0; i--) {
+ ProcessRecord app = lruList.get(i);
+ final ProcessStateRecord state = app.mState;
+ final ProcessCachedOptimizerRecord opt = app.mOptRecord;
+ if (!app.isKilledByAm() && app.getThread() != null && state.getCurAdj()
+ >= UNKNOWN_ADJ) {
+ final ProcessServiceRecord psr = app.mServices;
+ int targetAdj = CACHED_APP_MIN_ADJ;
+
+ if (opt != null && opt.isFreezeExempt()) {
+ // BIND_WAIVE_PRIORITY and the like get oom_adj 900
+ targetAdj += 0;
+ } else if ((state.getSetAdj() >= CACHED_APP_MIN_ADJ)
+ && (state.getLastStateTime()
+ + mConstants.TIERED_CACHED_ADJ_DECAY_TIME) < now) {
+ // Older cached apps get 950
+ targetAdj += 50;
+ } else {
+ // Newer cached apps get 910
+ targetAdj += 10;
+ }
+ state.setCurRawAdj(targetAdj);
+ state.setCurAdj(psr.modifyRawOomAdj(targetAdj));
+ }
+ }
+ } else {
+ // First update the OOM adjustment for each of the
+ // application processes based on their current state.
+ int curCachedAdj = CACHED_APP_MIN_ADJ;
+ int nextCachedAdj = curCachedAdj + (CACHED_APP_IMPORTANCE_LEVELS * 2);
+ int curCachedImpAdj = 0;
+ int curEmptyAdj = CACHED_APP_MIN_ADJ + CACHED_APP_IMPORTANCE_LEVELS;
+ int nextEmptyAdj = curEmptyAdj + (CACHED_APP_IMPORTANCE_LEVELS * 2);
+
+ final int emptyProcessLimit = mConstants.CUR_MAX_EMPTY_PROCESSES;
+ final int cachedProcessLimit = mConstants.CUR_MAX_CACHED_PROCESSES
+ - emptyProcessLimit;
+ // Let's determine how many processes we have running vs.
+ // how many slots we have for background processes; we may want
+ // to put multiple processes in a slot of there are enough of
+ // them.
+ int numEmptyProcs = numLru - mNumNonCachedProcs - mNumCachedHiddenProcs;
+ if (numEmptyProcs > cachedProcessLimit) {
+ // If there are more empty processes than our limit on cached
+ // processes, then use the cached process limit for the factor.
+ // This ensures that the really old empty processes get pushed
+ // down to the bottom, so if we are running low on memory we will
+ // have a better chance at keeping around more cached processes
+ // instead of a gazillion empty processes.
+ numEmptyProcs = cachedProcessLimit;
+ }
+ int cachedFactor = (mNumCachedHiddenProcs > 0
+ ? (mNumCachedHiddenProcs + mNumSlots - 1) : 1)
+ / mNumSlots;
+ if (cachedFactor < 1) cachedFactor = 1;
+
+ int emptyFactor = (numEmptyProcs + mNumSlots - 1) / mNumSlots;
+ if (emptyFactor < 1) emptyFactor = 1;
+
+ int stepCached = -1;
+ int stepEmpty = -1;
+ int lastCachedGroup = 0;
+ int lastCachedGroupImportance = 0;
+ int lastCachedGroupUid = 0;
+
+
+ for (int i = numLru - 1; i >= 0; i--) {
+ ProcessRecord app = lruList.get(i);
+ final ProcessStateRecord state = app.mState;
+ // If we haven't yet assigned the final cached adj
+ // to the process, do that now.
+ if (!app.isKilledByAm() && app.getThread() != null && state.getCurAdj()
>= UNKNOWN_ADJ) {
- final ProcessServiceRecord psr = app.mServices;
- switch (state.getCurProcState()) {
- case PROCESS_STATE_CACHED_ACTIVITY:
- case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
- case ActivityManager.PROCESS_STATE_CACHED_RECENT:
- // Figure out the next cached level, taking into account groups.
- boolean inGroup = false;
- final int connectionGroup = psr.getConnectionGroup();
- if (connectionGroup != 0) {
- final int connectionImportance = psr.getConnectionImportance();
- if (lastCachedGroupUid == app.uid
+ final ProcessServiceRecord psr = app.mServices;
+ switch (state.getCurProcState()) {
+ case PROCESS_STATE_CACHED_ACTIVITY:
+ case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
+ case ActivityManager.PROCESS_STATE_CACHED_RECENT:
+ // Figure out the next cached level, taking into account groups.
+ boolean inGroup = false;
+ final int connectionGroup = psr.getConnectionGroup();
+ if (connectionGroup != 0) {
+ final int connectionImportance = psr.getConnectionImportance();
+ if (lastCachedGroupUid == app.uid
&& lastCachedGroup == connectionGroup) {
- // This is in the same group as the last process, just tweak
- // adjustment by importance.
- if (connectionImportance > lastCachedGroupImportance) {
- lastCachedGroupImportance = connectionImportance;
- if (curCachedAdj < nextCachedAdj
+ // This is in the same group as the last process, just tweak
+ // adjustment by importance.
+ if (connectionImportance > lastCachedGroupImportance) {
+ lastCachedGroupImportance = connectionImportance;
+ if (curCachedAdj < nextCachedAdj
&& curCachedAdj < CACHED_APP_MAX_ADJ) {
- curCachedImpAdj++;
+ curCachedImpAdj++;
+ }
}
+ inGroup = true;
+ } else {
+ lastCachedGroupUid = app.uid;
+ lastCachedGroup = connectionGroup;
+ lastCachedGroupImportance = connectionImportance;
}
- inGroup = true;
- } else {
- lastCachedGroupUid = app.uid;
- lastCachedGroup = connectionGroup;
- lastCachedGroupImportance = connectionImportance;
}
- }
- if (!inGroup && curCachedAdj != nextCachedAdj) {
- stepCached++;
- curCachedImpAdj = 0;
- if (stepCached >= cachedFactor) {
- stepCached = 0;
- curCachedAdj = nextCachedAdj;
- nextCachedAdj += CACHED_APP_IMPORTANCE_LEVELS * 2;
- if (nextCachedAdj > CACHED_APP_MAX_ADJ) {
- nextCachedAdj = CACHED_APP_MAX_ADJ;
+ if (!inGroup && curCachedAdj != nextCachedAdj) {
+ stepCached++;
+ curCachedImpAdj = 0;
+ if (stepCached >= cachedFactor) {
+ stepCached = 0;
+ curCachedAdj = nextCachedAdj;
+ nextCachedAdj += CACHED_APP_IMPORTANCE_LEVELS * 2;
+ if (nextCachedAdj > CACHED_APP_MAX_ADJ) {
+ nextCachedAdj = CACHED_APP_MAX_ADJ;
+ }
}
}
- }
- // This process is a cached process holding activities...
- // assign it the next cached value for that type, and then
- // step that cached level.
- state.setCurRawAdj(curCachedAdj + curCachedImpAdj);
- state.setCurAdj(psr.modifyRawOomAdj(curCachedAdj + curCachedImpAdj));
- if (DEBUG_LRU) {
- Slog.d(TAG_LRU, "Assigning activity LRU #" + i
- + " adj: " + state.getCurAdj()
- + " (curCachedAdj=" + curCachedAdj
- + " curCachedImpAdj=" + curCachedImpAdj + ")");
- }
- break;
- default:
- // Figure out the next cached level.
- if (curEmptyAdj != nextEmptyAdj) {
- stepEmpty++;
- if (stepEmpty >= emptyFactor) {
- stepEmpty = 0;
- curEmptyAdj = nextEmptyAdj;
- nextEmptyAdj += CACHED_APP_IMPORTANCE_LEVELS * 2;
- if (nextEmptyAdj > CACHED_APP_MAX_ADJ) {
- nextEmptyAdj = CACHED_APP_MAX_ADJ;
+ // This process is a cached process holding activities...
+ // assign it the next cached value for that type, and then
+ // step that cached level.
+ state.setCurRawAdj(curCachedAdj + curCachedImpAdj);
+ state.setCurAdj(psr.modifyRawOomAdj(curCachedAdj + curCachedImpAdj));
+ if (DEBUG_LRU) {
+ Slog.d(TAG_LRU, "Assigning activity LRU #" + i
+ + " adj: " + state.getCurAdj()
+ + " (curCachedAdj=" + curCachedAdj
+ + " curCachedImpAdj=" + curCachedImpAdj + ")");
+ }
+ break;
+ default:
+ // Figure out the next cached level.
+ if (curEmptyAdj != nextEmptyAdj) {
+ stepEmpty++;
+ if (stepEmpty >= emptyFactor) {
+ stepEmpty = 0;
+ curEmptyAdj = nextEmptyAdj;
+ nextEmptyAdj += CACHED_APP_IMPORTANCE_LEVELS * 2;
+ if (nextEmptyAdj > CACHED_APP_MAX_ADJ) {
+ nextEmptyAdj = CACHED_APP_MAX_ADJ;
+ }
}
}
- }
- // For everything else, assign next empty cached process
- // level and bump that up. Note that this means that
- // long-running services that have dropped down to the
- // cached level will be treated as empty (since their process
- // state is still as a service), which is what we want.
- state.setCurRawAdj(curEmptyAdj);
- state.setCurAdj(psr.modifyRawOomAdj(curEmptyAdj));
- if (DEBUG_LRU) {
- Slog.d(TAG_LRU, "Assigning empty LRU #" + i
- + " adj: " + state.getCurAdj() + " (curEmptyAdj=" + curEmptyAdj
- + ")");
- }
- break;
+ // For everything else, assign next empty cached process
+ // level and bump that up. Note that this means that
+ // long-running services that have dropped down to the
+ // cached level will be treated as empty (since their process
+ // state is still as a service), which is what we want.
+ state.setCurRawAdj(curEmptyAdj);
+ state.setCurAdj(psr.modifyRawOomAdj(curEmptyAdj));
+ if (DEBUG_LRU) {
+ Slog.d(TAG_LRU, "Assigning empty LRU #" + i
+ + " adj: " + state.getCurAdj()
+ + " (curEmptyAdj=" + curEmptyAdj
+ + ")");
+ }
+ break;
+ }
}
}
}
}
-
private long mNextNoKillDebugMessageTime;
private double mLastFreeSwapPercent = 1.00;
@@ -1242,12 +1260,19 @@ public class OomAdjuster {
for (int i = numLru - 1; i >= 0; i--) {
ProcessRecord app = lruList.get(i);
final ProcessStateRecord state = app.mState;
- if (!app.isKilledByAm() && app.getThread() != null && !app.isPendingFinishAttach()) {
+ if (!app.isKilledByAm() && app.getThread() != null) {
// We don't need to apply the update for the process which didn't get computed
if (state.getCompletedAdjSeq() == mAdjSeq) {
applyOomAdjLSP(app, true, now, nowElapsed, oomAdjReason);
}
+ if (app.isPendingFinishAttach()) {
+ // Avoid trimming processes that are still initializing. If they aren't
+ // hosting any components yet because they may be unfairly killed.
+ // We however apply any computed previously computed oom scores before skipping.
+ continue;
+ }
+
final ProcessServiceRecord psr = app.mServices;
// Count the number of process types.
switch (state.getCurProcState()) {
@@ -1318,6 +1343,13 @@ public class OomAdjuster {
// left sitting around after no longer needed.
app.killLocked("isolated not needed", ApplicationExitInfo.REASON_OTHER,
ApplicationExitInfo.SUBREASON_ISOLATED_NOT_NEEDED, true);
+ } else if (app.isSdkSandbox && psr.numberOfRunningServices() <= 0
+ && app.getActiveInstrumentation() == null) {
+ // If this is an SDK sandbox process and there are no services running it, we
+ // aggressively kill the sandbox as we usually don't want to re-use the same
+ // sandbox again.
+ app.killLocked("sandbox not needed", ApplicationExitInfo.REASON_OTHER,
+ ApplicationExitInfo.SUBREASON_SDK_SANDBOX_NOT_NEEDED, true);
} else {
// Keeping this process, update its uid.
updateAppUidRecLSP(app);
@@ -1674,6 +1706,19 @@ public class OomAdjuster {
return false;
}
+ if (app.isPendingFinishAttach()) {
+ state.setAdjSeq(mAdjSeq);
+ state.setCompletedAdjSeq(mAdjSeq);
+ // If the process is still initializing, we skip computing any states because we
+ // don't want to override the special states that have been set at
+ // AMS#attachApplication with OomAdjuster#setAttachingProcessStates.
+ // In this limbo state, the app has |PROC_START_TIMEOUT| to finish attach application
+ // and receive updated proc_state based on its importance.
+ // Note that in this state, the oom_score is INVALID_ADJ which is outside the standard
+ // oom score range and the app is safe from lmkd kills.
+ return false;
+ }
+
state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN);
state.setAdjSource(null);
state.setAdjTarget(null);
@@ -1918,7 +1963,6 @@ public class OomAdjuster {
}
}
}
- updateShortFgsOwner(psr.mApp.uid, psr.mApp.mPid, hasShortForegroundServices);
// If the app was recently in the foreground and moved to a foreground service status,
// allow it to get a higher rank in memory for some time, compared to other foreground
@@ -2018,25 +2062,37 @@ public class OomAdjuster {
}
}
}
-
if (state.getCachedIsPreviousProcess() && state.getCachedHasActivities()) {
- if (adj > PREVIOUS_APP_ADJ) {
- // This was the previous process that showed UI to the user.
- // We want to try to keep it around more aggressively, to give
- // a good experience around switching between two apps.
- adj = PREVIOUS_APP_ADJ;
+ // This was the previous process that showed UI to the user. We want to
+ // try to keep it around more aggressively, to give a good experience
+ // around switching between two apps. However, we don't want to keep the
+ // process in this privileged state indefinitely. Eventually, allow the
+ // app to be demoted to cached.
+ if ((state.getSetProcState() == PROCESS_STATE_LAST_ACTIVITY
+ && (state.getLastStateTime() + mConstants.MAX_PREVIOUS_TIME) < now)) {
+ procState = PROCESS_STATE_LAST_ACTIVITY;
schedGroup = SCHED_GROUP_BACKGROUND;
- state.setCached(false);
- state.setAdjType("previous");
+ state.setAdjType("previous-expired");
+ adj = CACHED_APP_MIN_ADJ;
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
- reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to prev: " + app);
+ reportOomAdjMessageLocked(TAG_OOM_ADJ, "Expire prev adj: " + app);
}
- }
- if (procState > PROCESS_STATE_LAST_ACTIVITY) {
- procState = PROCESS_STATE_LAST_ACTIVITY;
- state.setAdjType("previous");
- if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
- reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to prev: " + app);
+ } else {
+ if (adj > PREVIOUS_APP_ADJ) {
+ adj = PREVIOUS_APP_ADJ;
+ schedGroup = SCHED_GROUP_BACKGROUND;
+ state.setCached(false);
+ state.setAdjType("previous");
+ if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
+ reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to prev: " + app);
+ }
+ }
+ if (procState > PROCESS_STATE_LAST_ACTIVITY) {
+ procState = PROCESS_STATE_LAST_ACTIVITY;
+ state.setAdjType("previous");
+ if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
+ reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to prev: " + app);
+ }
}
}
}
@@ -2135,8 +2191,6 @@ public class OomAdjuster {
}
}
- // TODO(short-service): While-in-user permissions. Do we need any change here for
- // short-FGS? (Likely not)
if (s.isForeground) {
final int fgsType = s.foregroundServiceType;
if (s.mAllowWhileInUsePermissionInFgs) {
@@ -2227,14 +2281,15 @@ public class OomAdjuster {
// elevated to a high enough procstate anyway to get network unless they
// request otherwise, so don't propagate the network capability by default
// in this case unless they explicitly request it.
- if ((cstate.getCurCapability() & PROCESS_CAPABILITY_NETWORK) != 0) {
+ if ((cstate.getCurCapability()
+ & PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK) != 0) {
if (clientProcState <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
// This is used to grant network access to Expedited Jobs.
if (cr.hasFlag(Context.BIND_BYPASS_POWER_NETWORK_RESTRICTIONS)) {
- capability |= PROCESS_CAPABILITY_NETWORK;
+ capability |= PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
}
} else {
- capability |= PROCESS_CAPABILITY_NETWORK;
+ capability |= PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
}
}
@@ -2745,27 +2800,33 @@ public class OomAdjuster {
}
private int getDefaultCapability(ProcessRecord app, int procState) {
+ final int networkCapabilities =
+ NetworkPolicyManager.getDefaultProcessNetworkCapabilities(procState);
+ final int baseCapabilities;
switch (procState) {
case PROCESS_STATE_PERSISTENT:
case PROCESS_STATE_PERSISTENT_UI:
case PROCESS_STATE_TOP:
- return PROCESS_CAPABILITY_ALL; // BFSL allowed
+ baseCapabilities = PROCESS_CAPABILITY_ALL; // BFSL allowed
+ break;
case PROCESS_STATE_BOUND_TOP:
- return PROCESS_CAPABILITY_NETWORK | PROCESS_CAPABILITY_BFSL;
+ baseCapabilities = PROCESS_CAPABILITY_BFSL;
+ break;
case PROCESS_STATE_FOREGROUND_SERVICE:
if (app.getActiveInstrumentation() != null) {
- return PROCESS_CAPABILITY_ALL_IMPLICIT | PROCESS_CAPABILITY_NETWORK ;
+ baseCapabilities = PROCESS_CAPABILITY_ALL_IMPLICIT;
} else {
// Capability from foreground service is conditional depending on
// foregroundServiceType in the manifest file and the
// mAllowWhileInUsePermissionInFgs flag.
- return PROCESS_CAPABILITY_NETWORK;
+ baseCapabilities = PROCESS_CAPABILITY_NONE;
}
- case PROCESS_STATE_BOUND_FOREGROUND_SERVICE:
- return PROCESS_CAPABILITY_NETWORK;
+ break;
default:
- return PROCESS_CAPABILITY_NONE;
+ baseCapabilities = PROCESS_CAPABILITY_NONE;
+ break;
}
+ return baseCapabilities | networkCapabilities;
}
/**
@@ -3178,7 +3239,7 @@ public class OomAdjuster {
}
@GuardedBy({"mService", "mProcLock"})
- void setAttachingSchedGroupLSP(ProcessRecord app) {
+ void setAttachingProcessStatesLSP(ProcessRecord app) {
int initialSchedGroup = SCHED_GROUP_DEFAULT;
final ProcessStateRecord state = app.mState;
// If the process has been marked as foreground, it is starting as the top app (with
@@ -3198,6 +3259,15 @@ public class OomAdjuster {
state.setSetSchedGroup(initialSchedGroup);
state.setCurrentSchedulingGroup(initialSchedGroup);
+ state.setCurProcState(PROCESS_STATE_CACHED_EMPTY);
+ state.setCurCapability(PROCESS_CAPABILITY_NONE);
+
+ state.setCurAdj(ProcessList.FOREGROUND_APP_ADJ);
+ state.setSetAdj(ProcessList.FOREGROUND_APP_ADJ);
+ state.setVerifiedAdj(ProcessList.FOREGROUND_APP_ADJ);
+ state.setForcingToImportant(null);
+ state.setHasShownUi(false);
+ state.setCached(true);
}
// ONLY used for unit testing in OomAdjusterTests.java
@@ -3418,40 +3488,4 @@ public class OomAdjuster {
mCachedAppOptimizer.unfreezeAppLSP(app, oomAdjReason);
}
}
-
- /**
- * Update {@link #mPidsWithShortFgs} and {@link #mUidsToPidsWithShortFgs} to keep track
- * of which UID/PID has a short FGS.
- *
- * TODO(short-FGS): Remove it and all the relevant code once SHORT_FGS use the FGS procstate.
- */
- void updateShortFgsOwner(int uid, int pid, boolean add) {
- synchronized (mPidsWithShortFgs) {
- if (add) {
- mUidsToPidsWithShortFgs.add(uid, pid);
- mPidsWithShortFgs.add(pid);
- } else {
- mUidsToPidsWithShortFgs.remove(uid, pid);
- mPidsWithShortFgs.remove(pid);
- }
- }
- }
-
- /**
- * Whether a UID has a (non-timed-out) short FGS or not.
- * It's indirectly called by PowerManager, so we can't hold the AM lock in it.
- */
- boolean hasUidShortForegroundService(int uid) {
- synchronized (mPidsWithShortFgs) {
- final ArraySet<Integer> pids = mUidsToPidsWithShortFgs.get(uid);
- if (pids == null || pids.size() == 0) {
- return false;
- }
- for (int i = pids.size() - 1; i >= 0; i--) {
- final int pid = pids.valueAt(i);
- return mPidsWithShortFgs.contains(pid);
- }
- }
- return false;
- }
}
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index 14ecf9facec1..daf227c029a1 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -69,7 +69,8 @@ public final class PendingIntentRecord extends IIntentSender.Stub {
@Overridable
private static final long DEFAULT_RESCIND_BAL_PRIVILEGES_FROM_PENDING_INTENT_SENDER = 244637991;
private static final String ENABLE_DEFAULT_RESCIND_BAL_PRIVILEGES_FROM_PENDING_INTENT_SENDER =
- "enable_default_rescind_bal_privileges_from_pending_intent_sender";
+ "DefaultRescindBalPrivilegesFromPendingIntentSender__"
+ + "enable_default_rescind_bal_privileges_from_pending_intent_sender";
public static final int FLAG_ACTIVITY_SENDER = 1 << 0;
public static final int FLAG_BROADCAST_SENDER = 1 << 1;
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index f4e2b0f38f13..35f71f74d0e1 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -3100,9 +3100,10 @@ public final class ProcessList {
hostingRecord.getDefiningUid(), hostingRecord.getDefiningProcessName());
final ProcessStateRecord state = r.mState;
- if (!mService.mBooted && !mService.mBooting
+ if (!isolated && !isSdkSandbox
&& userId == UserHandle.USER_SYSTEM
- && (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
+ && (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK
+ && (TextUtils.equals(proc, info.processName))) {
// The system process is initialized to SCHED_GROUP_DEFAULT in init.rc.
state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_DEFAULT);
state.setSetSchedGroup(ProcessList.SCHED_GROUP_DEFAULT);
diff --git a/services/core/java/com/android/server/am/SameProcessApplicationThread.java b/services/core/java/com/android/server/am/SameProcessApplicationThread.java
index 82dd5c2cf2c3..6deaf7b7fe4f 100644
--- a/services/core/java/com/android/server/am/SameProcessApplicationThread.java
+++ b/services/core/java/com/android/server/am/SameProcessApplicationThread.java
@@ -25,6 +25,7 @@ import android.content.pm.ActivityInfo;
import android.content.res.CompatibilityInfo;
import android.os.Bundle;
import android.os.Handler;
+import android.os.RemoteCallback;
import android.os.RemoteException;
import java.util.List;
@@ -77,17 +78,23 @@ public class SameProcessApplicationThread extends IApplicationThread.Default {
@Override
public void scheduleReceiverList(List<ReceiverInfo> info) {
- for (int i = 0; i < info.size(); i++) {
- ReceiverInfo r = info.get(i);
- if (r.registered) {
- scheduleRegisteredReceiver(r.receiver, r.intent,
- r.resultCode, r.data, r.extras, r.ordered, r.sticky, r.assumeDelivered,
- r.sendingUser, r.processState, r.sendingUid, r.sendingPackage);
- } else {
- scheduleReceiver(r.intent, r.activityInfo, r.compatInfo,
- r.resultCode, r.data, r.extras, r.sync, r.assumeDelivered,
- r.sendingUser, r.processState, r.sendingUid, r.sendingPackage);
+ mHandler.post(() -> {
+ try {
+ mWrapped.scheduleReceiverList(info);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ });
+ }
+
+ @Override
+ public void schedulePing(RemoteCallback pong) {
+ mHandler.post(() -> {
+ try {
+ mWrapped.schedulePing(pong);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
}
- }
+ });
}
}
diff --git a/services/core/java/com/android/server/am/TEST_MAPPING b/services/core/java/com/android/server/am/TEST_MAPPING
index c6a8bcd2fb03..d4bcd9e9c66e 100644
--- a/services/core/java/com/android/server/am/TEST_MAPPING
+++ b/services/core/java/com/android/server/am/TEST_MAPPING
@@ -106,9 +106,7 @@
{ "exclude-annotation": "androidx.test.filters.FlakyTest" },
{ "exclude-annotation": "org.junit.Ignore" }
]
- }
- ],
- "presubmit-large": [
+ },
{
"name": "CtsUsageStatsTestCases",
"file_patterns": [
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index fb5359cea808..5bea614d471b 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -60,8 +60,6 @@ import static android.app.AppOpsManager.opAllowSystemBypassRestriction;
import static android.app.AppOpsManager.opRestrictsRead;
import static android.app.AppOpsManager.opToName;
import static android.app.AppOpsManager.opToPublicName;
-import static android.content.Intent.ACTION_PACKAGE_REMOVED;
-import static android.content.Intent.EXTRA_REPLACING;
import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS;
import static android.content.pm.PermissionInfo.PROTECTION_FLAG_APPOP;
@@ -493,7 +491,8 @@ public class AppOpsService extends IAppOpsService.Stub {
final class UidState {
public final int uid;
- public ArrayMap<String, Ops> pkgOps;
+ @NonNull
+ public final ArrayMap<String, Ops> pkgOps = new ArrayMap<>();
// true indicates there is an interested observer, false there isn't but it has such an op
//TODO: Move foregroundOps and hasForegroundWatchers into the AppOpsServiceInterface.
@@ -506,12 +505,10 @@ public class AppOpsService extends IAppOpsService.Stub {
public void clear() {
mAppOpsCheckingService.removeUid(uid);
- if (pkgOps != null) {
- for (String packageName : pkgOps.keySet()) {
- mAppOpsCheckingService.removePackage(packageName, UserHandle.getUserId(uid));
- }
+ for (int i = 0; i < pkgOps.size(); i++) {
+ String packageName = pkgOps.keyAt(i);
+ mAppOpsCheckingService.removePackage(packageName, UserHandle.getUserId(uid));
}
- pkgOps = null;
}
// Functions for uid mode access and manipulation.
@@ -535,12 +532,10 @@ public class AppOpsService extends IAppOpsService.Stub {
public void evalForegroundOps() {
foregroundOps = null;
foregroundOps = mAppOpsCheckingService.evalForegroundUidOps(uid, foregroundOps);
- if (pkgOps != null) {
- for (int i = pkgOps.size() - 1; i >= 0; i--) {
- foregroundOps = mAppOpsCheckingService
- .evalForegroundPackageOps(pkgOps.valueAt(i).packageName, foregroundOps,
- UserHandle.getUserId(uid));
- }
+ for (int i = pkgOps.size() - 1; i >= 0; i--) {
+ foregroundOps = mAppOpsCheckingService
+ .evalForegroundPackageOps(pkgOps.valueAt(i).packageName, foregroundOps,
+ UserHandle.getUserId(uid));
}
hasForegroundWatchers = false;
if (foregroundOps != null) {
@@ -960,7 +955,7 @@ public class AppOpsService extends IAppOpsService.Stub {
LocalManagerRegistry.addManager(AppOpsManagerLocal.class, new AppOpsManagerLocalImpl());
}
- /** Handler for work when packages are removed or updated */
+ /** Handler for work when packages are updated */
private BroadcastReceiver mOnPackageUpdatedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -968,19 +963,7 @@ public class AppOpsService extends IAppOpsService.Stub {
String pkgName = intent.getData().getEncodedSchemeSpecificPart();
int uid = intent.getIntExtra(Intent.EXTRA_UID, Process.INVALID_UID);
- if (action.equals(ACTION_PACKAGE_REMOVED) && !intent.hasExtra(EXTRA_REPLACING)) {
- synchronized (AppOpsService.this) {
- UidState uidState = mUidStates.get(uid);
- if (uidState == null || uidState.pkgOps == null) {
- return;
- }
- mAppOpsCheckingService.removePackage(pkgName, UserHandle.getUserId(uid));
- Ops removedOps = uidState.pkgOps.remove(pkgName);
- if (removedOps != null) {
- scheduleFastWriteLocked();
- }
- }
- } else if (action.equals(Intent.ACTION_PACKAGE_REPLACED)) {
+ if (action.equals(Intent.ACTION_PACKAGE_REPLACED)) {
AndroidPackage pkg = getPackageManagerInternal().getPackage(pkgName);
if (pkg == null) {
return;
@@ -1007,7 +990,7 @@ public class AppOpsService extends IAppOpsService.Stub {
synchronized (AppOpsService.this) {
UidState uidState = mUidStates.get(uid);
- if (uidState == null || uidState.pkgOps == null) {
+ if (uidState == null) {
return;
}
@@ -1055,21 +1038,10 @@ public class AppOpsService extends IAppOpsService.Stub {
mAppOpsCheckingService.systemReady();
initializeUidStates();
- getUserManagerInternal().addUserLifecycleListener(
- new UserManagerInternal.UserLifecycleListener() {
- @Override
- public void onUserCreated(UserInfo user, Object token) {
- initializeUserUidStates(user.id);
- }
-
- // onUserRemoved handled by #removeUser
- });
-
mConstants.startMonitoring(mContext.getContentResolver());
mHistoricalRegistry.systemReady(mContext.getContentResolver());
IntentFilter packageUpdateFilter = new IntentFilter();
- packageUpdateFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
packageUpdateFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
packageUpdateFilter.addDataScheme("package");
@@ -1090,9 +1062,6 @@ public class AppOpsService extends IAppOpsService.Stub {
}
ArrayMap<String, Ops> pkgs = uidState.pkgOps;
- if (pkgs == null) {
- continue;
- }
int numPkgs = pkgs.size();
for (int pkgNum = 0; pkgNum < numPkgs; pkgNum++) {
@@ -1114,6 +1083,52 @@ public class AppOpsService extends IAppOpsService.Stub {
}
}
+ getUserManagerInternal().addUserLifecycleListener(
+ new UserManagerInternal.UserLifecycleListener() {
+ @Override
+ public void onUserCreated(UserInfo user, Object token) {
+ initializeUserUidStates(user.id);
+ }
+
+ // onUserRemoved handled by #removeUser
+ });
+
+ getPackageManagerInternal().getPackageList(
+ new PackageManagerInternal.PackageListObserver() {
+ @Override
+ public void onPackageAdded(String packageName, int appId) {
+ PackageInfo pi = getPackageManagerInternal().getPackageInfo(packageName,
+ PackageManager.GET_PERMISSIONS, Process.myUid(),
+ mContext.getUserId());
+ boolean isSamplingTarget = isSamplingTarget(pi);
+ int[] userIds = getUserManagerInternal().getUserIds();
+ synchronized (AppOpsService.this) {
+ if (isSamplingTarget) {
+ mRarelyUsedPackages.add(packageName);
+ }
+ for (int i = 0; i < userIds.length; i++) {
+ int uid = UserHandle.getUid(userIds[i], appId);
+ UidState uidState = getUidStateLocked(uid, true);
+ if (!uidState.pkgOps.containsKey(packageName)) {
+ uidState.pkgOps.put(packageName,
+ new Ops(packageName, uidState));
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onPackageRemoved(String packageName, int appId) {
+ int[] userIds = getUserManagerInternal().getUserIds();
+ synchronized (AppOpsService.this) {
+ for (int i = 0; i < userIds.length; i++) {
+ int uid = UserHandle.getUid(userIds[i], appId);
+ packageRemovedLocked(uid, packageName);
+ }
+ }
+ }
+ });
+
final IntentFilter packageSuspendFilter = new IntentFilter();
packageSuspendFilter.addAction(Intent.ACTION_PACKAGES_UNSUSPENDED);
packageSuspendFilter.addAction(Intent.ACTION_PACKAGES_SUSPENDED);
@@ -1143,25 +1158,6 @@ public class AppOpsService extends IAppOpsService.Stub {
}
}, UserHandle.ALL, packageSuspendFilter, null, null);
- final IntentFilter packageAddedFilter = new IntentFilter();
- packageAddedFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
- packageAddedFilter.addDataScheme("package");
- mContext.registerReceiver(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final Uri data = intent.getData();
-
- final String packageName = data.getSchemeSpecificPart();
- PackageInfo pi = getPackageManagerInternal().getPackageInfo(packageName,
- PackageManager.GET_PERMISSIONS, Process.myUid(), mContext.getUserId());
- if (isSamplingTarget(pi)) {
- synchronized (AppOpsService.this) {
- mRarelyUsedPackages.add(packageName);
- }
- }
- }
- }, packageAddedFilter);
-
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
@@ -1217,9 +1213,6 @@ public class AppOpsService extends IAppOpsService.Stub {
PackageStateInternal packageState = packageStates.valueAt(j);
int uid = UserHandle.getUid(userId, packageState.getAppId());
UidState uidState = getUidStateLocked(uid, true);
- if (uidState.pkgOps == null) {
- uidState.pkgOps = new ArrayMap<>();
- }
String packageName = packageStates.keyAt(j);
Ops ops = new Ops(packageName, uidState);
uidState.pkgOps.put(packageName, ops);
@@ -1246,46 +1239,43 @@ public class AppOpsService extends IAppOpsService.Stub {
mCheckOpsDelegateDispatcher = new CheckOpsDelegateDispatcher(policy, delegate);
}
- public void packageRemoved(int uid, String packageName) {
+ @VisibleForTesting
+ void packageRemoved(int uid, String packageName) {
synchronized (this) {
- UidState uidState = mUidStates.get(uid);
- if (uidState == null) {
- return;
- }
+ packageRemovedLocked(uid, packageName);
+ }
+ }
- Ops removedOps = null;
+ @GuardedBy("this")
+ private void packageRemovedLocked(int uid, String packageName) {
+ UidState uidState = mUidStates.get(uid);
+ if (uidState == null) {
+ return;
+ }
- // Remove any package state if such.
- if (uidState.pkgOps != null) {
- removedOps = uidState.pkgOps.remove(packageName);
- mAppOpsCheckingService.removePackage(packageName, UserHandle.getUserId(uid));
- }
+ Ops removedOps = null;
- // If we just nuked the last package state check if the UID is valid.
- if (removedOps != null && uidState.pkgOps.isEmpty()
- && getPackagesForUid(uid).length <= 0) {
- uidState.clear();
- mUidStates.remove(uid);
- }
+ // Remove any package state if such.
+ removedOps = uidState.pkgOps.remove(packageName);
+ mAppOpsCheckingService.removePackage(packageName, UserHandle.getUserId(uid));
- if (removedOps != null) {
- scheduleFastWriteLocked();
+ if (removedOps != null) {
+ scheduleFastWriteLocked();
- final int numOps = removedOps.size();
- for (int opNum = 0; opNum < numOps; opNum++) {
- final Op op = removedOps.valueAt(opNum);
+ final int numOps = removedOps.size();
+ for (int opNum = 0; opNum < numOps; opNum++) {
+ final Op op = removedOps.valueAt(opNum);
- final int numAttributions = op.mAttributions.size();
- for (int attributionNum = 0; attributionNum < numAttributions;
- attributionNum++) {
- AttributedOp attributedOp = op.mAttributions.valueAt(attributionNum);
+ final int numAttributions = op.mAttributions.size();
+ for (int attributionNum = 0; attributionNum < numAttributions;
+ attributionNum++) {
+ AttributedOp attributedOp = op.mAttributions.valueAt(attributionNum);
- while (attributedOp.isRunning()) {
- attributedOp.finished(attributedOp.mInProgressEvents.keyAt(0));
- }
- while (attributedOp.isPaused()) {
- attributedOp.finished(attributedOp.mPausedInProgressEvents.keyAt(0));
- }
+ while (attributedOp.isRunning()) {
+ attributedOp.finished(attributedOp.mInProgressEvents.keyAt(0));
+ }
+ while (attributedOp.isPaused()) {
+ attributedOp.finished(attributedOp.mPausedInProgressEvents.keyAt(0));
}
}
}
@@ -1322,7 +1312,7 @@ public class AppOpsService extends IAppOpsService.Stub {
mHandler.sendMessage(PooledLambda.obtainMessage(
AppOpsService::notifyOpChangedForAllPkgsInUid,
this, code, uidState.uid, true, null));
- } else if (uidState.pkgOps != null) {
+ } else if (!uidState.pkgOps.isEmpty()) {
final ArraySet<OnOpModeChangedListener> listenerSet =
mAppOpsCheckingService.getOpModeChangedListeners(code);
if (listenerSet != null) {
@@ -1351,7 +1341,7 @@ public class AppOpsService extends IAppOpsService.Stub {
}
}
- if (uidState != null && uidState.pkgOps != null) {
+ if (uidState != null) {
int numPkgs = uidState.pkgOps.size();
for (int pkgNum = 0; pkgNum < numPkgs; pkgNum++) {
Ops ops = uidState.pkgOps.valueAt(pkgNum);
@@ -1481,7 +1471,7 @@ public class AppOpsService extends IAppOpsService.Stub {
final int uidStateCount = mUidStates.size();
for (int i = 0; i < uidStateCount; i++) {
UidState uidState = mUidStates.valueAt(i);
- if (uidState.pkgOps == null || uidState.pkgOps.isEmpty()) {
+ if (uidState.pkgOps.isEmpty()) {
continue;
}
ArrayMap<String, Ops> packages = uidState.pkgOps;
@@ -2122,7 +2112,7 @@ public class AppOpsService extends IAppOpsService.Stub {
}
}
- if (uidState.pkgOps == null) {
+ if (uidState.pkgOps.isEmpty()) {
continue;
}
@@ -3706,7 +3696,7 @@ public class AppOpsService extends IAppOpsService.Stub {
// Do not check if uid/packageName/attributionTag is already known.
synchronized (this) {
UidState uidState = mUidStates.get(uid);
- if (uidState != null && uidState.pkgOps != null) {
+ if (uidState != null && !uidState.pkgOps.isEmpty()) {
Ops ops = uidState.pkgOps.get(packageName);
if (ops != null && (attributionTag == null || ops.knownAttributionTags.contains(
@@ -3842,13 +3832,6 @@ public class AppOpsService extends IAppOpsService.Stub {
return null;
}
- if (uidState.pkgOps == null) {
- if (!edit) {
- return null;
- }
- uidState.pkgOps = new ArrayMap<>();
- }
-
Ops ops = uidState.pkgOps.get(packageName);
if (ops == null) {
if (!edit) {
@@ -4159,9 +4142,6 @@ public class AppOpsService extends IAppOpsService.Stub {
}
}
- if (uidState.pkgOps == null) {
- uidState.pkgOps = new ArrayMap<>();
- }
Ops ops = uidState.pkgOps.get(pkgName);
if (ops == null) {
ops = new Ops(pkgName, uidState);
@@ -5476,7 +5456,7 @@ public class AppOpsService extends IAppOpsService.Stub {
private void updateStartedOpModeForUidLocked(int code, boolean restricted, int uid) {
UidState uidState = mUidStates.get(uid);
- if (uidState == null || uidState.pkgOps == null) {
+ if (uidState == null) {
return;
}
@@ -5600,7 +5580,7 @@ public class AppOpsService extends IAppOpsService.Stub {
return;
}
UidState uidState = mUidStates.get(uid);
- if (uidState == null || uidState.pkgOps == null) {
+ if (uidState == null) {
return;
}
Ops removedOps = uidState.pkgOps.remove(packageName);
diff --git a/services/core/java/com/android/server/appop/AppOpsUidStateTrackerImpl.java b/services/core/java/com/android/server/appop/AppOpsUidStateTrackerImpl.java
index 49279d44ea7c..2d6966ad0cf8 100644
--- a/services/core/java/com/android/server/appop/AppOpsUidStateTrackerImpl.java
+++ b/services/core/java/com/android/server/appop/AppOpsUidStateTrackerImpl.java
@@ -327,9 +327,12 @@ class AppOpsUidStateTrackerImpl implements AppOpsUidStateTracker {
}
private void commitUidPendingState(int uid) {
- int pendingUidState = mPendingUidStates.get(uid, MIN_PRIORITY_UID_STATE);
- int pendingCapability = mPendingCapability.get(uid, PROCESS_CAPABILITY_NONE);
- boolean pendingVisibleAppWidget = mPendingVisibleAppWidget.get(uid, false);
+ int pendingUidState = mPendingUidStates.get(uid,
+ mUidStates.get(uid, MIN_PRIORITY_UID_STATE));
+ int pendingCapability = mPendingCapability.get(uid,
+ mCapability.get(uid, PROCESS_CAPABILITY_NONE));
+ boolean pendingVisibleAppWidget = mPendingVisibleAppWidget.get(uid,
+ mVisibleAppWidget.get(uid, false));
int uidState = mUidStates.get(uid, MIN_PRIORITY_UID_STATE);
int capability = mCapability.get(uid, PROCESS_CAPABILITY_NONE);
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 88c0c7ff052b..0d0e5764b522 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1315,7 +1315,7 @@ public class AudioService extends IAudioService.Stub
// persistent data
initVolumeGroupStates();
- mSoundDoseHelper.initSafeUsbMediaVolumeIndex();
+ mSoundDoseHelper.initSafeMediaVolumeIndex();
// Link VGS on VSS
initVolumeStreamStates();
@@ -8358,6 +8358,7 @@ public class AudioService extends IAudioService.Stub
synchronized (VolumeStreamState.class) {
// apply device specific volumes first
int index;
+ boolean isAbsoluteVolume = false;
for (int i = 0; i < mIndexMap.size(); i++) {
final int device = mIndexMap.keyAt(i);
if (device != AudioSystem.DEVICE_OUT_DEFAULT) {
@@ -8366,6 +8367,7 @@ public class AudioService extends IAudioService.Stub
} else if (isAbsoluteVolumeDevice(device)
|| isA2dpAbsoluteVolumeDevice(device)
|| AudioSystem.isLeAudioDeviceType(device)) {
+ isAbsoluteVolume = true;
index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10);
} else if (isFullVolumeDevice(device)) {
index = (mIndexMax + 5)/10;
@@ -8374,6 +8376,11 @@ public class AudioService extends IAudioService.Stub
} else {
index = (mIndexMap.valueAt(i) + 5)/10;
}
+
+ sendMsg(mAudioHandler, SoundDoseHelper.MSG_CSD_UPDATE_ATTENUATION,
+ SENDMSG_REPLACE, device, isAbsoluteVolume ? 1 : 0, this,
+ /*delay=*/0);
+
setStreamVolumeIndex(index, device);
}
}
@@ -8830,7 +8837,7 @@ public class AudioService extends IAudioService.Stub
final VolumeStreamState streamState = mStreamStates[update.mStreamType];
if (update.hasVolumeIndex()) {
int index = update.getVolumeIndex();
- if (!mSoundDoseHelper.checkSafeMediaVolume(update.mStreamType, index, update.mDevice)) {
+ if (mSoundDoseHelper.checkSafeMediaVolume(update.mStreamType, index, update.mDevice)) {
index = mSoundDoseHelper.safeMediaVolumeIndex(update.mDevice);
}
streamState.setIndex(index, update.mDevice, update.mCaller,
@@ -8848,6 +8855,10 @@ public class AudioService extends IAudioService.Stub
/*package*/ void setDeviceVolume(VolumeStreamState streamState, int device) {
synchronized (VolumeStreamState.class) {
+ sendMsg(mAudioHandler, SoundDoseHelper.MSG_CSD_UPDATE_ATTENUATION, SENDMSG_REPLACE,
+ device, (isAbsoluteVolumeDevice(device) || isA2dpAbsoluteVolumeDevice(device)
+ || AudioSystem.isLeAudioDeviceType(device) ? 1 : 0),
+ streamState, /*delay=*/0);
// Apply volume
streamState.applyDeviceVolume_syncVSS(device);
diff --git a/services/core/java/com/android/server/audio/SoundDoseHelper.java b/services/core/java/com/android/server/audio/SoundDoseHelper.java
index 4e8e70420955..cf81dbe08182 100644
--- a/services/core/java/com/android/server/audio/SoundDoseHelper.java
+++ b/services/core/java/com/android/server/audio/SoundDoseHelper.java
@@ -52,10 +52,10 @@ import com.android.server.utils.EventLogger;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashSet;
+import java.util.HashMap;
import java.util.List;
import java.util.Objects;
-import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
/**
@@ -79,7 +79,6 @@ public class SoundDoseHelper {
// SAFE_MEDIA_VOLUME_DISABLED according to country option. If not SAFE_MEDIA_VOLUME_DISABLED, it
// can be set to SAFE_MEDIA_VOLUME_INACTIVE by calling AudioService.disableSafeMediaVolume()
// (when user opts out).
- // Note: when CSD calculation is enabled the state is set to SAFE_MEDIA_VOLUME_DISABLED
private static final int SAFE_MEDIA_VOLUME_NOT_CONFIGURED = 0;
private static final int SAFE_MEDIA_VOLUME_DISABLED = 1;
private static final int SAFE_MEDIA_VOLUME_INACTIVE = 2; // confirmed
@@ -89,9 +88,12 @@ public class SoundDoseHelper {
private static final int MSG_PERSIST_SAFE_VOLUME_STATE = SAFE_MEDIA_VOLUME_MSG_START + 2;
private static final int MSG_PERSIST_MUSIC_ACTIVE_MS = SAFE_MEDIA_VOLUME_MSG_START + 3;
private static final int MSG_PERSIST_CSD_VALUES = SAFE_MEDIA_VOLUME_MSG_START + 4;
+ /*package*/ static final int MSG_CSD_UPDATE_ATTENUATION = SAFE_MEDIA_VOLUME_MSG_START + 5;
private static final int UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX = (20 * 3600 * 1000); // 20 hours
+ private static final int MOMENTARY_EXPOSURE_TIMEOUT_MS = (20 * 3600 * 1000); // 20 hours
+
// 30s after boot completed
private static final int SAFE_VOLUME_CONFIGURE_TIMEOUT_MS = 30000;
@@ -125,23 +127,50 @@ public class SoundDoseHelper {
// mSafeMediaVolumeIndex is the cached value of config_safe_media_volume_index property
private int mSafeMediaVolumeIndex;
- // mSafeUsbMediaVolumeDbfs is the cached value of the config_safe_media_volume_usb_mB
+ // mSafeMediaVolumeDbfs is the cached value of the config_safe_media_volume_usb_mB
// property, divided by 100.0.
- private float mSafeUsbMediaVolumeDbfs;
-
- // mSafeUsbMediaVolumeIndex is used for USB Headsets and is the music volume UI index
- // corresponding to a gain of mSafeUsbMediaVolumeDbfs (defaulting to -37dB) in audio
- // flinger mixer.
- // We remove -22 dBs from the theoretical -15dB to account for the EQ + bass boost
- // amplification when both effects are on with all band gains at maximum.
- // This level corresponds to a loudness of 85 dB SPL for the warning to be displayed when
- // the headset is compliant to EN 60950 with a max loudness of 100dB SPL.
- private int mSafeUsbMediaVolumeIndex;
- // mSafeMediaVolumeDevices lists the devices for which safe media volume is enforced,
- private final Set<Integer> mSafeMediaVolumeDevices = new HashSet<>(
- Arrays.asList(AudioSystem.DEVICE_OUT_WIRED_HEADSET,
- AudioSystem.DEVICE_OUT_WIRED_HEADPHONE, AudioSystem.DEVICE_OUT_USB_HEADSET));
+ // For now using the same value for CSD supported devices
+ private float mSafeMediaVolumeDbfs;
+
+ private static class SafeDeviceVolumeInfo {
+ int mDeviceType;
+ int mSafeVolumeIndex = -1;
+
+ SafeDeviceVolumeInfo(int deviceType) {
+ mDeviceType = deviceType;
+ }
+ }
+ /**
+ * mSafeMediaVolumeDevices lists the devices for which safe media volume is enforced.
+ * Contains a safe volume index for a given device type.
+ * Indexes are used for headsets and is the music volume UI index
+ * corresponding to a gain of mSafeMediaVolumeDbfs (defaulting to -37dB) in audio
+ * flinger mixer.
+ * We remove -22 dBs from the theoretical -15dB to account for the EQ + bass boost
+ * amplification when both effects are on with all band gains at maximum.
+ * This level corresponds to a loudness of 85 dB SPL for the warning to be displayed when
+ * the headset is compliant to EN 60950 with a max loudness of 100dB SPL.
+ */
+ private final HashMap<Integer, SafeDeviceVolumeInfo> mSafeMediaVolumeDevices =
+ new HashMap<>() {{
+ put(AudioSystem.DEVICE_OUT_WIRED_HEADSET,
+ new SafeDeviceVolumeInfo(AudioSystem.DEVICE_OUT_WIRED_HEADSET));
+ put(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE,
+ new SafeDeviceVolumeInfo(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE));
+ put(AudioSystem.DEVICE_OUT_USB_HEADSET,
+ new SafeDeviceVolumeInfo(AudioSystem.DEVICE_OUT_USB_HEADSET));
+ put(AudioSystem.DEVICE_OUT_BLE_HEADSET,
+ new SafeDeviceVolumeInfo(AudioSystem.DEVICE_OUT_BLE_HEADSET));
+ put(AudioSystem.DEVICE_OUT_BLE_BROADCAST,
+ new SafeDeviceVolumeInfo(AudioSystem.DEVICE_OUT_BLE_BROADCAST));
+ put(AudioSystem.DEVICE_OUT_HEARING_AID,
+ new SafeDeviceVolumeInfo(AudioSystem.DEVICE_OUT_HEARING_AID));
+ put(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES,
+ new SafeDeviceVolumeInfo(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES));
+ put(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
+ new SafeDeviceVolumeInfo(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP));
+ }};
// mMusicActiveMs is the cumulative time of music activity since safe volume was disabled.
// When this time reaches UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX, the safe media volume is re-enabled
@@ -158,12 +187,16 @@ public class SoundDoseHelper {
private final boolean mEnableCsd;
- private ISoundDose mSoundDose;
-
private final Object mCsdStateLock = new Object();
+ private final AtomicReference<ISoundDose> mSoundDose = new AtomicReference<>();
+
@GuardedBy("mCsdStateLock")
private float mCurrentCsd = 0.f;
+
+ @GuardedBy("mCsdStateLock")
+ private long mLastMomentaryExposureTimeMs = -1;
+
// dose at which the next dose reached warning occurs
@GuardedBy("mCsdStateLock")
private float mNextCsdWarning = 1.0f;
@@ -179,10 +212,26 @@ public class SoundDoseHelper {
private final ISoundDoseCallback.Stub mSoundDoseCallback = new ISoundDoseCallback.Stub() {
public void onMomentaryExposure(float currentMel, int deviceId) {
+ if (!mEnableCsd) {
+ Log.w(TAG, "onMomentaryExposure: csd not supported, ignoring callback");
+ return;
+ }
+
Log.w(TAG, "DeviceId " + deviceId + " triggered momentary exposure with value: "
+ currentMel);
mLogger.enqueue(SoundDoseEvent.getMomentaryExposureEvent(currentMel));
- if (mEnableCsd) {
+
+ boolean postWarning = false;
+ synchronized (mCsdStateLock) {
+ if (mLastMomentaryExposureTimeMs < 0
+ || (System.currentTimeMillis() - mLastMomentaryExposureTimeMs)
+ >= MOMENTARY_EXPOSURE_TIMEOUT_MS) {
+ mLastMomentaryExposureTimeMs = System.currentTimeMillis();
+ postWarning = true;
+ }
+ }
+
+ if (postWarning) {
mVolumeController.postDisplayCsdWarning(
AudioManager.CSD_WARNING_MOMENTARY_EXPOSURE,
getTimeoutMsForWarning(AudioManager.CSD_WARNING_MOMENTARY_EXPOSURE));
@@ -241,12 +290,10 @@ public class SoundDoseHelper {
mContext = context;
mEnableCsd = mContext.getResources().getBoolean(R.bool.config_audio_csd_enabled_default);
- if (mEnableCsd) {
- mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_DISABLED;
- } else {
- mSafeMediaVolumeState = mSettings.getGlobalInt(audioService.getContentResolver(),
- Settings.Global.AUDIO_SAFE_VOLUME_STATE, 0);
- }
+ initCsd();
+
+ mSafeMediaVolumeState = mSettings.getGlobalInt(audioService.getContentResolver(),
+ Settings.Global.AUDIO_SAFE_VOLUME_STATE, SAFE_MEDIA_VOLUME_NOT_CONFIGURED);
// The default safe volume index read here will be replaced by the actual value when
// the mcc is read by onConfigureSafeMedia()
@@ -263,9 +310,14 @@ public class SoundDoseHelper {
return 0.f;
}
- Objects.requireNonNull(mSoundDose, "Sound dose interface not initialized");
+ final ISoundDose soundDose = mSoundDose.get();
+ if (soundDose == null) {
+ Log.w(TAG, "Sound dose interface not initialized");
+ return 0.f;
+ }
+
try {
- return mSoundDose.getOutputRs2();
+ return soundDose.getOutputRs2();
} catch (RemoteException e) {
Log.e(TAG, "Exception while getting the RS2 exposure value", e);
return 0.f;
@@ -277,9 +329,14 @@ public class SoundDoseHelper {
return;
}
- Objects.requireNonNull(mSoundDose, "Sound dose interface not initialized");
+ final ISoundDose soundDose = mSoundDose.get();
+ if (soundDose == null) {
+ Log.w(TAG, "Sound dose interface not initialized");
+ return;
+ }
+
try {
- mSoundDose.setOutputRs2(rs2Value);
+ soundDose.setOutputRs2(rs2Value);
} catch (RemoteException e) {
Log.e(TAG, "Exception while setting the RS2 exposure value", e);
}
@@ -290,9 +347,14 @@ public class SoundDoseHelper {
return -1.f;
}
- Objects.requireNonNull(mSoundDose, "Sound dose interface not initialized");
+ final ISoundDose soundDose = mSoundDose.get();
+ if (soundDose == null) {
+ Log.w(TAG, "Sound dose interface not initialized");
+ return -1.f;
+ }
+
try {
- return mSoundDose.getCsd();
+ return soundDose.getCsd();
} catch (RemoteException e) {
Log.e(TAG, "Exception while getting the CSD value", e);
return -1.f;
@@ -304,13 +366,18 @@ public class SoundDoseHelper {
return;
}
- Objects.requireNonNull(mSoundDose, "Sound dose interface not initialized");
+ final ISoundDose soundDose = mSoundDose.get();
+ if (soundDose == null) {
+ Log.w(TAG, "Sound dose interface not initialized");
+ return;
+ }
+
try {
final SoundDoseRecord record = new SoundDoseRecord();
record.timestamp = System.currentTimeMillis();
record.value = csd;
final SoundDoseRecord[] recordArray = new SoundDoseRecord[] { record };
- mSoundDose.resetCsd(csd, recordArray);
+ soundDose.resetCsd(csd, recordArray);
} catch (RemoteException e) {
Log.e(TAG, "Exception while setting the CSD value", e);
}
@@ -321,9 +388,14 @@ public class SoundDoseHelper {
return;
}
- Objects.requireNonNull(mSoundDose, "Sound dose interface not initialized");
+ final ISoundDose soundDose = mSoundDose.get();
+ if (soundDose == null) {
+ Log.w(TAG, "Sound dose interface not initialized");
+ return;
+ }
+
try {
- mSoundDose.forceUseFrameworkMel(useFrameworkMel);
+ soundDose.forceUseFrameworkMel(useFrameworkMel);
} catch (RemoteException e) {
Log.e(TAG, "Exception while forcing the internal MEL computation", e);
}
@@ -334,9 +406,14 @@ public class SoundDoseHelper {
return;
}
- Objects.requireNonNull(mSoundDose, "Sound dose interface not initialized");
+ final ISoundDose soundDose = mSoundDose.get();
+ if (soundDose == null) {
+ Log.w(TAG, "Sound dose interface not initialized");
+ return;
+ }
+
try {
- mSoundDose.forceComputeCsdOnAllDevices(computeCsdOnAllDevices);
+ soundDose.forceComputeCsdOnAllDevices(computeCsdOnAllDevices);
} catch (RemoteException e) {
Log.e(TAG, "Exception while forcing CSD computation on all devices", e);
}
@@ -347,14 +424,12 @@ public class SoundDoseHelper {
}
/*package*/ int safeMediaVolumeIndex(int device) {
- if (!mSafeMediaVolumeDevices.contains(device)) {
+ final SafeDeviceVolumeInfo vi = mSafeMediaVolumeDevices.get(device);
+ if (vi == null) {
return MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
}
- if (device == AudioSystem.DEVICE_OUT_USB_HEADSET) {
- return mSafeUsbMediaVolumeIndex;
- } else {
- return mSafeMediaVolumeIndex;
- }
+
+ return vi.mSafeVolumeIndex;
}
/*package*/ void restoreMusicActiveMs() {
@@ -378,20 +453,24 @@ public class SoundDoseHelper {
/*package*/ void enforceSafeMediaVolume(String caller) {
AudioService.VolumeStreamState streamState = mAudioService.getVssVolumeForStream(
AudioSystem.STREAM_MUSIC);
- Set<Integer> devices = mSafeMediaVolumeDevices;
- for (int device : devices) {
- int index = streamState.getIndex(device);
- int safeIndex = safeMediaVolumeIndex(device);
+ for (SafeDeviceVolumeInfo vi : mSafeMediaVolumeDevices.values()) {
+ int index = streamState.getIndex(vi.mDeviceType);
+ int safeIndex = safeMediaVolumeIndex(vi.mDeviceType);
if (index > safeIndex) {
- streamState.setIndex(safeIndex, device, caller, true /*hasModifyAudioSettings*/);
+ streamState.setIndex(safeIndex, vi.mDeviceType, caller,
+ true /*hasModifyAudioSettings*/);
mAudioHandler.sendMessageAtTime(
- mAudioHandler.obtainMessage(MSG_SET_DEVICE_VOLUME, device, /*arg2=*/0,
- streamState), /*delay=*/0);
+ mAudioHandler.obtainMessage(MSG_SET_DEVICE_VOLUME, vi.mDeviceType,
+ /*arg2=*/0, streamState), /*delay=*/0);
}
}
}
+ /**
+ * Returns {@code true} if the safe media actions can be applied for the given stream type,
+ * volume index and device.
+ **/
/*package*/ boolean checkSafeMediaVolume(int streamType, int index, int device) {
boolean result;
synchronized (mSafeMediaVolumeStateLock) {
@@ -402,17 +481,16 @@ public class SoundDoseHelper {
@GuardedBy("mSafeMediaVolumeStateLock")
private boolean checkSafeMediaVolume_l(int streamType, int index, int device) {
- return (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_ACTIVE)
- || (AudioService.mStreamVolumeAlias[streamType] != AudioSystem.STREAM_MUSIC)
- || (!mSafeMediaVolumeDevices.contains(device))
- || (index <= safeMediaVolumeIndex(device))
- || mEnableCsd;
+ return (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE)
+ && (AudioService.mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC)
+ && (mSafeMediaVolumeDevices.containsKey(device))
+ && (index > safeMediaVolumeIndex(device));
}
/*package*/ boolean willDisplayWarningAfterCheckVolume(int streamType, int index, int device,
int flags) {
synchronized (mSafeMediaVolumeStateLock) {
- if (!checkSafeMediaVolume_l(streamType, index, device)) {
+ if (checkSafeMediaVolume_l(streamType, index, device)) {
mVolumeController.postDisplaySafeVolumeWarning(flags);
mPendingVolumeCommand = new StreamVolumeCommand(
streamType, index, flags, device);
@@ -443,15 +521,13 @@ public class SoundDoseHelper {
/*package*/ void scheduleMusicActiveCheck() {
synchronized (mSafeMediaVolumeStateLock) {
cancelMusicActiveCheck();
- if (!mEnableCsd) {
- mMusicActiveIntent = PendingIntent.getBroadcast(mContext,
- REQUEST_CODE_CHECK_MUSIC_ACTIVE,
- new Intent(ACTION_CHECK_MUSIC_ACTIVE),
- PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
- mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP,
- SystemClock.elapsedRealtime()
- + MUSIC_ACTIVE_POLL_PERIOD_MS, mMusicActiveIntent);
- }
+ mMusicActiveIntent = PendingIntent.getBroadcast(mContext,
+ REQUEST_CODE_CHECK_MUSIC_ACTIVE,
+ new Intent(ACTION_CHECK_MUSIC_ACTIVE),
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
+ mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ SystemClock.elapsedRealtime()
+ + MUSIC_ACTIVE_POLL_PERIOD_MS, mMusicActiveIntent);
}
}
@@ -459,7 +535,7 @@ public class SoundDoseHelper {
synchronized (mSafeMediaVolumeStateLock) {
if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE) {
int device = mAudioService.getDeviceForStream(AudioSystem.STREAM_MUSIC);
- if (mSafeMediaVolumeDevices.contains(device) && isStreamActive) {
+ if (mSafeMediaVolumeDevices.containsKey(device) && isStreamActive) {
scheduleMusicActiveCheck();
int index = mAudioService.getVssVolumeForDevice(AudioSystem.STREAM_MUSIC,
device);
@@ -487,27 +563,31 @@ public class SoundDoseHelper {
/*package*/ void configureSafeMedia(boolean forced, String caller) {
int msg = MSG_CONFIGURE_SAFE_MEDIA;
- mAudioHandler.removeMessages(msg);
+ if (forced) {
+ // unforced should not cancel forced configure messages
+ mAudioHandler.removeMessages(msg);
+ }
long time = 0;
if (forced) {
time = (SystemClock.uptimeMillis() + (SystemProperties.getBoolean(
"audio.safemedia.bypass", false) ? 0 : SAFE_VOLUME_CONFIGURE_TIMEOUT_MS));
}
+
mAudioHandler.sendMessageAtTime(
mAudioHandler.obtainMessage(msg, /*arg1=*/forced ? 1 : 0, /*arg2=*/0, caller),
time);
}
- /*package*/ void initSafeUsbMediaVolumeIndex() {
- // mSafeUsbMediaVolumeIndex must be initialized after createStreamStates() because it
- // relies on audio policy having correct ranges for volume indexes.
- mSafeUsbMediaVolumeIndex = getSafeUsbMediaVolumeIndex();
+ /*package*/ void initSafeMediaVolumeIndex() {
+ for (SafeDeviceVolumeInfo vi : mSafeMediaVolumeDevices.values()) {
+ vi.mSafeVolumeIndex = getSafeDeviceMediaVolumeIndex(vi.mDeviceType);
+ }
}
/*package*/ int getSafeMediaVolumeIndex(int device) {
- if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE && mSafeMediaVolumeDevices.contains(
- device)) {
+ if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE
+ && mSafeMediaVolumeDevices.containsKey(device)) {
return safeMediaVolumeIndex(device);
} else {
return -1;
@@ -516,7 +596,7 @@ public class SoundDoseHelper {
/*package*/ boolean raiseVolumeDisplaySafeMediaVolume(int streamType, int index, int device,
int flags) {
- if (checkSafeMediaVolume(streamType, index, device)) {
+ if (!checkSafeMediaVolume(streamType, index, device)) {
return false;
}
@@ -525,7 +605,7 @@ public class SoundDoseHelper {
}
/*package*/ boolean safeDevicesContains(int device) {
- return mSafeMediaVolumeDevices.contains(device);
+ return mSafeMediaVolumeDevices.containsKey(device);
}
/*package*/ void invalidatPendingVolumeCommand() {
@@ -551,6 +631,15 @@ public class SoundDoseHelper {
case MSG_PERSIST_CSD_VALUES:
onPersistSoundDoseRecords();
break;
+ case MSG_CSD_UPDATE_ATTENUATION:
+ final int device = msg.arg1;
+ final boolean isAbsoluteVolume = (msg.arg2 == 1);
+ final AudioService.VolumeStreamState streamState =
+ (AudioService.VolumeStreamState) msg.obj;
+
+ updateDoseAttenuation(streamState.getIndex(device), device,
+ streamState.getStreamType(), isAbsoluteVolume);
+ break;
default:
Log.e(TAG, "Unexpected msg to handle: " + msg.what);
break;
@@ -562,8 +651,11 @@ public class SoundDoseHelper {
pw.print(" mSafeMediaVolumeState=");
pw.println(safeMediaVolumeStateToString(mSafeMediaVolumeState));
pw.print(" mSafeMediaVolumeIndex="); pw.println(mSafeMediaVolumeIndex);
- pw.print(" mSafeUsbMediaVolumeIndex="); pw.println(mSafeUsbMediaVolumeIndex);
- pw.print(" mSafeUsbMediaVolumeDbfs="); pw.println(mSafeUsbMediaVolumeDbfs);
+ for (SafeDeviceVolumeInfo vi : mSafeMediaVolumeDevices.values()) {
+ pw.print(" mSafeMediaVolumeIndex["); pw.print(vi.mDeviceType);
+ pw.print("]="); pw.println(vi.mSafeVolumeIndex);
+ }
+ pw.print(" mSafeMediaVolumeDbfs="); pw.println(mSafeMediaVolumeDbfs);
pw.print(" mMusicActiveMs="); pw.println(mMusicActiveMs);
pw.print(" mMcc="); pw.println(mMcc);
pw.print(" mPendingVolumeCommand="); pw.println(mPendingVolumeCommand);
@@ -574,16 +666,18 @@ public class SoundDoseHelper {
/*package*/void reset() {
Log.d(TAG, "Reset the sound dose helper");
- mSoundDose = AudioSystem.getSoundDoseInterface(mSoundDoseCallback);
+ mSoundDose.set(AudioSystem.getSoundDoseInterface(mSoundDoseCallback));
+
synchronized (mCsdStateLock) {
try {
- if (mSoundDose != null && mSoundDose.asBinder().isBinderAlive()) {
+ final ISoundDose soundDose = mSoundDose.get();
+ if (soundDose != null && soundDose.asBinder().isBinderAlive()) {
if (mCurrentCsd != 0.f) {
Log.d(TAG,
"Resetting the saved sound dose value " + mCurrentCsd);
SoundDoseRecord[] records = mDoseRecords.toArray(
new SoundDoseRecord[0]);
- mSoundDose.resetCsd(mCurrentCsd, records);
+ soundDose.resetCsd(mCurrentCsd, records);
}
}
} catch (RemoteException e) {
@@ -592,34 +686,69 @@ public class SoundDoseHelper {
}
}
+ private void updateDoseAttenuation(int newIndex, int device, int streamType,
+ boolean isAbsoluteVolume) {
+ if (!mEnableCsd) {
+ return;
+ }
+
+ final ISoundDose soundDose = mSoundDose.get();
+ if (soundDose == null) {
+ Log.w(TAG, "Can not apply attenuation. ISoundDose itf is null.");
+ return;
+ }
+
+ try {
+ if (!isAbsoluteVolume) {
+ // remove any possible previous attenuation
+ soundDose.updateAttenuation(/* attenuationDB= */0.f, device);
+
+ return;
+ }
+
+ if (AudioService.mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC
+ && mSafeMediaVolumeDevices.containsKey(device)) {
+ soundDose.updateAttenuation(
+ AudioSystem.getStreamVolumeDB(AudioSystem.STREAM_MUSIC,
+ (newIndex + 5) / 10,
+ device), device);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not apply the attenuation for MEL calculation with volume index "
+ + newIndex, e);
+ }
+ }
+
private void initCsd() {
- if (mEnableCsd) {
- Log.v(TAG, "Initializing sound dose");
+ if (!mEnableCsd) {
+ return;
+ }
- synchronized (mCsdStateLock) {
- if (mGlobalTimeOffsetInSecs == GLOBAL_TIME_OFFSET_UNINITIALIZED) {
- mGlobalTimeOffsetInSecs = System.currentTimeMillis() / 1000L;
- }
+ Log.v(TAG, "Initializing sound dose");
- float prevCsd = mCurrentCsd;
- // Restore persisted values
- mCurrentCsd = parseGlobalSettingFloat(
- Settings.Global.AUDIO_SAFE_CSD_CURRENT_VALUE, /* defaultValue= */0.f);
- if (mCurrentCsd != prevCsd) {
- mNextCsdWarning = parseGlobalSettingFloat(
- Settings.Global.AUDIO_SAFE_CSD_NEXT_WARNING, /* defaultValue= */1.f);
- final List<SoundDoseRecord> records = persistedStringToRecordList(
- mSettings.getGlobalString(mAudioService.getContentResolver(),
- Settings.Global.AUDIO_SAFE_CSD_DOSE_RECORDS),
- mGlobalTimeOffsetInSecs);
- if (records != null) {
- mDoseRecords.addAll(records);
- }
- }
+ synchronized (mCsdStateLock) {
+ if (mGlobalTimeOffsetInSecs == GLOBAL_TIME_OFFSET_UNINITIALIZED) {
+ mGlobalTimeOffsetInSecs = System.currentTimeMillis() / 1000L;
}
- reset();
+ float prevCsd = mCurrentCsd;
+ // Restore persisted values
+ mCurrentCsd = parseGlobalSettingFloat(
+ Settings.Global.AUDIO_SAFE_CSD_CURRENT_VALUE, /* defaultValue= */0.f);
+ if (mCurrentCsd != prevCsd) {
+ mNextCsdWarning = parseGlobalSettingFloat(
+ Settings.Global.AUDIO_SAFE_CSD_NEXT_WARNING, /* defaultValue= */1.f);
+ final List<SoundDoseRecord> records = persistedStringToRecordList(
+ mSettings.getGlobalString(mAudioService.getContentResolver(),
+ Settings.Global.AUDIO_SAFE_CSD_DOSE_RECORDS),
+ mGlobalTimeOffsetInSecs);
+ if (records != null) {
+ mDoseRecords.addAll(records);
+ }
+ }
}
+
+ reset();
}
private void onConfigureSafeMedia(boolean force, String caller) {
@@ -629,7 +758,7 @@ public class SoundDoseHelper {
mSafeMediaVolumeIndex = mContext.getResources().getInteger(
com.android.internal.R.integer.config_safe_media_volume_index) * 10;
- mSafeUsbMediaVolumeIndex = getSafeUsbMediaVolumeIndex();
+ initSafeMediaVolumeIndex();
boolean safeMediaVolumeEnabled =
SystemProperties.getBoolean("audio.safemedia.force", false)
@@ -642,7 +771,7 @@ public class SoundDoseHelper {
// The persisted state is either "disabled" or "active": this is the state applied
// next time we boot and cannot be "inactive"
int persistedState;
- if (safeMediaVolumeEnabled && !safeMediaVolumeBypass && !mEnableCsd) {
+ if (safeMediaVolumeEnabled && !safeMediaVolumeBypass) {
persistedState = SAFE_MEDIA_VOLUME_ACTIVE;
// The state can already be "inactive" here if the user has forced it before
// the 30 seconds timeout for forced configuration. In this case we don't reset
@@ -668,10 +797,6 @@ public class SoundDoseHelper {
/*obj=*/null), /*delay=*/0);
}
}
-
- if (mEnableCsd) {
- initCsd();
- }
}
private int getTimeoutMsForWarning(@AudioManager.CsdWarning int csdWarning) {
@@ -719,25 +844,32 @@ public class SoundDoseHelper {
mAudioHandler.obtainMessage(MSG_PERSIST_MUSIC_ACTIVE_MS, mMusicActiveMs, 0).sendToTarget();
}
- private int getSafeUsbMediaVolumeIndex() {
+ private int getSafeDeviceMediaVolumeIndex(int deviceType) {
+ // legacy implementation uses mSafeMediaVolumeIndex for wired HS/HP
+ // instead of computing it from the volume curves
+ if ((deviceType == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE
+ || deviceType == AudioSystem.DEVICE_OUT_WIRED_HEADSET) && !mEnableCsd) {
+ return mSafeMediaVolumeIndex;
+ }
+
// determine UI volume index corresponding to the wanted safe gain in dBFS
int min = MIN_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
int max = MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
- mSafeUsbMediaVolumeDbfs = mContext.getResources().getInteger(
+ mSafeMediaVolumeDbfs = mContext.getResources().getInteger(
com.android.internal.R.integer.config_safe_media_volume_usb_mB) / 100.0f;
while (Math.abs(max - min) > 1) {
int index = (max + min) / 2;
- float gainDB = AudioSystem.getStreamVolumeDB(
- AudioSystem.STREAM_MUSIC, index, AudioSystem.DEVICE_OUT_USB_HEADSET);
+ float gainDB = AudioSystem.getStreamVolumeDB(AudioSystem.STREAM_MUSIC, index,
+ deviceType);
if (Float.isNaN(gainDB)) {
//keep last min in case of read error
break;
- } else if (gainDB == mSafeUsbMediaVolumeDbfs) {
+ } else if (gainDB == mSafeMediaVolumeDbfs) {
min = index;
break;
- } else if (gainDB < mSafeUsbMediaVolumeDbfs) {
+ } else if (gainDB < mSafeMediaVolumeDbfs) {
min = index;
} else {
max = index;
diff --git a/services/core/java/com/android/server/audio/TEST_MAPPING b/services/core/java/com/android/server/audio/TEST_MAPPING
index 300a2c84888d..2cea32af2396 100644
--- a/services/core/java/com/android/server/audio/TEST_MAPPING
+++ b/services/core/java/com/android/server/audio/TEST_MAPPING
@@ -1,5 +1,5 @@
{
- "presubmit-large": [
+ "presubmit": [
{
"name": "CtsMediaAudioTestCases",
"options": [
@@ -24,9 +24,7 @@
"include-annotation": "android.platform.test.annotations.Presubmit"
}
]
- }
- ],
- "presubmit": [
+ },
{
"name": "FrameworksServicesTests",
"options": [
diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
index 57d28f95eb6a..005ad20a2d48 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
@@ -23,6 +23,7 @@ import android.app.ActivityTaskManager;
import android.app.TaskStackListener;
import android.content.Context;
import android.content.pm.ApplicationInfo;
+import android.hardware.biometrics.AuthenticateOptions;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricManager;
@@ -44,8 +45,8 @@ import java.util.function.Supplier;
/**
* A class to keep track of the authentication state for a given client.
*/
-public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
- implements AuthenticationConsumer {
+public abstract class AuthenticationClient<T, O extends AuthenticateOptions>
+ extends AcquisitionClient<T> implements AuthenticationConsumer {
// New, has not started yet
public static final int STATE_NEW = 0;
@@ -75,7 +76,6 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
private final LockoutTracker mLockoutTracker;
private final boolean mIsRestricted;
private final boolean mAllowBackgroundAuthentication;
- private final boolean mIsKeyguardBypassEnabled;
// TODO: This is currently hard to maintain, as each AuthenticationClient subclass must update
// the state. We should think of a way to improve this in the future.
@State
@@ -90,14 +90,15 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
public AuthenticationClient(@NonNull Context context, @NonNull Supplier<T> lazyDaemon,
@NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener,
- int targetUserId, long operationId, boolean restricted, @NonNull String owner,
- int cookie, boolean requireConfirmation, int sensorId,
+ long operationId, boolean restricted, @NonNull O options,
+ int cookie, boolean requireConfirmation,
@NonNull BiometricLogger biometricLogger, @NonNull BiometricContext biometricContext,
boolean isStrongBiometric, @Nullable TaskStackListener taskStackListener,
@NonNull LockoutTracker lockoutTracker, boolean allowBackgroundAuthentication,
- boolean shouldVibrate, boolean isKeyguardBypassEnabled, int sensorStrength) {
- super(context, lazyDaemon, token, listener, targetUserId, owner, cookie, sensorId,
- shouldVibrate, biometricLogger, biometricContext);
+ boolean shouldVibrate, int sensorStrength) {
+ super(context, lazyDaemon, token, listener, options.getUserId(),
+ options.getOpPackageName(), cookie, options.getSensorId(), shouldVibrate,
+ biometricLogger, biometricContext);
mIsStrongBiometric = isStrongBiometric;
mOperationId = operationId;
mRequireConfirmation = requireConfirmation;
@@ -107,7 +108,6 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
mLockoutTracker = lockoutTracker;
mIsRestricted = restricted;
mAllowBackgroundAuthentication = allowBackgroundAuthentication;
- mIsKeyguardBypassEnabled = isKeyguardBypassEnabled;
mShouldUseLockoutTracker = lockoutTracker != null;
mSensorStrength = sensorStrength;
}
@@ -374,14 +374,6 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
return mState;
}
- /**
- * @return true if the client supports bypass (e.g. passive auth such as face), and if it's
- * enabled by the user.
- */
- public boolean isKeyguardBypassEnabled() {
- return mIsKeyguardBypassEnabled;
- }
-
@Override
public int getProtoEnum() {
return BiometricsProto.CM_AUTHENTICATE;
diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java b/services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java
index 7b8f82441fd6..f516a4930a58 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java
@@ -37,6 +37,7 @@ public class BiometricNotificationUtils {
private static final String TAG = "BiometricNotificationUtils";
private static final String RE_ENROLL_NOTIFICATION_TAG = "FaceService";
private static final String BAD_CALIBRATION_NOTIFICATION_TAG = "FingerprintService";
+ private static final String KEY_RE_ENROLL_FACE = "re_enroll_face_unlock";
private static final int NOTIFICATION_ID = 1;
private static final long NOTIFICATION_INTERVAL_MS = 24 * 60 * 60 * 1000;
private static long sLastAlertTime = 0;
@@ -57,6 +58,7 @@ public class BiometricNotificationUtils {
final Intent intent = new Intent("android.settings.FACE_SETTINGS");
intent.setPackage("com.android.settings");
+ intent.putExtra(KEY_RE_ENROLL_FACE, true);
final PendingIntent pendingIntent = PendingIntent.getActivityAsUser(context,
0 /* requestCode */, intent, PendingIntent.FLAG_IMMUTABLE /* flags */,
diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/BiometricServiceProvider.java
index 0f1fe68ad1d7..25651fa2887e 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BiometricServiceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BiometricServiceProvider.java
@@ -17,6 +17,7 @@
package com.android.server.biometrics.sensors;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.hardware.biometrics.SensorPropertiesInternal;
import android.util.proto.ProtoOutputStream;
@@ -39,7 +40,7 @@ public interface BiometricServiceProvider<T extends SensorPropertiesInternal> {
List<T> getSensorProperties();
/** Properties for the given sensor id. */
- @NonNull
+ @Nullable
T getSensorProperties(int sensorId);
boolean isHardwareDetected(int sensorId);
diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricStateCallback.java b/services/core/java/com/android/server/biometrics/sensors/BiometricStateCallback.java
index 2263e80039bd..a4b0a0eece5b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BiometricStateCallback.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BiometricStateCallback.java
@@ -92,7 +92,7 @@ public class BiometricStateCallback<T extends BiometricServiceProvider<P>,
final int previousBiometricState = mBiometricState;
if (client instanceof AuthenticationClient) {
- final AuthenticationClient<?> authClient = (AuthenticationClient<?>) client;
+ final AuthenticationClient<?, ?> authClient = (AuthenticationClient<?, ?>) client;
if (authClient.isKeyguard()) {
mBiometricState = STATE_KEYGUARD_AUTH;
} else if (authClient.isBiometricPrompt()) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
index cdf22aadbd8c..69ad1523118d 100644
--- a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
@@ -64,7 +64,6 @@ public abstract class InternalCleanupClient<S extends BiometricAuthenticator.Ide
private final ArrayList<UserTemplate> mUnknownHALTemplates = new ArrayList<>();
private final BiometricUtils<S> mBiometricUtils;
private final Map<Integer, Long> mAuthenticatorIds;
- private final List<S> mEnrolledList;
private final boolean mHasEnrollmentsBeforeStarting;
private BaseClientMonitor mCurrentTask;
private boolean mFavorHalEnrollments = false;
@@ -135,13 +134,12 @@ public abstract class InternalCleanupClient<S extends BiometricAuthenticator.Ide
protected InternalCleanupClient(@NonNull Context context, @NonNull Supplier<T> lazyDaemon,
int userId, @NonNull String owner, int sensorId,
@NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
- @NonNull List<S> enrolledList, @NonNull BiometricUtils<S> utils,
+ @NonNull BiometricUtils<S> utils,
@NonNull Map<Integer, Long> authenticatorIds) {
super(context, lazyDaemon, null /* token */, null /* ClientMonitorCallbackConverter */,
userId, owner, 0 /* cookie */, sensorId, logger, biometricContext);
mBiometricUtils = utils;
mAuthenticatorIds = authenticatorIds;
- mEnrolledList = enrolledList;
mHasEnrollmentsBeforeStarting = !utils.getBiometricsForUser(context, userId).isEmpty();
}
@@ -169,12 +167,16 @@ public abstract class InternalCleanupClient<S extends BiometricAuthenticator.Ide
public void start(@NonNull ClientMonitorCallback callback) {
super.start(callback);
+ final List<S> enrolledList =
+ mBiometricUtils.getBiometricsForUser(getContext(), getTargetUserId());
+
// Start enumeration. Removal will start if necessary, when enumeration is completed.
mCurrentTask = getEnumerateClient(getContext(), mLazyDaemon, getToken(), getTargetUserId(),
- getOwnerString(), mEnrolledList, mBiometricUtils, getSensorId(), getLogger(),
+ getOwnerString(), enrolledList, mBiometricUtils, getSensorId(), getLogger(),
getBiometricContext());
- Slog.d(TAG, "Starting enumerate: " + mCurrentTask);
+ Slog.d(TAG, "Starting enumerate: " + mCurrentTask + " enrolledList size:"
+ + enrolledList.size());
mCurrentTask.start(mEnumerateCallback);
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java
index b2fd46d1475d..fb64bcc3abc1 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java
@@ -23,6 +23,7 @@ import android.hardware.biometrics.IInvalidationCallback;
import android.hardware.biometrics.ITestSession;
import android.hardware.biometrics.ITestSessionCallback;
import android.hardware.biometrics.SensorPropertiesInternal;
+import android.hardware.face.FaceAuthenticateOptions;
import android.hardware.face.IFaceService;
import android.os.IBinder;
import android.os.RemoteException;
@@ -63,9 +64,13 @@ public final class FaceAuthenticator extends IBiometricAuthenticator.Stub {
long operationId, int userId, IBiometricSensorReceiver sensorReceiver,
String opPackageName, long requestId, int cookie, boolean allowBackgroundAuthentication)
throws RemoteException {
- mFaceService.prepareForAuthentication(mSensorId, requireConfirmation, token, operationId,
- userId, sensorReceiver, opPackageName, requestId, cookie,
- allowBackgroundAuthentication);
+ mFaceService.prepareForAuthentication(requireConfirmation, token, operationId,
+ sensorReceiver, new FaceAuthenticateOptions.Builder()
+ .setUserId(userId)
+ .setSensorId(mSensorId)
+ .setOpPackageName(opPackageName)
+ .build(),
+ requestId, cookie, allowBackgroundAuthentication);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
index 0248010bc9f3..c2994a953f31 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
@@ -35,6 +35,7 @@ import android.hardware.biometrics.ITestSessionCallback;
import android.hardware.biometrics.face.IFace;
import android.hardware.biometrics.face.SensorProps;
import android.hardware.face.Face;
+import android.hardware.face.FaceAuthenticateOptions;
import android.hardware.face.FaceSensorPropertiesInternal;
import android.hardware.face.FaceServiceReceiver;
import android.hardware.face.IFaceAuthenticatorsRegisteredCallback;
@@ -238,14 +239,14 @@ public class FaceService extends SystemService {
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override // Binder call
- public long authenticate(final IBinder token, final long operationId, int userId,
- final IFaceServiceReceiver receiver, final String opPackageName,
- boolean isKeyguardBypassEnabled) {
+ public long authenticate(final IBinder token, final long operationId,
+ final IFaceServiceReceiver receiver, final FaceAuthenticateOptions options) {
// TODO(b/152413782): If the sensor supports face detect and the device is encrypted or
// lockdown, something wrong happened. See similar path in FingerprintService.
super.authenticate_enforcePermission();
+ final String opPackageName = options.getOpPackageName();
final boolean restricted = false; // Face APIs are private
final int statsClient = Utils.isKeyguard(getContext(), opPackageName)
? BiometricsProtoEnums.CLIENT_KEYGUARD
@@ -260,19 +261,20 @@ public class FaceService extends SystemService {
Slog.w(TAG, "Null provider for authenticate");
return -1;
}
+ options.setSensorId(provider.first);
- return provider.second.scheduleAuthenticate(provider.first, token, operationId, userId,
- 0 /* cookie */,
- new ClientMonitorCallbackConverter(receiver), opPackageName, restricted,
- statsClient, isKeyguard, isKeyguardBypassEnabled);
+ return provider.second.scheduleAuthenticate(token, operationId,
+ 0 /* cookie */, new ClientMonitorCallbackConverter(receiver), options,
+ restricted, statsClient, isKeyguard);
}
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override // Binder call
- public long detectFace(final IBinder token, final int userId,
- final IFaceServiceReceiver receiver, final String opPackageName) {
+ public long detectFace(final IBinder token,
+ final IFaceServiceReceiver receiver, final FaceAuthenticateOptions options) {
super.detectFace_enforcePermission();
+ final String opPackageName = options.getOpPackageName();
if (!Utils.isKeyguard(getContext(), opPackageName)) {
Slog.w(TAG, "detectFace called from non-sysui package: " + opPackageName);
return -1;
@@ -283,32 +285,32 @@ public class FaceService extends SystemService {
Slog.w(TAG, "Null provider for detectFace");
return -1;
}
+ options.setSensorId(provider.first);
- return provider.second.scheduleFaceDetect(provider.first, token, userId,
- new ClientMonitorCallbackConverter(receiver), opPackageName,
+ return provider.second.scheduleFaceDetect(token,
+ new ClientMonitorCallbackConverter(receiver), options,
BiometricsProtoEnums.CLIENT_KEYGUARD);
}
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override // Binder call
- public void prepareForAuthentication(int sensorId, boolean requireConfirmation,
- IBinder token, long operationId, int userId,
- IBiometricSensorReceiver sensorReceiver, String opPackageName, long requestId,
- int cookie, boolean allowBackgroundAuthentication) {
+ public void prepareForAuthentication(boolean requireConfirmation,
+ IBinder token, long operationId, IBiometricSensorReceiver sensorReceiver,
+ FaceAuthenticateOptions options, long requestId, int cookie,
+ boolean allowBackgroundAuthentication) {
super.prepareForAuthentication_enforcePermission();
- final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(options.getSensorId());
if (provider == null) {
Slog.w(TAG, "Null provider for prepareForAuthentication");
return;
}
- final boolean isKeyguardBypassEnabled = false; // only valid for keyguard clients
final boolean restricted = true; // BiometricPrompt is always restricted
- provider.scheduleAuthenticate(sensorId, token, operationId, userId, cookie,
- new ClientMonitorCallbackConverter(sensorReceiver), opPackageName, requestId,
+ provider.scheduleAuthenticate(token, operationId, cookie,
+ new ClientMonitorCallbackConverter(sensorReceiver), options, requestId,
restricted, BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT,
- allowBackgroundAuthentication, isKeyguardBypassEnabled);
+ allowBackgroundAuthentication);
}
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java
index 85f95cec8377..2cf64b72d01f 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java
@@ -22,6 +22,7 @@ import android.hardware.biometrics.IInvalidationCallback;
import android.hardware.biometrics.ITestSession;
import android.hardware.biometrics.ITestSessionCallback;
import android.hardware.face.Face;
+import android.hardware.face.FaceAuthenticateOptions;
import android.hardware.face.FaceManager;
import android.hardware.face.FaceSensorPropertiesInternal;
import android.hardware.face.IFaceServiceReceiver;
@@ -82,21 +83,22 @@ public interface ServiceProvider extends BiometricServiceProvider<FaceSensorProp
void cancelEnrollment(int sensorId, @NonNull IBinder token, long requestId);
- long scheduleFaceDetect(int sensorId, @NonNull IBinder token, int userId,
- @NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName,
+ long scheduleFaceDetect(@NonNull IBinder token,
+ @NonNull ClientMonitorCallbackConverter callback,
+ @NonNull FaceAuthenticateOptions options,
int statsClient);
void cancelFaceDetect(int sensorId, @NonNull IBinder token, long requestId);
- long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId,
+ long scheduleAuthenticate(@NonNull IBinder token, long operationId,
int cookie, @NonNull ClientMonitorCallbackConverter callback,
- @NonNull String opPackageName, boolean restricted, int statsClient,
- boolean allowBackgroundAuthentication, boolean isKeyguardBypassEnabled);
+ @NonNull FaceAuthenticateOptions options,
+ boolean restricted, int statsClient, boolean allowBackgroundAuthentication);
- void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId,
+ void scheduleAuthenticate(@NonNull IBinder token, long operationId,
int cookie, @NonNull ClientMonitorCallbackConverter callback,
- @NonNull String opPackageName, long requestId, boolean restricted, int statsClient,
- boolean allowBackgroundAuthentication, boolean isKeyguardBypassEnabled);
+ @NonNull FaceAuthenticateOptions options, long requestId,
+ boolean restricted, int statsClient, boolean allowBackgroundAuthentication);
void cancelAuthentication(int sensorId, @NonNull IBinder token, long requestId);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
index d8b825d2c0e5..976f1cbe1e5c 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
@@ -28,6 +28,7 @@ import android.hardware.biometrics.BiometricFaceConstants;
import android.hardware.biometrics.BiometricManager.Authenticators;
import android.hardware.biometrics.common.ICancellationSignal;
import android.hardware.biometrics.face.IFace;
+import android.hardware.face.FaceAuthenticateOptions;
import android.hardware.face.FaceAuthenticationFrame;
import android.hardware.face.FaceManager;
import android.os.IBinder;
@@ -56,7 +57,7 @@ import java.util.function.Supplier;
/**
* Face-specific authentication client for the {@link IFace} AIDL HAL interface.
*/
-class FaceAuthenticationClient extends AuthenticationClient<AidlSession>
+class FaceAuthenticationClient extends AuthenticationClient<AidlSession, FaceAuthenticateOptions>
implements LockoutConsumer {
private static final String TAG = "FaceAuthenticationClient";
@@ -80,16 +81,16 @@ class FaceAuthenticationClient extends AuthenticationClient<AidlSession>
FaceAuthenticationClient(@NonNull Context context,
@NonNull Supplier<AidlSession> lazyDaemon,
@NonNull IBinder token, long requestId,
- @NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId,
- boolean restricted, String owner, int cookie, boolean requireConfirmation, int sensorId,
+ @NonNull ClientMonitorCallbackConverter listener, long operationId,
+ boolean restricted, @NonNull FaceAuthenticateOptions options, int cookie,
+ boolean requireConfirmation,
@NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
boolean isStrongBiometric, @NonNull UsageStats usageStats,
@NonNull LockoutCache lockoutCache, boolean allowBackgroundAuthentication,
- boolean isKeyguardBypassEnabled, @Authenticators.Types int sensorStrength) {
- this(context, lazyDaemon, token, requestId, listener, targetUserId, operationId,
- restricted, owner, cookie, requireConfirmation, sensorId, logger, biometricContext,
- isStrongBiometric, usageStats, lockoutCache /* lockoutCache */,
- allowBackgroundAuthentication, isKeyguardBypassEnabled,
+ @Authenticators.Types int sensorStrength) {
+ this(context, lazyDaemon, token, requestId, listener, operationId,
+ restricted, options, cookie, requireConfirmation, logger, biometricContext,
+ isStrongBiometric, usageStats, lockoutCache, allowBackgroundAuthentication,
context.getSystemService(SensorPrivacyManager.class), sensorStrength);
}
@@ -97,18 +98,19 @@ class FaceAuthenticationClient extends AuthenticationClient<AidlSession>
FaceAuthenticationClient(@NonNull Context context,
@NonNull Supplier<AidlSession> lazyDaemon,
@NonNull IBinder token, long requestId,
- @NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId,
- boolean restricted, String owner, int cookie, boolean requireConfirmation, int sensorId,
+ @NonNull ClientMonitorCallbackConverter listener, long operationId,
+ boolean restricted, @NonNull FaceAuthenticateOptions options, int cookie,
+ boolean requireConfirmation,
@NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
boolean isStrongBiometric, @NonNull UsageStats usageStats,
@NonNull LockoutCache lockoutCache, boolean allowBackgroundAuthentication,
- boolean isKeyguardBypassEnabled, SensorPrivacyManager sensorPrivacyManager,
+ SensorPrivacyManager sensorPrivacyManager,
@Authenticators.Types int biometricStrength) {
- super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
- owner, cookie, requireConfirmation, sensorId, logger, biometricContext,
+ super(context, lazyDaemon, token, listener, operationId, restricted,
+ options, cookie, requireConfirmation, logger, biometricContext,
isStrongBiometric, null /* taskStackListener */, null /* lockoutCache */,
allowBackgroundAuthentication, false /* shouldVibrate */,
- isKeyguardBypassEnabled, biometricStrength);
+ biometricStrength);
setRequestId(requestId);
mUsageStats = usageStats;
mNotificationManager = context.getSystemService(NotificationManager.class);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java
index 506b2bc8d9db..e65202dca5cd 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java
@@ -22,6 +22,7 @@ import android.content.Context;
import android.hardware.SensorPrivacyManager;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.common.ICancellationSignal;
+import android.hardware.face.FaceAuthenticateOptions;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
@@ -51,11 +52,11 @@ public class FaceDetectClient extends AcquisitionClient<AidlSession> implements
FaceDetectClient(@NonNull Context context, @NonNull Supplier<AidlSession> lazyDaemon,
@NonNull IBinder token, long requestId,
- @NonNull ClientMonitorCallbackConverter listener, int userId,
- @NonNull String owner, int sensorId,
+ @NonNull ClientMonitorCallbackConverter listener,
+ @NonNull FaceAuthenticateOptions options,
@NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
boolean isStrongBiometric) {
- this(context, lazyDaemon, token, requestId, listener, userId, owner, sensorId,
+ this(context, lazyDaemon, token, requestId, listener, options,
logger, biometricContext, isStrongBiometric,
context.getSystemService(SensorPrivacyManager.class));
}
@@ -63,11 +64,12 @@ public class FaceDetectClient extends AcquisitionClient<AidlSession> implements
@VisibleForTesting
FaceDetectClient(@NonNull Context context, @NonNull Supplier<AidlSession> lazyDaemon,
@NonNull IBinder token, long requestId,
- @NonNull ClientMonitorCallbackConverter listener, int userId,
- @NonNull String owner, int sensorId,
+ @NonNull ClientMonitorCallbackConverter listener,
+ @NonNull FaceAuthenticateOptions options,
@NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
boolean isStrongBiometric, SensorPrivacyManager sensorPrivacyManager) {
- super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId,
+ super(context, lazyDaemon, token, listener, options.getUserId(),
+ options.getOpPackageName(), 0 /* cookie */, options.getSensorId(),
true /* shouldVibrate */, logger, biometricContext);
setRequestId(requestId);
mIsStrongBiometric = isStrongBiometric;
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInternalCleanupClient.java
index b0b23faa9aa5..f09d192966f1 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInternalCleanupClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInternalCleanupClient.java
@@ -43,10 +43,10 @@ class FaceInternalCleanupClient extends InternalCleanupClient<Face, AidlSession>
FaceInternalCleanupClient(@NonNull Context context,
@NonNull Supplier<AidlSession> lazyDaemon, int userId, @NonNull String owner,
int sensorId, @NonNull BiometricLogger logger,
- @NonNull BiometricContext biometricContext, @NonNull List<Face> enrolledList,
+ @NonNull BiometricContext biometricContext,
@NonNull BiometricUtils<Face> utils, @NonNull Map<Integer, Long> authenticatorIds) {
super(context, lazyDaemon, userId, owner, sensorId, logger, biometricContext,
- enrolledList, utils, authenticatorIds);
+ utils, authenticatorIds);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
index 89852a14ba9b..1a53fec82d98 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
@@ -32,6 +32,7 @@ import android.hardware.biometrics.common.ComponentInfo;
import android.hardware.biometrics.face.IFace;
import android.hardware.biometrics.face.SensorProps;
import android.hardware.face.Face;
+import android.hardware.face.FaceAuthenticateOptions;
import android.hardware.face.FaceSensorPropertiesInternal;
import android.hardware.face.IFaceServiceReceiver;
import android.os.Binder;
@@ -409,16 +410,17 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
}
@Override
- public long scheduleFaceDetect(int sensorId, @NonNull IBinder token,
- int userId, @NonNull ClientMonitorCallbackConverter callback,
- @NonNull String opPackageName, int statsClient) {
+ public long scheduleFaceDetect(@NonNull IBinder token,
+ @NonNull ClientMonitorCallbackConverter callback,
+ @NonNull FaceAuthenticateOptions options, int statsClient) {
final long id = mRequestCounter.incrementAndGet();
+ final int sensorId = options.getSensorId();
mHandler.post(() -> {
final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId);
final FaceDetectClient client = new FaceDetectClient(mContext,
mSensors.get(sensorId).getLazySession(),
- token, id, callback, userId, opPackageName, sensorId,
+ token, id, callback, options,
createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient),
mBiometricContext, isStrongBiometric);
scheduleForSensor(sensorId, client, mBiometricStateCallback);
@@ -434,22 +436,23 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
}
@Override
- public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
- int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback,
- @NonNull String opPackageName, long requestId, boolean restricted, int statsClient,
- boolean allowBackgroundAuthentication, boolean isKeyguardBypassEnabled) {
+ public void scheduleAuthenticate(@NonNull IBinder token, long operationId,
+ int cookie, @NonNull ClientMonitorCallbackConverter callback,
+ @NonNull FaceAuthenticateOptions options,
+ long requestId, boolean restricted, int statsClient,
+ boolean allowBackgroundAuthentication) {
mHandler.post(() -> {
+ final int userId = options.getUserId();
+ final int sensorId = options.getSensorId();
final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId);
final FaceAuthenticationClient client = new FaceAuthenticationClient(
mContext, mSensors.get(sensorId).getLazySession(), token, requestId, callback,
- userId, operationId, restricted, opPackageName, cookie,
- false /* requireConfirmation */, sensorId,
+ operationId, restricted, options, cookie,
+ false /* requireConfirmation */,
createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient),
mBiometricContext, isStrongBiometric,
mUsageStats, mSensors.get(sensorId).getLockoutCache(),
- allowBackgroundAuthentication, isKeyguardBypassEnabled,
- Utils.getCurrentStrength(sensorId)
- );
+ allowBackgroundAuthentication, Utils.getCurrentStrength(sensorId));
scheduleForSensor(sensorId, client, new ClientMonitorCallback() {
@Override
public void onClientStarted(
@@ -469,15 +472,14 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
}
@Override
- public long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
- int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback,
- @NonNull String opPackageName, boolean restricted, int statsClient,
- boolean allowBackgroundAuthentication, boolean isKeyguardBypassEnabled) {
+ public long scheduleAuthenticate(@NonNull IBinder token, long operationId,
+ int cookie, @NonNull ClientMonitorCallbackConverter callback,
+ @NonNull FaceAuthenticateOptions options, boolean restricted, int statsClient,
+ boolean allowBackgroundAuthentication) {
final long id = mRequestCounter.incrementAndGet();
- scheduleAuthenticate(sensorId, token, operationId, userId, cookie, callback,
- opPackageName, id, restricted, statsClient,
- allowBackgroundAuthentication, isKeyguardBypassEnabled);
+ scheduleAuthenticate(token, operationId, cookie, callback,
+ options, id, restricted, statsClient, allowBackgroundAuthentication);
return id;
}
@@ -595,14 +597,13 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
public void scheduleInternalCleanup(int sensorId, int userId,
@Nullable ClientMonitorCallback callback, boolean favorHalEnrollments) {
mHandler.post(() -> {
- final List<Face> enrolledList = getEnrolledFaces(sensorId, userId);
final FaceInternalCleanupClient client =
new FaceInternalCleanupClient(mContext,
mSensors.get(sensorId).getLazySession(), userId,
mContext.getOpPackageName(), sensorId,
createLogger(BiometricsProtoEnums.ACTION_ENUMERATE,
BiometricsProtoEnums.CLIENT_UNKNOWN),
- mBiometricContext, enrolledList,
+ mBiometricContext,
FaceUtils.getInstance(sensorId),
mSensors.get(sensorId).getAuthenticatorIds());
if (favorHalEnrollments) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
index 1adc5e3e74b5..1e33c96d50ad 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
@@ -31,6 +31,7 @@ import android.hardware.biometrics.ITestSessionCallback;
import android.hardware.biometrics.face.V1_0.IBiometricsFace;
import android.hardware.biometrics.face.V1_0.IBiometricsFaceClientCallback;
import android.hardware.face.Face;
+import android.hardware.face.FaceAuthenticateOptions;
import android.hardware.face.FaceSensorPropertiesInternal;
import android.hardware.face.IFaceServiceReceiver;
import android.os.Binder;
@@ -650,9 +651,9 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
}
@Override
- public long scheduleFaceDetect(int sensorId, @NonNull IBinder token,
- int userId, @NonNull ClientMonitorCallbackConverter callback,
- @NonNull String opPackageName, int statsClient) {
+ public long scheduleFaceDetect(@NonNull IBinder token,
+ @NonNull ClientMonitorCallbackConverter callback,
+ @NonNull FaceAuthenticateOptions options, int statsClient) {
throw new IllegalStateException("Face detect not supported by IBiometricsFace@1.0. Did you"
+ "forget to check the supportsFaceDetection flag?");
}
@@ -664,35 +665,35 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
}
@Override
- public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
- int userId, int cookie, @NonNull ClientMonitorCallbackConverter receiver,
- @NonNull String opPackageName, long requestId, boolean restricted, int statsClient,
- boolean allowBackgroundAuthentication, boolean isKeyguardBypassEnabled) {
+ public void scheduleAuthenticate(@NonNull IBinder token, long operationId,
+ int cookie, @NonNull ClientMonitorCallbackConverter receiver,
+ @NonNull FaceAuthenticateOptions options, long requestId, boolean restricted,
+ int statsClient, boolean allowBackgroundAuthentication) {
mHandler.post(() -> {
+ final int userId = options.getUserId();
scheduleUpdateActiveUserWithoutHandler(userId);
final boolean isStrongBiometric = Utils.isStrongBiometric(mSensorId);
final FaceAuthenticationClient client = new FaceAuthenticationClient(mContext,
- mLazyDaemon, token, requestId, receiver, userId, operationId, restricted,
- opPackageName, cookie, false /* requireConfirmation */, mSensorId,
+ mLazyDaemon, token, requestId, receiver, operationId, restricted,
+ options, cookie, false /* requireConfirmation */,
createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient),
mBiometricContext, isStrongBiometric, mLockoutTracker,
- mUsageStats, allowBackgroundAuthentication, isKeyguardBypassEnabled,
+ mUsageStats, allowBackgroundAuthentication,
Utils.getCurrentStrength(mSensorId));
mScheduler.scheduleClientMonitor(client);
});
}
@Override
- public long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
- int userId, int cookie, @NonNull ClientMonitorCallbackConverter receiver,
- @NonNull String opPackageName, boolean restricted, int statsClient,
- boolean allowBackgroundAuthentication, boolean isKeyguardBypassEnabled) {
+ public long scheduleAuthenticate(@NonNull IBinder token, long operationId,
+ int cookie, @NonNull ClientMonitorCallbackConverter receiver,
+ @NonNull FaceAuthenticateOptions options, boolean restricted, int statsClient,
+ boolean allowBackgroundAuthentication) {
final long id = mRequestCounter.incrementAndGet();
- scheduleAuthenticate(sensorId, token, operationId, userId, cookie, receiver,
- opPackageName, id, restricted, statsClient,
- allowBackgroundAuthentication, isKeyguardBypassEnabled);
+ scheduleAuthenticate(token, operationId, cookie, receiver,
+ options, id, restricted, statsClient, allowBackgroundAuthentication);
return id;
}
@@ -817,12 +818,11 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
mHandler.post(() -> {
scheduleUpdateActiveUserWithoutHandler(userId);
- final List<Face> enrolledList = getEnrolledFaces(mSensorId, userId);
final FaceInternalCleanupClient client = new FaceInternalCleanupClient(mContext,
mLazyDaemon, userId, mContext.getOpPackageName(), mSensorId,
createLogger(BiometricsProtoEnums.ACTION_ENUMERATE,
BiometricsProtoEnums.CLIENT_UNKNOWN),
- mBiometricContext, enrolledList,
+ mBiometricContext,
FaceUtils.getLegacyInstance(mSensorId), mAuthenticatorIds);
mScheduler.scheduleClientMonitor(client, new ClientMonitorCompositeCallback(callback,
mBiometricStateCallback));
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
index d4a7f085b8c5..8ab88923d01e 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
@@ -25,6 +25,7 @@ import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricFaceConstants;
import android.hardware.biometrics.BiometricManager.Authenticators;
import android.hardware.biometrics.face.V1_0.IBiometricsFace;
+import android.hardware.face.FaceAuthenticateOptions;
import android.hardware.face.FaceManager;
import android.os.IBinder;
import android.os.RemoteException;
@@ -50,7 +51,8 @@ import java.util.function.Supplier;
* Face-specific authentication client supporting the {@link android.hardware.biometrics.face.V1_0}
* HIDL interface.
*/
-class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> {
+class FaceAuthenticationClient
+ extends AuthenticationClient<IBiometricsFace, FaceAuthenticateOptions> {
private static final String TAG = "FaceAuthenticationClient";
@@ -67,17 +69,18 @@ class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> {
FaceAuthenticationClient(@NonNull Context context,
@NonNull Supplier<IBiometricsFace> lazyDaemon,
@NonNull IBinder token, long requestId,
- @NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId,
- boolean restricted, String owner, int cookie, boolean requireConfirmation, int sensorId,
+ @NonNull ClientMonitorCallbackConverter listener, long operationId,
+ boolean restricted, @NonNull FaceAuthenticateOptions options, int cookie,
+ boolean requireConfirmation,
@NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
boolean isStrongBiometric, @NonNull LockoutTracker lockoutTracker,
@NonNull UsageStats usageStats, boolean allowBackgroundAuthentication,
- boolean isKeyguardBypassEnabled, @Authenticators.Types int sensorStrength) {
- super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
- owner, cookie, requireConfirmation, sensorId, logger, biometricContext,
+ @Authenticators.Types int sensorStrength) {
+ super(context, lazyDaemon, token, listener, operationId, restricted,
+ options, cookie, requireConfirmation, logger, biometricContext,
isStrongBiometric, null /* taskStackListener */,
lockoutTracker, allowBackgroundAuthentication, false /* shouldVibrate */,
- isKeyguardBypassEnabled, sensorStrength);
+ sensorStrength);
setRequestId(requestId);
mUsageStats = usageStats;
mSensorPrivacyManager = context.getSystemService(SensorPrivacyManager.class);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceInternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceInternalCleanupClient.java
index d21a7501e516..89a17c6b570e 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceInternalCleanupClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceInternalCleanupClient.java
@@ -42,10 +42,10 @@ class FaceInternalCleanupClient extends InternalCleanupClient<Face, IBiometricsF
FaceInternalCleanupClient(@NonNull Context context,
@NonNull Supplier<IBiometricsFace> lazyDaemon, int userId, @NonNull String owner,
int sensorId, @NonNull BiometricLogger logger,
- @NonNull BiometricContext biometricContext, @NonNull List<Face> enrolledList,
+ @NonNull BiometricContext biometricContext,
@NonNull BiometricUtils<Face> utils, @NonNull Map<Integer, Long> authenticatorIds) {
super(context, lazyDaemon, userId, owner, sensorId, logger, biometricContext,
- enrolledList, utils, authenticatorIds);
+ utils, authenticatorIds);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java
index 52d887a75216..d47a57ad6742 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java
@@ -23,6 +23,7 @@ import android.hardware.biometrics.IInvalidationCallback;
import android.hardware.biometrics.ITestSession;
import android.hardware.biometrics.ITestSessionCallback;
import android.hardware.biometrics.SensorPropertiesInternal;
+import android.hardware.fingerprint.FingerprintAuthenticateOptions;
import android.hardware.fingerprint.IFingerprintService;
import android.os.IBinder;
import android.os.RemoteException;
@@ -63,8 +64,13 @@ public final class FingerprintAuthenticator extends IBiometricAuthenticator.Stub
long operationId, int userId, IBiometricSensorReceiver sensorReceiver,
String opPackageName, long requestId, int cookie, boolean allowBackgroundAuthentication)
throws RemoteException {
- mFingerprintService.prepareForAuthentication(mSensorId, token, operationId, userId,
- sensorReceiver, opPackageName, requestId, cookie, allowBackgroundAuthentication);
+ mFingerprintService.prepareForAuthentication(token, operationId, sensorReceiver,
+ new FingerprintAuthenticateOptions.Builder()
+ .setSensorId(mSensorId)
+ .setUserId(userId)
+ .setOpPackageName(opPackageName)
+ .build(),
+ requestId, cookie, allowBackgroundAuthentication);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
index 1c57151ed7bd..dc00ffc9f922 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
@@ -45,6 +45,7 @@ import android.hardware.biometrics.ITestSessionCallback;
import android.hardware.biometrics.fingerprint.IFingerprint;
import android.hardware.biometrics.fingerprint.PointerContext;
import android.hardware.fingerprint.Fingerprint;
+import android.hardware.fingerprint.FingerprintAuthenticateOptions;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.FingerprintServiceReceiver;
@@ -118,7 +119,7 @@ public class FingerprintService extends SystemService {
@NonNull
private final Supplier<String[]> mAidlInstanceNameSupplier;
@NonNull
- private final Function<String, IFingerprint> mIFingerprintProvider;
+ private final Function<String, FingerprintProvider> mFingerprintProvider;
@NonNull
private final BiometricStateCallback<ServiceProvider, FingerprintSensorPropertiesInternal>
mBiometricStateCallback;
@@ -252,15 +253,14 @@ public class FingerprintService extends SystemService {
public long authenticate(
final IBinder token,
final long operationId,
- final int sensorId,
- final int userId,
final IFingerprintServiceReceiver receiver,
- final String opPackageName,
- final String attributionTag,
- boolean ignoreEnrollmentState) {
+ final FingerprintAuthenticateOptions options) {
final int callingUid = Binder.getCallingUid();
final int callingPid = Binder.getCallingPid();
final int callingUserId = UserHandle.getCallingUserId();
+ final String opPackageName = options.getOpPackageName();
+ final String attributionTag = options.getAttributionTag();
+ final int userId = options.getUserId();
if (!canUseFingerprint(
opPackageName,
@@ -297,31 +297,35 @@ public class FingerprintService extends SystemService {
: BiometricsProtoEnums.CLIENT_FINGERPRINT_MANAGER;
final Pair<Integer, ServiceProvider> provider;
- if (sensorId == FingerprintManager.SENSOR_ID_ANY) {
+ if (options.getSensorId() == FingerprintManager.SENSOR_ID_ANY) {
provider = mRegistry.getSingleProvider();
} else {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
- provider = new Pair<>(sensorId, mRegistry.getProviderForSensor(sensorId));
+ provider = new Pair<>(options.getSensorId(),
+ mRegistry.getProviderForSensor(options.getSensorId()));
}
+
if (provider == null) {
Slog.w(TAG, "Null provider for authenticate");
return -1;
}
+ options.setSensorId(provider.first);
final FingerprintSensorPropertiesInternal sensorProps =
- provider.second.getSensorProperties(sensorId);
+ provider.second.getSensorProperties(options.getSensorId());
if (!isKeyguard && !Utils.isSettings(getContext(), opPackageName)
&& sensorProps != null && sensorProps.isAnyUdfpsType()) {
try {
return authenticateWithPrompt(operationId, sensorProps, callingUid,
- callingUserId, receiver, opPackageName, ignoreEnrollmentState);
+ callingUserId, receiver, opPackageName,
+ options.isIgnoreEnrollmentState());
} catch (PackageManager.NameNotFoundException e) {
Slog.e(TAG, "Invalid package", e);
return -1;
}
}
- return provider.second.scheduleAuthenticate(provider.first, token, operationId, userId,
- 0 /* cookie */, new ClientMonitorCallbackConverter(receiver), opPackageName,
+ return provider.second.scheduleAuthenticate(token, operationId,
+ 0 /* cookie */, new ClientMonitorCallbackConverter(receiver), options,
restricted, statsClient, isKeyguard);
}
@@ -412,49 +416,46 @@ public class FingerprintService extends SystemService {
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override
- public long detectFingerprint(final IBinder token, final int userId,
- final IFingerprintServiceReceiver receiver, final String opPackageName) {
+ public long detectFingerprint(final IBinder token,
+ final IFingerprintServiceReceiver receiver,
+ final FingerprintAuthenticateOptions options) {
super.detectFingerprint_enforcePermission();
+ final String opPackageName = options.getOpPackageName();
if (!Utils.isKeyguard(getContext(), opPackageName)) {
Slog.w(TAG, "detectFingerprint called from non-sysui package: " + opPackageName);
return -1;
}
- if (!Utils.isUserEncryptedOrLockdown(mLockPatternUtils, userId)) {
- // If this happens, something in KeyguardUpdateMonitor is wrong. This should only
- // ever be invoked when the user is encrypted or lockdown.
- Slog.e(TAG, "detectFingerprint invoked when user is not encrypted or lockdown");
- return -1;
- }
-
final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
if (provider == null) {
Slog.w(TAG, "Null provider for detectFingerprint");
return -1;
}
+ options.setSensorId(provider.first);
- return provider.second.scheduleFingerDetect(provider.first, token, userId,
- new ClientMonitorCallbackConverter(receiver), opPackageName,
+ return provider.second.scheduleFingerDetect(token,
+ new ClientMonitorCallbackConverter(receiver), options,
BiometricsProtoEnums.CLIENT_KEYGUARD);
}
@android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_BIOMETRIC)
@Override // Binder call
- public void prepareForAuthentication(int sensorId, IBinder token, long operationId,
- int userId, IBiometricSensorReceiver sensorReceiver, String opPackageName,
+ public void prepareForAuthentication(IBinder token, long operationId,
+ IBiometricSensorReceiver sensorReceiver,
+ @NonNull FingerprintAuthenticateOptions options,
long requestId, int cookie, boolean allowBackgroundAuthentication) {
super.prepareForAuthentication_enforcePermission();
- final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
+ final ServiceProvider provider = mRegistry.getProviderForSensor(options.getSensorId());
if (provider == null) {
Slog.w(TAG, "Null provider for prepareForAuthentication");
return;
}
final boolean restricted = true; // BiometricPrompt is always restricted
- provider.scheduleAuthenticate(sensorId, token, operationId, userId, cookie,
- new ClientMonitorCallbackConverter(sensorReceiver), opPackageName, requestId,
+ provider.scheduleAuthenticate(token, operationId, cookie,
+ new ClientMonitorCallbackConverter(sensorReceiver), options, requestId,
restricted, BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT,
allowBackgroundAuthentication);
}
@@ -978,8 +979,7 @@ public class FingerprintService extends SystemService {
() -> IBiometricService.Stub.asInterface(
ServiceManager.getService(Context.BIOMETRIC_SERVICE)),
() -> ServiceManager.getDeclaredInstances(IFingerprint.DESCRIPTOR),
- (fqName) -> IFingerprint.Stub.asInterface(
- Binder.allowBlocking(ServiceManager.waitForDeclaredService(fqName))));
+ null /* fingerprintProvider */);
}
@VisibleForTesting
@@ -987,16 +987,35 @@ public class FingerprintService extends SystemService {
BiometricContext biometricContext,
Supplier<IBiometricService> biometricServiceSupplier,
Supplier<String[]> aidlInstanceNameSupplier,
- Function<String, IFingerprint> fingerprintProvider) {
+ Function<String, FingerprintProvider> fingerprintProvider) {
super(context);
mBiometricContext = biometricContext;
mAidlInstanceNameSupplier = aidlInstanceNameSupplier;
- mIFingerprintProvider = fingerprintProvider;
mAppOps = context.getSystemService(AppOpsManager.class);
mGestureAvailabilityDispatcher = new GestureAvailabilityDispatcher();
mLockoutResetDispatcher = new LockoutResetDispatcher(context);
mLockPatternUtils = new LockPatternUtils(context);
mBiometricStateCallback = new BiometricStateCallback<>(UserManager.get(context));
+ mFingerprintProvider = fingerprintProvider != null ? fingerprintProvider :
+ (name) -> {
+ final String fqName = IFingerprint.DESCRIPTOR + "/" + name;
+ final IFingerprint fp = IFingerprint.Stub.asInterface(
+ Binder.allowBlocking(ServiceManager.waitForDeclaredService(fqName)));
+ if (fp != null) {
+ try {
+ return new FingerprintProvider(getContext(),
+ mBiometricStateCallback, fp.getSensorProps(), name,
+ mLockoutResetDispatcher, mGestureAvailabilityDispatcher,
+ mBiometricContext);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote exception in getSensorProps: " + fqName);
+ }
+ } else {
+ Slog.e(TAG, "Unable to get declared service: " + fqName);
+ }
+
+ return null;
+ };
mHandler = new Handler(Looper.getMainLooper());
mRegistry = new FingerprintServiceRegistry(mServiceWrapper, biometricServiceSupplier);
mRegistry.addAllRegisteredCallback(new IFingerprintAuthenticatorsRegisteredCallback.Stub() {
@@ -1040,23 +1059,9 @@ public class FingerprintService extends SystemService {
final List<ServiceProvider> providers = new ArrayList<>();
for (String instance : instances) {
- final String fqName = IFingerprint.DESCRIPTOR + "/" + instance;
- final IFingerprint fp = mIFingerprintProvider.apply(fqName);
-
- if (fp != null) {
- try {
- final FingerprintProvider provider = new FingerprintProvider(getContext(),
- mBiometricStateCallback, fp.getSensorProps(), instance,
- mLockoutResetDispatcher, mGestureAvailabilityDispatcher,
- mBiometricContext);
- Slog.i(TAG, "Adding AIDL provider: " + fqName);
- providers.add(provider);
- } catch (RemoteException e) {
- Slog.e(TAG, "Remote exception in getSensorProps: " + fqName);
- }
- } else {
- Slog.e(TAG, "Unable to get declared service: " + fqName);
- }
+ final FingerprintProvider provider = mFingerprintProvider.apply(instance);
+ Slog.i(TAG, "Adding AIDL provider: " + instance);
+ providers.add(provider);
}
return providers;
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
index 5b6f14d6c805..004af2c2ad62 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
@@ -23,6 +23,7 @@ import android.hardware.biometrics.ITestSession;
import android.hardware.biometrics.ITestSessionCallback;
import android.hardware.biometrics.fingerprint.PointerContext;
import android.hardware.fingerprint.Fingerprint;
+import android.hardware.fingerprint.FingerprintAuthenticateOptions;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.IFingerprintServiceReceiver;
@@ -78,19 +79,21 @@ public interface ServiceProvider extends
void cancelEnrollment(int sensorId, @NonNull IBinder token, long requestId);
- long scheduleFingerDetect(int sensorId, @NonNull IBinder token, int userId,
- @NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName,
+ long scheduleFingerDetect(@NonNull IBinder token,
+ @NonNull ClientMonitorCallbackConverter callback,
+ @NonNull FingerprintAuthenticateOptions options,
int statsClient);
- void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId,
+ void scheduleAuthenticate(@NonNull IBinder token, long operationId,
int cookie, @NonNull ClientMonitorCallbackConverter callback,
- @NonNull String opPackageName, long requestId, boolean restricted, int statsClient,
+ @NonNull FingerprintAuthenticateOptions options,
+ long requestId, boolean restricted, int statsClient,
boolean allowBackgroundAuthentication);
- long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId,
+ long scheduleAuthenticate(@NonNull IBinder token, long operationId,
int cookie, @NonNull ClientMonitorCallbackConverter callback,
- @NonNull String opPackageName, boolean restricted, int statsClient,
- boolean allowBackgroundAuthentication);
+ @NonNull FingerprintAuthenticateOptions options,
+ boolean restricted, int statsClient, boolean allowBackgroundAuthentication);
void startPreparedClient(int sensorId, int cookie);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/AidlConversionUtils.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/AidlConversionUtils.java
index 1630be77ee7b..bae84bd01e05 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/AidlConversionUtils.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/AidlConversionUtils.java
@@ -48,6 +48,8 @@ final class AidlConversionUtils {
return BiometricFingerprintConstants.FINGERPRINT_ERROR_VENDOR;
} else if (aidlError == Error.BAD_CALIBRATION) {
return BiometricFingerprintConstants.FINGERPRINT_ERROR_BAD_CALIBRATION;
+ } else if (aidlError == Error.POWER_PRESS) {
+ return BiometricFingerprintConstants.BIOMETRIC_ERROR_POWER_PRESSED;
} else {
return BiometricFingerprintConstants.FINGERPRINT_ERROR_UNKNOWN;
}
@@ -84,6 +86,8 @@ final class AidlConversionUtils {
} else if (aidlAcquiredInfo == AcquiredInfo.RETRYING_CAPTURE) {
// No framework constant available
return BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_UNKNOWN;
+ } else if (aidlAcquiredInfo == AcquiredInfo.POWER_PRESS) {
+ return BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_POWER_PRESSED;
} else {
return BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_UNKNOWN;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
index a90679e755cf..0f81f9f2660e 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
@@ -26,6 +26,7 @@ import android.hardware.biometrics.BiometricFingerprintConstants.FingerprintAcqu
import android.hardware.biometrics.BiometricManager.Authenticators;
import android.hardware.biometrics.common.ICancellationSignal;
import android.hardware.biometrics.fingerprint.PointerContext;
+import android.hardware.fingerprint.FingerprintAuthenticateOptions;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.ISidefpsController;
import android.hardware.fingerprint.IUdfpsOverlay;
@@ -65,7 +66,8 @@ import java.util.function.Supplier;
* Fingerprint-specific authentication client supporting the {@link
* android.hardware.biometrics.fingerprint.IFingerprint} AIDL interface.
*/
-class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession>
+class FingerprintAuthenticationClient
+ extends AuthenticationClient<AidlSession, FingerprintAuthenticateOptions>
implements Udfps, LockoutConsumer, PowerPressHandler {
private static final String TAG = "FingerprintAuthenticationClient";
private static final int MESSAGE_AUTH_SUCCESS = 2;
@@ -97,13 +99,11 @@ class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession>
@NonNull IBinder token,
long requestId,
@NonNull ClientMonitorCallbackConverter listener,
- int targetUserId,
long operationId,
boolean restricted,
- @NonNull String owner,
+ @NonNull FingerprintAuthenticateOptions options,
int cookie,
boolean requireConfirmation,
- int sensorId,
@NonNull BiometricLogger biometricLogger,
@NonNull BiometricContext biometricContext,
boolean isStrongBiometric,
@@ -122,13 +122,11 @@ class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession>
lazyDaemon,
token,
listener,
- targetUserId,
operationId,
restricted,
- owner,
+ options,
cookie,
requireConfirmation,
- sensorId,
biometricLogger,
biometricContext,
isStrongBiometric,
@@ -136,7 +134,6 @@ class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession>
null /* lockoutCache */,
allowBackgroundAuthentication,
false /* shouldVibrate */,
- false /* isKeyguardBypassEnabled */,
biometricStrength);
setRequestId(requestId);
mSensorOverlays = new SensorOverlays(udfpsOverlayController,
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java
index f6911ea29837..376d23187fb8 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java
@@ -21,6 +21,7 @@ import android.annotation.Nullable;
import android.content.Context;
import android.hardware.biometrics.BiometricOverlayConstants;
import android.hardware.biometrics.common.ICancellationSignal;
+import android.hardware.fingerprint.FingerprintAuthenticateOptions;
import android.hardware.fingerprint.IUdfpsOverlay;
import android.hardware.fingerprint.IUdfpsOverlayController;
import android.os.IBinder;
@@ -52,13 +53,14 @@ class FingerprintDetectClient extends AcquisitionClient<AidlSession> implements
FingerprintDetectClient(@NonNull Context context, @NonNull Supplier<AidlSession> lazyDaemon,
@NonNull IBinder token, long requestId,
- @NonNull ClientMonitorCallbackConverter listener, int userId,
- @NonNull String owner, int sensorId,
+ @NonNull ClientMonitorCallbackConverter listener,
+ @NonNull FingerprintAuthenticateOptions options,
@NonNull BiometricLogger biometricLogger, @NonNull BiometricContext biometricContext,
@Nullable IUdfpsOverlayController udfpsOverlayController,
@Nullable IUdfpsOverlay udfpsOverlay,
boolean isStrongBiometric) {
- super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId,
+ super(context, lazyDaemon, token, listener, options.getUserId(),
+ options.getOpPackageName(), 0 /* cookie */, options.getSensorId(),
true /* shouldVibrate */, biometricLogger, biometricContext);
setRequestId(requestId);
mIsStrongBiometric = isStrongBiometric;
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
index 513b3e3e6e86..c2ca78e91fe3 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
@@ -274,8 +274,5 @@ class FingerprintEnrollClient extends EnrollClient<AidlSession> implements Udfps
}
@Override
- public void onPowerPressed() {
- onAcquired(BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_POWER_PRESSED,
- 0 /* vendorCode */);
- }
+ public void onPowerPressed() {}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClient.java
index c315ccf8dea2..ff9127f516af 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClient.java
@@ -45,10 +45,9 @@ class FingerprintInternalCleanupClient extends InternalCleanupClient<Fingerprint
@NonNull Supplier<AidlSession> lazyDaemon,
int userId, @NonNull String owner, int sensorId,
@NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
- @NonNull List<Fingerprint> enrolledList,
@NonNull FingerprintUtils utils, @NonNull Map<Integer, Long> authenticatorIds) {
super(context, lazyDaemon, userId, owner, sensorId, logger, biometricContext,
- enrolledList, utils, authenticatorIds);
+ utils, authenticatorIds);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
index 776d33172e68..23b6f84e6954 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
@@ -37,6 +37,7 @@ import android.hardware.biometrics.fingerprint.IFingerprint;
import android.hardware.biometrics.fingerprint.PointerContext;
import android.hardware.biometrics.fingerprint.SensorProps;
import android.hardware.fingerprint.Fingerprint;
+import android.hardware.fingerprint.FingerprintAuthenticateOptions;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.IFingerprintServiceReceiver;
@@ -422,15 +423,17 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
}
@Override
- public long scheduleFingerDetect(int sensorId, @NonNull IBinder token, int userId,
- @NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName,
+ public long scheduleFingerDetect(@NonNull IBinder token,
+ @NonNull ClientMonitorCallbackConverter callback,
+ @NonNull FingerprintAuthenticateOptions options,
int statsClient) {
final long id = mRequestCounter.incrementAndGet();
mHandler.post(() -> {
+ final int sensorId = options.getSensorId();
final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId);
final FingerprintDetectClient client = new FingerprintDetectClient(mContext,
- mSensors.get(sensorId).getLazySession(), token, id, callback, userId,
- opPackageName, sensorId,
+ mSensors.get(sensorId).getLazySession(), token, id, callback,
+ options,
createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient),
mBiometricContext,
mUdfpsOverlayController, mUdfpsOverlay, isStrongBiometric);
@@ -441,16 +444,19 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
}
@Override
- public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
- int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback,
- @NonNull String opPackageName, long requestId, boolean restricted, int statsClient,
+ public void scheduleAuthenticate(@NonNull IBinder token, long operationId,
+ int cookie, @NonNull ClientMonitorCallbackConverter callback,
+ @NonNull FingerprintAuthenticateOptions options,
+ long requestId, boolean restricted, int statsClient,
boolean allowBackgroundAuthentication) {
mHandler.post(() -> {
+ final int userId = options.getUserId();
+ final int sensorId = options.getSensorId();
final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId);
final FingerprintAuthenticationClient client = new FingerprintAuthenticationClient(
mContext, mSensors.get(sensorId).getLazySession(), token, requestId, callback,
- userId, operationId, restricted, opPackageName, cookie,
- false /* requireConfirmation */, sensorId,
+ operationId, restricted, options, cookie,
+ false /* requireConfirmation */,
createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient),
mBiometricContext, isStrongBiometric,
mTaskStackListener, mSensors.get(sensorId).getLockoutCache(),
@@ -485,14 +491,14 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
}
@Override
- public long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
- int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback,
- @NonNull String opPackageName, boolean restricted, int statsClient,
+ public long scheduleAuthenticate(@NonNull IBinder token, long operationId,
+ int cookie, @NonNull ClientMonitorCallbackConverter callback,
+ @NonNull FingerprintAuthenticateOptions options, boolean restricted, int statsClient,
boolean allowBackgroundAuthentication) {
final long id = mRequestCounter.incrementAndGet();
- scheduleAuthenticate(sensorId, token, operationId, userId, cookie, callback,
- opPackageName, id, restricted, statsClient, allowBackgroundAuthentication);
+ scheduleAuthenticate(token, operationId, cookie, callback,
+ options, id, restricted, statsClient, allowBackgroundAuthentication);
return id;
}
@@ -556,7 +562,6 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
public void scheduleInternalCleanup(int sensorId, int userId,
@Nullable ClientMonitorCallback callback, boolean favorHalEnrollments) {
mHandler.post(() -> {
- final List<Fingerprint> enrolledList = getEnrolledFingerprints(sensorId, userId);
final FingerprintInternalCleanupClient client =
new FingerprintInternalCleanupClient(mContext,
mSensors.get(sensorId).getLazySession(), userId,
@@ -564,7 +569,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
createLogger(BiometricsProtoEnums.ACTION_ENUMERATE,
BiometricsProtoEnums.CLIENT_UNKNOWN),
mBiometricContext,
- enrolledList, FingerprintUtils.getInstance(sensorId),
+ FingerprintUtils.getInstance(sensorId),
mSensors.get(sensorId).getAuthenticatorIds());
if (favorHalEnrollments) {
client.setFavorHalEnrollments();
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
index 4567addc4302..9e6f4e4f13f3 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
@@ -34,6 +34,7 @@ import android.hardware.biometrics.fingerprint.PointerContext;
import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
import android.hardware.biometrics.fingerprint.V2_2.IBiometricsFingerprintClientCallback;
import android.hardware.fingerprint.Fingerprint;
+import android.hardware.fingerprint.FingerprintAuthenticateOptions;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorProperties;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
@@ -631,17 +632,17 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
}
@Override
- public long scheduleFingerDetect(int sensorId, @NonNull IBinder token, int userId,
- @NonNull ClientMonitorCallbackConverter listener, @NonNull String opPackageName,
+ public long scheduleFingerDetect(@NonNull IBinder token,
+ @NonNull ClientMonitorCallbackConverter listener,
+ @NonNull FingerprintAuthenticateOptions options,
int statsClient) {
final long id = mRequestCounter.incrementAndGet();
mHandler.post(() -> {
- scheduleUpdateActiveUserWithoutHandler(userId);
+ scheduleUpdateActiveUserWithoutHandler(options.getUserId());
final boolean isStrongBiometric = Utils.isStrongBiometric(mSensorProperties.sensorId);
final FingerprintDetectClient client = new FingerprintDetectClient(mContext,
- mLazyDaemon, token, id, listener, userId, opPackageName,
- mSensorProperties.sensorId,
+ mLazyDaemon, token, id, listener, options,
createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient),
mBiometricContext, mUdfpsOverlayController, mUdfpsOverlay,
isStrongBiometric);
@@ -652,18 +653,18 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
}
@Override
- public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
- int userId, int cookie, @NonNull ClientMonitorCallbackConverter listener,
- @NonNull String opPackageName, long requestId, boolean restricted, int statsClient,
+ public void scheduleAuthenticate(@NonNull IBinder token, long operationId,
+ int cookie, @NonNull ClientMonitorCallbackConverter listener,
+ @NonNull FingerprintAuthenticateOptions options,
+ long requestId, boolean restricted, int statsClient,
boolean allowBackgroundAuthentication) {
mHandler.post(() -> {
- scheduleUpdateActiveUserWithoutHandler(userId);
+ scheduleUpdateActiveUserWithoutHandler(options.getUserId());
final boolean isStrongBiometric = Utils.isStrongBiometric(mSensorProperties.sensorId);
final FingerprintAuthenticationClient client = new FingerprintAuthenticationClient(
- mContext, mLazyDaemon, token, requestId, listener, userId, operationId,
- restricted, opPackageName, cookie, false /* requireConfirmation */,
- mSensorProperties.sensorId,
+ mContext, mLazyDaemon, token, requestId, listener, operationId,
+ restricted, options, cookie, false /* requireConfirmation */,
createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient),
mBiometricContext, isStrongBiometric,
mTaskStackListener, mLockoutTracker,
@@ -675,14 +676,14 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
}
@Override
- public long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
- int userId, int cookie, @NonNull ClientMonitorCallbackConverter listener,
- @NonNull String opPackageName, boolean restricted, int statsClient,
+ public long scheduleAuthenticate(@NonNull IBinder token, long operationId,
+ int cookie, @NonNull ClientMonitorCallbackConverter listener,
+ @NonNull FingerprintAuthenticateOptions options, boolean restricted, int statsClient,
boolean allowBackgroundAuthentication) {
final long id = mRequestCounter.incrementAndGet();
- scheduleAuthenticate(sensorId, token, operationId, userId, cookie, listener,
- opPackageName, id, restricted, statsClient, allowBackgroundAuthentication);
+ scheduleAuthenticate(token, operationId, cookie, listener,
+ options, id, restricted, statsClient, allowBackgroundAuthentication);
return id;
}
@@ -741,14 +742,12 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
mHandler.post(() -> {
scheduleUpdateActiveUserWithoutHandler(userId);
- final List<Fingerprint> enrolledList = getEnrolledFingerprints(
- mSensorProperties.sensorId, userId);
final FingerprintInternalCleanupClient client = new FingerprintInternalCleanupClient(
mContext, mLazyDaemon, userId, mContext.getOpPackageName(),
mSensorProperties.sensorId,
createLogger(BiometricsProtoEnums.ACTION_ENUMERATE,
BiometricsProtoEnums.CLIENT_UNKNOWN),
- mBiometricContext, enrolledList,
+ mBiometricContext,
FingerprintUtils.getLegacyInstance(mSensorId), mAuthenticatorIds);
mScheduler.scheduleClientMonitor(client, callback);
});
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java
index 73b1288d00d2..0a47c12bbe73 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java
@@ -22,6 +22,7 @@ import android.app.trust.TrustManager;
import android.content.ContentResolver;
import android.content.Context;
import android.hardware.biometrics.fingerprint.PointerContext;
+import android.hardware.fingerprint.FingerprintAuthenticateOptions;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
@@ -362,13 +363,16 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage
// Store the authClient parameters so it can be rescheduled
final IBinder token = client.getToken();
final long operationId = authClient.getOperationId();
- final int user = client.getTargetUserId();
final int cookie = client.getCookie();
final ClientMonitorCallbackConverter listener = client.getListener();
- final String opPackageName = client.getOwnerString();
final boolean restricted = authClient.isRestricted();
final int statsClient = client.getLogger().getStatsClient();
final boolean isKeyguard = authClient.isKeyguard();
+ final FingerprintAuthenticateOptions options =
+ new FingerprintAuthenticateOptions.Builder()
+ .setUserId(client.getTargetUserId())
+ .setOpPackageName(client.getOwnerString())
+ .build();
// Don't actually send cancel() to the HAL, since successful auth already finishes
// HAL authenticate() lifecycle. Just
@@ -376,8 +380,8 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage
// Schedule this only after we invoke onClientFinished for the previous client, so that
// internal preemption logic is not run.
- mFingerprint21.scheduleAuthenticate(mFingerprint21.mSensorProperties.sensorId, token,
- operationId, user, cookie, listener, opPackageName, restricted, statsClient,
+ mFingerprint21.scheduleAuthenticate(token,
+ operationId, cookie, listener, options, restricted, statsClient,
isKeyguard);
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
index a9cc897a2937..d22aef8b3971 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
@@ -26,6 +26,7 @@ import android.hardware.biometrics.BiometricFingerprintConstants;
import android.hardware.biometrics.BiometricManager.Authenticators;
import android.hardware.biometrics.fingerprint.PointerContext;
import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
+import android.hardware.fingerprint.FingerprintAuthenticateOptions;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.ISidefpsController;
import android.hardware.fingerprint.IUdfpsOverlay;
@@ -57,7 +58,8 @@ import java.util.function.Supplier;
* {@link android.hardware.biometrics.fingerprint.V2_1} and
* {@link android.hardware.biometrics.fingerprint.V2_2} HIDL interfaces.
*/
-class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFingerprint>
+class FingerprintAuthenticationClient
+ extends AuthenticationClient<IBiometricsFingerprint, FingerprintAuthenticateOptions>
implements Udfps {
private static final String TAG = "Biometrics/FingerprintAuthClient";
@@ -72,9 +74,9 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi
FingerprintAuthenticationClient(@NonNull Context context,
@NonNull Supplier<IBiometricsFingerprint> lazyDaemon,
@NonNull IBinder token, long requestId,
- @NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId,
- boolean restricted, @NonNull String owner, int cookie, boolean requireConfirmation,
- int sensorId, @NonNull BiometricLogger logger,
+ @NonNull ClientMonitorCallbackConverter listener, long operationId,
+ boolean restricted, @NonNull FingerprintAuthenticateOptions options,
+ int cookie, boolean requireConfirmation, @NonNull BiometricLogger logger,
@NonNull BiometricContext biometricContext, boolean isStrongBiometric,
@NonNull TaskStackListener taskStackListener,
@NonNull LockoutFrameworkImpl lockoutTracker,
@@ -84,11 +86,10 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi
boolean allowBackgroundAuthentication,
@NonNull FingerprintSensorPropertiesInternal sensorProps,
@Authenticators.Types int sensorStrength) {
- super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
- owner, cookie, requireConfirmation, sensorId, logger, biometricContext,
+ super(context, lazyDaemon, token, listener, operationId, restricted,
+ options, cookie, requireConfirmation, logger, biometricContext,
isStrongBiometric, taskStackListener, lockoutTracker, allowBackgroundAuthentication,
- false /* shouldVibrate */, false /* isKeyguardBypassEnabled */,
- sensorStrength);
+ false /* shouldVibrate */, sensorStrength);
setRequestId(requestId);
mLockoutFrameworkImpl = lockoutTracker;
mSensorOverlays = new SensorOverlays(udfpsOverlayController,
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java
index cfa9fb429fdd..362c820b9e8d 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java
@@ -24,6 +24,7 @@ import android.hardware.biometrics.BiometricFingerprintConstants;
import android.hardware.biometrics.BiometricOverlayConstants;
import android.hardware.biometrics.fingerprint.PointerContext;
import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
+import android.hardware.fingerprint.FingerprintAuthenticateOptions;
import android.hardware.fingerprint.IUdfpsOverlay;
import android.hardware.fingerprint.IUdfpsOverlayController;
import android.os.IBinder;
@@ -61,12 +62,13 @@ class FingerprintDetectClient extends AcquisitionClient<IBiometricsFingerprint>
public FingerprintDetectClient(@NonNull Context context,
@NonNull Supplier<IBiometricsFingerprint> lazyDaemon,
@NonNull IBinder token, long requestId,
- @NonNull ClientMonitorCallbackConverter listener, int userId, @NonNull String owner,
- int sensorId,
+ @NonNull ClientMonitorCallbackConverter listener,
+ @NonNull FingerprintAuthenticateOptions options,
@NonNull BiometricLogger biometricLogger, @NonNull BiometricContext biometricContext,
@Nullable IUdfpsOverlayController udfpsOverlayController,
@Nullable IUdfpsOverlay udfpsOverlay, boolean isStrongBiometric) {
- super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId,
+ super(context, lazyDaemon, token, listener, options.getUserId(),
+ options.getOpPackageName(), 0 /* cookie */, options.getSensorId(),
true /* shouldVibrate */, biometricLogger, biometricContext);
setRequestId(requestId);
mSensorOverlays = new SensorOverlays(udfpsOverlayController,
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintInternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintInternalCleanupClient.java
index 5e7cf3578411..8b61f5966c14 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintInternalCleanupClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintInternalCleanupClient.java
@@ -45,11 +45,10 @@ class FingerprintInternalCleanupClient
@NonNull Supplier<IBiometricsFingerprint> lazyDaemon, int userId,
@NonNull String owner, int sensorId,
@NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
- @NonNull List<Fingerprint> enrolledList,
@NonNull BiometricUtils<Fingerprint> utils,
@NonNull Map<Integer, Long> authenticatorIds) {
super(context, lazyDaemon, userId, owner, sensorId, logger, biometricContext,
- enrolledList, utils, authenticatorIds);
+ utils, authenticatorIds);
}
@Override
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index f7183e6b3ba7..fab138bb2931 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -18,9 +18,9 @@ package com.android.server.clipboard;
import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
import static android.companion.virtual.VirtualDeviceManager.ACTION_VIRTUAL_DEVICE_REMOVED;
-import static android.companion.virtual.VirtualDeviceManager.DEVICE_ID_DEFAULT;
-import static android.companion.virtual.VirtualDeviceManager.DEVICE_ID_INVALID;
import static android.companion.virtual.VirtualDeviceManager.EXTRA_VIRTUAL_DEVICE_ID;
+import static android.content.Context.DEVICE_ID_DEFAULT;
+import static android.content.Context.DEVICE_ID_INVALID;
import android.Manifest;
import android.annotation.NonNull;
@@ -484,6 +484,51 @@ public class ClipboardService extends SystemService {
sourcePackage);
}
+ @Override
+ public boolean areClipboardAccessNotificationsEnabledForUser(int userId) {
+ int result = getContext().checkCallingOrSelfPermission(
+ Manifest.permission.MANAGE_CLIPBOARD_ACCESS_NOTIFICATION);
+ if (result != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("areClipboardAccessNotificationsEnable requires "
+ + "permission MANAGE_CLIPBOARD_ACCESS_NOTIFICATION");
+ }
+
+ long callingId = Binder.clearCallingIdentity();
+ try {
+ return Settings.Secure.getIntForUser(getContext().getContentResolver(),
+ Settings.Secure.CLIPBOARD_SHOW_ACCESS_NOTIFICATIONS,
+ getDefaultClipboardAccessNotificationsSetting(), userId) != 0;
+ } finally {
+ Binder.restoreCallingIdentity(callingId);
+ }
+ }
+
+ @Override
+ public void setClipboardAccessNotificationsEnabledForUser(boolean enable, int userId) {
+ int result = getContext().checkCallingOrSelfPermission(
+ Manifest.permission.MANAGE_CLIPBOARD_ACCESS_NOTIFICATION);
+ if (result != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("areClipboardAccessNotificationsEnable requires "
+ + "permission MANAGE_CLIPBOARD_ACCESS_NOTIFICATION");
+ }
+
+ long callingId = Binder.clearCallingIdentity();
+ try {
+ ContentResolver resolver = getContext()
+ .createContextAsUser(UserHandle.of(userId), 0).getContentResolver();
+ Settings.Secure.putInt(resolver,
+ Settings.Secure.CLIPBOARD_SHOW_ACCESS_NOTIFICATIONS, (enable ? 1 : 0));
+ } finally {
+ Binder.restoreCallingIdentity(callingId);
+ }
+ }
+
+ private int getDefaultClipboardAccessNotificationsSetting() {
+ return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_CLIPBOARD,
+ ClipboardManager.DEVICE_CONFIG_SHOW_ACCESS_NOTIFICATIONS,
+ ClipboardManager.DEVICE_CONFIG_DEFAULT_SHOW_ACCESS_NOTIFICATIONS) ? 1 : 0;
+ }
+
private void checkAndSetPrimaryClip(
ClipData clip,
String callingPackage,
diff --git a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
index 3a4aaa76d633..1f82961efd22 100644
--- a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
+++ b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
@@ -31,7 +31,9 @@ import android.net.metrics.DnsEvent;
import android.net.metrics.NetworkMetrics;
import android.net.metrics.WakeupEvent;
import android.net.metrics.WakeupStats;
+import android.os.BatteryStatsInternal;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.Log;
@@ -44,6 +46,7 @@ import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.RingBuffer;
import com.android.internal.util.TokenBucket;
import com.android.net.module.util.BaseNetdEventListener;
+import com.android.server.LocalServices;
import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
import java.io.PrintWriter;
@@ -74,7 +77,7 @@ public class NetdEventListenerService extends BaseNetdEventListener {
// TODO: dedup this String constant with the one used in
// ConnectivityService#wakeupModifyInterface().
@VisibleForTesting
- static final String WAKEUP_EVENT_IFACE_PREFIX = "iface:";
+ static final String WAKEUP_EVENT_PREFIX_DELIM = ":";
// Array of aggregated DNS and connect events sent by netd, grouped by net id.
@GuardedBy("this")
@@ -278,17 +281,14 @@ public class NetdEventListenerService extends BaseNetdEventListener {
@Override
public synchronized void onWakeupEvent(String prefix, int uid, int ethertype, int ipNextHeader,
byte[] dstHw, String srcIp, String dstIp, int srcPort, int dstPort, long timestampNs) {
- String iface = prefix.replaceFirst(WAKEUP_EVENT_IFACE_PREFIX, "");
- final long timestampMs;
- if (timestampNs > 0) {
- timestampMs = timestampNs / NANOS_PER_MS;
- } else {
- timestampMs = System.currentTimeMillis();
+ final String[] prefixParts = prefix.split(WAKEUP_EVENT_PREFIX_DELIM);
+ if (prefixParts.length != 2) {
+ throw new IllegalArgumentException("Prefix " + prefix
+ + " required in format <nethandle>:<interface>");
}
- WakeupEvent event = new WakeupEvent();
- event.iface = iface;
- event.timestampMs = timestampMs;
+ final WakeupEvent event = new WakeupEvent();
+ event.iface = prefixParts[1];
event.uid = uid;
event.ethertype = ethertype;
event.dstHwAddr = MacAddress.fromBytes(dstHw);
@@ -297,11 +297,25 @@ public class NetdEventListenerService extends BaseNetdEventListener {
event.ipNextHeader = ipNextHeader;
event.srcPort = srcPort;
event.dstPort = dstPort;
+ if (timestampNs > 0) {
+ event.timestampMs = timestampNs / NANOS_PER_MS;
+ } else {
+ event.timestampMs = System.currentTimeMillis();
+ }
addWakeupEvent(event);
- String dstMac = event.dstHwAddr.toString();
+ final BatteryStatsInternal bsi = LocalServices.getService(BatteryStatsInternal.class);
+ if (bsi != null) {
+ final long netHandle = Long.parseLong(prefixParts[0]);
+ final long elapsedMs = SystemClock.elapsedRealtime() + event.timestampMs
+ - System.currentTimeMillis();
+ bsi.noteCpuWakingNetworkPacket(Network.fromNetworkHandle(netHandle), elapsedMs,
+ event.uid);
+ }
+
+ final String dstMac = event.dstHwAddr.toString();
FrameworkStatsLog.write(FrameworkStatsLog.PACKET_WAKEUP_OCCURRED,
- uid, iface, ethertype, dstMac, srcIp, dstIp, ipNextHeader, srcPort, dstPort);
+ uid, event.iface, ethertype, dstMac, srcIp, dstIp, ipNextHeader, srcPort, dstPort);
}
@Override
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 5d31e40ad9d3..1ce917cb7841 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -258,7 +258,8 @@ public class Vpn {
public static final int AUTOMATIC_KEEPALIVE_DELAY_SECONDS = 30;
// Default keepalive timeout for carrier config is 5 minutes. Mimic this.
- private static final int DEFAULT_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT = 5 * 60;
+ @VisibleForTesting
+ static final int DEFAULT_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT = 5 * 60;
// TODO: create separate trackers for each unique VPN to support
// automated reconnection
@@ -3253,6 +3254,8 @@ public class Vpn {
}
mActiveNetwork = network;
+ mUnderlyingLinkProperties = null;
+ mUnderlyingNetworkCapabilities = null;
mRetryCount = 0;
startOrMigrateIkeSession(network);
diff --git a/services/core/java/com/android/server/cpu/CpuMonitorService.java b/services/core/java/com/android/server/cpu/CpuMonitorService.java
index b0dfb8467fa7..4eefe5c8cad5 100644
--- a/services/core/java/com/android/server/cpu/CpuMonitorService.java
+++ b/services/core/java/com/android/server/cpu/CpuMonitorService.java
@@ -38,7 +38,7 @@ import java.util.concurrent.Executor;
/** Service to monitor CPU availability and usage. */
public final class CpuMonitorService extends SystemService {
static final String TAG = CpuMonitorService.class.getSimpleName();
- static final boolean DEBUG = Slogf.isLoggable(TAG, Log.DEBUG);
+ static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
// TODO(b/242722241): Make this a resource overlay property.
// Maintain 3 monitoring intervals:
// * One to poll very frequently when mCpuAvailabilityCallbackInfoByCallbacks are available and
diff --git a/services/core/java/com/android/server/display/BrightnessTracker.java b/services/core/java/com/android/server/display/BrightnessTracker.java
index 6e1640d545fe..22b6a53ab907 100644
--- a/services/core/java/com/android/server/display/BrightnessTracker.java
+++ b/services/core/java/com/android/server/display/BrightnessTracker.java
@@ -35,7 +35,6 @@ import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.display.AmbientBrightnessDayStats;
import android.hardware.display.BrightnessChangeEvent;
-import android.hardware.display.BrightnessConfiguration;
import android.hardware.display.ColorDisplayManager;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerInternal;
@@ -126,7 +125,7 @@ public class BrightnessTracker {
private static final int MSG_BRIGHTNESS_CHANGED = 1;
private static final int MSG_STOP_SENSOR_LISTENER = 2;
private static final int MSG_START_SENSOR_LISTENER = 3;
- private static final int MSG_BRIGHTNESS_CONFIG_CHANGED = 4;
+ private static final int MSG_SHOULD_COLLECT_COLOR_SAMPLE_CHANGED = 4;
private static final int MSG_SENSOR_CHANGED = 5;
private static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
@@ -162,7 +161,7 @@ public class BrightnessTracker {
private boolean mColorSamplingEnabled;
private int mNoFramesToSample;
private float mFrameRate;
- private BrightnessConfiguration mBrightnessConfiguration;
+ private boolean mShouldCollectColorSample = false;
// End of block of members that should only be accessed on the mBgHandler thread.
private @UserIdInt int mCurrentUserId = UserHandle.USER_NULL;
@@ -208,9 +207,9 @@ public class BrightnessTracker {
/**
* Update tracker with new brightness configuration.
*/
- public void setBrightnessConfiguration(BrightnessConfiguration brightnessConfiguration) {
- mBgHandler.obtainMessage(MSG_BRIGHTNESS_CONFIG_CHANGED,
- brightnessConfiguration).sendToTarget();
+ public void setShouldCollectColorSample(boolean shouldCollectColorSample) {
+ mBgHandler.obtainMessage(MSG_SHOULD_COLLECT_COLOR_SAMPLE_CHANGED,
+ shouldCollectColorSample).sendToTarget();
}
private void backgroundStart(float initialBrightness) {
@@ -320,7 +319,7 @@ public class BrightnessTracker {
* Notify the BrightnessTracker that the user has changed the brightness of the display.
*/
public void notifyBrightnessChanged(float brightness, boolean userInitiated,
- float powerBrightnessFactor, boolean isUserSetBrightness,
+ float powerBrightnessFactor, boolean wasShortTermModelActive,
boolean isDefaultBrightnessConfig, String uniqueDisplayId, float[] luxValues,
long[] luxTimestamps) {
if (DEBUG) {
@@ -329,7 +328,7 @@ public class BrightnessTracker {
}
Message m = mBgHandler.obtainMessage(MSG_BRIGHTNESS_CHANGED,
userInitiated ? 1 : 0, 0 /*unused*/, new BrightnessChangeValues(brightness,
- powerBrightnessFactor, isUserSetBrightness, isDefaultBrightnessConfig,
+ powerBrightnessFactor, wasShortTermModelActive, isDefaultBrightnessConfig,
mInjector.currentTimeMillis(), uniqueDisplayId, luxValues, luxTimestamps));
m.sendToTarget();
}
@@ -343,7 +342,7 @@ public class BrightnessTracker {
}
private void handleBrightnessChanged(float brightness, boolean userInitiated,
- float powerBrightnessFactor, boolean isUserSetBrightness,
+ float powerBrightnessFactor, boolean wasShortTermModelActive,
boolean isDefaultBrightnessConfig, long timestamp, String uniqueDisplayId,
float[] luxValues, long[] luxTimestamps) {
BrightnessChangeEvent.Builder builder;
@@ -368,7 +367,7 @@ public class BrightnessTracker {
builder.setBrightness(brightness);
builder.setTimeStamp(timestamp);
builder.setPowerBrightnessFactor(powerBrightnessFactor);
- builder.setUserBrightnessPoint(isUserSetBrightness);
+ builder.setUserBrightnessPoint(wasShortTermModelActive);
builder.setIsDefaultBrightnessConfig(isDefaultBrightnessConfig);
builder.setUniqueDisplayId(uniqueDisplayId);
@@ -827,8 +826,7 @@ public class BrightnessTracker {
if (!mInjector.isBrightnessModeAutomatic(mContentResolver)
|| !mInjector.isInteractive(mContext)
|| mColorSamplingEnabled
- || mBrightnessConfiguration == null
- || !mBrightnessConfiguration.shouldCollectColorSamples()) {
+ || !mShouldCollectColorSample) {
return;
}
@@ -997,7 +995,7 @@ public class BrightnessTracker {
BrightnessChangeValues values = (BrightnessChangeValues) msg.obj;
boolean userInitiatedChange = (msg.arg1 == 1);
handleBrightnessChanged(values.brightness, userInitiatedChange,
- values.powerBrightnessFactor, values.isUserSetBrightness,
+ values.powerBrightnessFactor, values.wasShortTermModelActive,
values.isDefaultBrightnessConfig, values.timestamp,
values.uniqueDisplayId, values.luxValues, values.luxTimestamps);
break;
@@ -1009,14 +1007,11 @@ public class BrightnessTracker {
stopSensorListener();
disableColorSampling();
break;
- case MSG_BRIGHTNESS_CONFIG_CHANGED:
- mBrightnessConfiguration = (BrightnessConfiguration) msg.obj;
- boolean shouldCollectColorSamples =
- mBrightnessConfiguration != null
- && mBrightnessConfiguration.shouldCollectColorSamples();
- if (shouldCollectColorSamples && !mColorSamplingEnabled) {
+ case MSG_SHOULD_COLLECT_COLOR_SAMPLE_CHANGED:
+ mShouldCollectColorSample = (boolean) msg.obj;
+ if (mShouldCollectColorSample && !mColorSamplingEnabled) {
enableColorSampling();
- } else if (!shouldCollectColorSamples && mColorSamplingEnabled) {
+ } else if (!mShouldCollectColorSample && mColorSamplingEnabled) {
disableColorSampling();
}
break;
@@ -1031,7 +1026,7 @@ public class BrightnessTracker {
private static class BrightnessChangeValues {
public final float brightness;
public final float powerBrightnessFactor;
- public final boolean isUserSetBrightness;
+ public final boolean wasShortTermModelActive;
public final boolean isDefaultBrightnessConfig;
public final long timestamp;
public final String uniqueDisplayId;
@@ -1039,11 +1034,11 @@ public class BrightnessTracker {
public final long[] luxTimestamps;
BrightnessChangeValues(float brightness, float powerBrightnessFactor,
- boolean isUserSetBrightness, boolean isDefaultBrightnessConfig,
+ boolean wasShortTermModelActive, boolean isDefaultBrightnessConfig,
long timestamp, String uniqueDisplayId, float[] luxValues, long[] luxTimestamps) {
this.brightness = brightness;
this.powerBrightnessFactor = powerBrightnessFactor;
- this.isUserSetBrightness = isUserSetBrightness;
+ this.wasShortTermModelActive = wasShortTermModelActive;
this.isDefaultBrightnessConfig = isDefaultBrightnessConfig;
this.timestamp = timestamp;
this.uniqueDisplayId = uniqueDisplayId;
diff --git a/services/core/java/com/android/server/display/DeviceStateToLayoutMap.java b/services/core/java/com/android/server/display/DeviceStateToLayoutMap.java
index ce29013f1623..63218ee4e12d 100644
--- a/services/core/java/com/android/server/display/DeviceStateToLayoutMap.java
+++ b/services/core/java/com/android/server/display/DeviceStateToLayoutMap.java
@@ -138,6 +138,8 @@ class DeviceStateToLayoutMap {
display.setPosition(POSITION_UNKNOWN);
}
display.setRefreshRateZoneId(d.getRefreshRateZoneId());
+ display.setRefreshRateThermalThrottlingMapId(
+ d.getRefreshRateThermalThrottlingMapId());
}
}
} catch (IOException | DatatypeConfigurationException | XmlPullParserException e) {
diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java
index 99e709ea3fd8..d57dc471694e 100644
--- a/services/core/java/com/android/server/display/DisplayDevice.java
+++ b/services/core/java/com/android/server/display/DisplayDevice.java
@@ -22,11 +22,14 @@ import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.display.DisplayViewport;
import android.os.IBinder;
+import android.util.Slog;
import android.view.Display;
import android.view.DisplayAddress;
import android.view.Surface;
import android.view.SurfaceControl;
+import com.android.server.display.mode.DisplayModeDirector;
+
import java.io.PrintWriter;
/**
@@ -37,6 +40,7 @@ import java.io.PrintWriter;
* </p>
*/
abstract class DisplayDevice {
+ private static final String TAG = "DisplayDevice";
private static final Display.Mode EMPTY_DISPLAY_MODE = new Display.Mode.Builder().build();
private final DisplayAdapter mDisplayAdapter;
@@ -267,10 +271,13 @@ abstract class DisplayDevice {
/**
* Sets the display layer stack while in a transaction.
*/
- public final void setLayerStackLocked(SurfaceControl.Transaction t, int layerStack) {
+ public final void setLayerStackLocked(SurfaceControl.Transaction t, int layerStack,
+ int layerStackTag) {
if (mCurrentLayerStack != layerStack) {
mCurrentLayerStack = layerStack;
t.setDisplayLayerStack(mDisplayToken, layerStack);
+ Slog.i(TAG, "[" + layerStackTag + "] Layerstack set to " + layerStack + " for "
+ + mUniqueId);
}
}
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index d9b350189fc4..cdab77def83e 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -31,6 +31,7 @@ import android.text.TextUtils;
import android.util.MathUtils;
import android.util.Pair;
import android.util.Slog;
+import android.util.SparseArray;
import android.util.Spline;
import android.view.DisplayAddress;
import android.view.SurfaceControl;
@@ -54,6 +55,8 @@ import com.android.server.display.config.NitsMap;
import com.android.server.display.config.Point;
import com.android.server.display.config.RefreshRateConfigs;
import com.android.server.display.config.RefreshRateRange;
+import com.android.server.display.config.RefreshRateThrottlingMap;
+import com.android.server.display.config.RefreshRateThrottlingPoint;
import com.android.server.display.config.RefreshRateZone;
import com.android.server.display.config.SdrHdrRatioMap;
import com.android.server.display.config.SdrHdrRatioPoint;
@@ -88,6 +91,7 @@ import javax.xml.datatype.DatatypeConfigurationException;
* <pre>
* {@code
* <displayConfiguration>
+ * <name>Built-In Display</name>
* <densityMapping>
* <density>
* <height>480</height>
@@ -149,9 +153,26 @@ import javax.xml.datatype.DatatypeConfigurationException;
* <brightness>0.005</brightness>
* </brightnessThrottlingPoint>
* </concurrentDisplaysBrightnessThrottlingMap>
+ * <refreshRateThrottlingMap>
+ * <refreshRateThrottlingPoint>
+ * <thermalStatus>critical</thermalStatus>
+ * <refreshRateRange>
+ * <minimum>0</minimum>
+ * <maximum>60</maximum>
+ * </refreshRateRange>
+ * </refreshRateThrottlingPoint>
+ * </refreshRateThrottlingMap>
* </thermalThrottling>
*
* <refreshRate>
+ * <refreshRateZoneProfiles>
+ * <refreshRateZoneProfile id="concurrent">
+ * <refreshRateRange>
+ * <minimum>60</minimum>
+ * <maximum>60</maximum>
+ * </refreshRateRange>
+ * </refreshRateZoneProfile>
+ * </refreshRateZoneProfiles>
* <defaultRefreshRateInHbmHdr>75</defaultRefreshRateInHbmHdr>
* <defaultRefreshRateInHbmSunlight>75</defaultRefreshRateInHbmSunlight>
* <lowerBlockingZoneConfigs>
@@ -417,7 +438,7 @@ public class DisplayDeviceConfig {
public static final String QUIRK_CAN_SET_BRIGHTNESS_VIA_HWC = "canSetBrightnessViaHwc";
- static final String DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID = "default";
+ static final String DEFAULT_ID = "default";
private static final float BRIGHTNESS_DEFAULT = 0.5f;
private static final String ETC_DIR = "etc";
@@ -479,6 +500,10 @@ public class DisplayDeviceConfig {
private final List<RefreshRateLimitation> mRefreshRateLimitations =
new ArrayList<>(2 /*initialCapacity*/);
+ // Name of the display, if configured.
+ @Nullable
+ private String mName;
+
// Nits and backlight values that are loaded from either the display device config file, or
// config.xml. These are the raw values and just used for the dumpsys
private float[] mRawNits;
@@ -662,7 +687,11 @@ public class DisplayDeviceConfig {
private int[] mHighDisplayBrightnessThresholds = DEFAULT_BRIGHTNESS_THRESHOLDS;
private int[] mHighAmbientBrightnessThresholds = DEFAULT_BRIGHTNESS_THRESHOLDS;
- private Map<String, BrightnessThrottlingData> mBrightnessThrottlingDataMap = new HashMap();
+ private final Map<String, BrightnessThrottlingData> mBrightnessThrottlingDataMap =
+ new HashMap<>();
+
+ private final Map<String, SparseArray<SurfaceControl.RefreshRateRange>>
+ mRefreshRateThrottlingMap = new HashMap<>();
@Nullable
private HostUsiVersion mHostUsiVersion;
@@ -808,6 +837,15 @@ public class DisplayDeviceConfig {
return config;
}
+ /** The name of the display.
+ *
+ * @return The name of the display.
+ */
+ @Nullable
+ public String getName() {
+ return mName;
+ }
+
/**
* Return the brightness mapping nits array.
*
@@ -1260,7 +1298,7 @@ public class DisplayDeviceConfig {
return mAmbientDarkeningPercentagesIdle;
}
- SensorData getAmbientLightSensor() {
+ public SensorData getAmbientLightSensor() {
return mAmbientLightSensor;
}
@@ -1315,6 +1353,17 @@ public class DisplayDeviceConfig {
}
/**
+ * @param id - throttling data id or null for default
+ * @return refresh rate throttling configuration
+ */
+ @Nullable
+ public SparseArray<SurfaceControl.RefreshRateRange> getRefreshRateThrottlingData(
+ @Nullable String id) {
+ String key = id == null ? DEFAULT_ID : id;
+ return mRefreshRateThrottlingMap.get(key);
+ }
+
+ /**
* @return Auto brightness darkening light debounce
*/
public long getAutoBrightnessDarkeningLightDebounce() {
@@ -1552,6 +1601,8 @@ public class DisplayDeviceConfig {
+ ", mRefreshRateZoneProfiles= " + mRefreshRateZoneProfiles
+ ", mDefaultRefreshRateInHbmHdr= " + mDefaultRefreshRateInHbmHdr
+ ", mDefaultRefreshRateInHbmSunlight= " + mDefaultRefreshRateInHbmSunlight
+ + ", mRefreshRateThrottlingMap= " + mRefreshRateThrottlingMap
+ + "\n"
+ ", mLowDisplayBrightnessThresholds= "
+ Arrays.toString(mLowDisplayBrightnessThresholds)
+ ", mLowAmbientBrightnessThresholds= "
@@ -1609,11 +1660,12 @@ public class DisplayDeviceConfig {
try (InputStream in = new BufferedInputStream(new FileInputStream(configFile))) {
final DisplayConfiguration config = XmlParser.read(in);
if (config != null) {
+ loadName(config);
loadDensityMapping(config);
loadBrightnessDefaultFromDdcXml(config);
loadBrightnessConstraintsFromConfigXml();
loadBrightnessMap(config);
- loadBrightnessThrottlingMaps(config);
+ loadThermalThrottlingConfig(config);
loadHighBrightnessModeData(config);
loadQuirks(config);
loadBrightnessRamps(config);
@@ -1680,6 +1732,10 @@ public class DisplayDeviceConfig {
}
}
+ private void loadName(DisplayConfiguration config) {
+ mName = config.getName();
+ }
+
private void loadDensityMapping(DisplayConfiguration config) {
if (config.getDensityMapping() == null) {
return;
@@ -1823,13 +1879,17 @@ public class DisplayDeviceConfig {
return Spline.createSpline(nits, ratios);
}
- private void loadBrightnessThrottlingMaps(DisplayConfiguration config) {
+ private void loadThermalThrottlingConfig(DisplayConfiguration config) {
final ThermalThrottling throttlingConfig = config.getThermalThrottling();
if (throttlingConfig == null) {
Slog.i(TAG, "No thermal throttling config found");
return;
}
+ loadBrightnessThrottlingMaps(throttlingConfig);
+ loadRefreshRateThermalThrottlingMap(throttlingConfig);
+ }
+ private void loadBrightnessThrottlingMaps(ThermalThrottling throttlingConfig) {
final List<BrightnessThrottlingMap> maps = throttlingConfig.getBrightnessThrottlingMap();
if (maps == null || maps.isEmpty()) {
Slog.i(TAG, "No brightness throttling map found");
@@ -1855,7 +1915,7 @@ public class DisplayDeviceConfig {
}
if (!badConfig) {
- String id = map.getId() == null ? DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID
+ String id = map.getId() == null ? DEFAULT_ID
: map.getId();
if (mBrightnessThrottlingDataMap.containsKey(id)) {
throw new RuntimeException("Brightness throttling data with ID " + id
@@ -1867,6 +1927,57 @@ public class DisplayDeviceConfig {
}
}
+ private void loadRefreshRateThermalThrottlingMap(ThermalThrottling throttlingConfig) {
+ List<RefreshRateThrottlingMap> maps = throttlingConfig.getRefreshRateThrottlingMap();
+ if (maps == null || maps.isEmpty()) {
+ Slog.w(TAG, "RefreshRateThrottling: map not found");
+ return;
+ }
+
+ for (RefreshRateThrottlingMap map : maps) {
+ List<RefreshRateThrottlingPoint> points = map.getRefreshRateThrottlingPoint();
+ String id = map.getId() == null ? DEFAULT_ID : map.getId();
+
+ if (points == null || points.isEmpty()) {
+ // Expected at lease 1 throttling point for each map
+ Slog.w(TAG, "RefreshRateThrottling: points not found for mapId=" + id);
+ continue;
+ }
+ if (mRefreshRateThrottlingMap.containsKey(id)) {
+ Slog.wtf(TAG, "RefreshRateThrottling: map already exists, mapId=" + id);
+ continue;
+ }
+
+ SparseArray<SurfaceControl.RefreshRateRange> refreshRates = new SparseArray<>();
+ for (RefreshRateThrottlingPoint point : points) {
+ ThermalStatus status = point.getThermalStatus();
+ if (!thermalStatusIsValid(status)) {
+ Slog.wtf(TAG,
+ "RefreshRateThrottling: Invalid thermalStatus=" + status.getRawName()
+ + ",mapId=" + id);
+ continue;
+ }
+ int thermalStatusInt = convertThermalStatus(status);
+ if (refreshRates.contains(thermalStatusInt)) {
+ Slog.wtf(TAG, "RefreshRateThrottling: thermalStatus=" + status.getRawName()
+ + " is already in the map, mapId=" + id);
+ continue;
+ }
+
+ refreshRates.put(thermalStatusInt, new SurfaceControl.RefreshRateRange(
+ point.getRefreshRateRange().getMinimum().floatValue(),
+ point.getRefreshRateRange().getMaximum().floatValue()
+ ));
+ }
+ if (refreshRates.size() == 0) {
+ Slog.w(TAG, "RefreshRateThrottling: no valid throttling points fond for map, mapId="
+ + id);
+ continue;
+ }
+ mRefreshRateThrottlingMap.put(id, refreshRates);
+ }
+ }
+
private void loadRefreshRateSetting(DisplayConfiguration config) {
final RefreshRateConfigs refreshRateConfigs =
(config == null) ? null : config.getRefreshRate();
@@ -2821,7 +2932,7 @@ public class DisplayDeviceConfig {
/**
* Uniquely identifies a Sensor, with the combination of Type and Name.
*/
- static class SensorData {
+ public static class SensorData {
public String type;
public String name;
public float minRefreshRate = 0.0f;
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 81e550e3d62f..21cc172f5908 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -24,6 +24,7 @@ import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE;
import static android.hardware.display.DisplayManager.EventsMask;
+import static android.hardware.display.DisplayManager.HDR_OUTPUT_CONTROL_FLAG;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
@@ -38,8 +39,10 @@ import static android.hardware.display.DisplayManagerGlobal.DisplayEvent;
import static android.hardware.display.DisplayViewport.VIEWPORT_EXTERNAL;
import static android.hardware.display.DisplayViewport.VIEWPORT_INTERNAL;
import static android.hardware.display.DisplayViewport.VIEWPORT_VIRTUAL;
+import static android.hardware.display.HdrConversionMode.HDR_CONVERSION_UNSUPPORTED;
import static android.os.Process.FIRST_APPLICATION_UID;
import static android.os.Process.ROOT_UID;
+import static android.provider.DeviceConfig.NAMESPACE_DISPLAY_MANAGER;
import android.Manifest;
import android.annotation.NonNull;
@@ -137,6 +140,7 @@ import android.window.ScreenCapture;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.display.BrightnessSynchronizer;
+import com.android.internal.os.BackgroundThread;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.IndentingPrintWriter;
@@ -148,6 +152,7 @@ import com.android.server.UiThread;
import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
import com.android.server.display.DisplayDeviceConfig.SensorData;
import com.android.server.display.layout.Layout;
+import com.android.server.display.mode.DisplayModeDirector;
import com.android.server.display.utils.SensorUtils;
import com.android.server.input.InputManagerInternal;
import com.android.server.wm.SurfaceAnimationThread;
@@ -232,6 +237,9 @@ public final class DisplayManagerService extends SystemService {
private static final int MSG_LOAD_BRIGHTNESS_CONFIGURATIONS = 6;
private static final int MSG_DELIVER_DISPLAY_EVENT_FRAME_RATE_OVERRIDE = 7;
private static final int MSG_DELIVER_DISPLAY_GROUP_EVENT = 8;
+ private static final int[] EMPTY_ARRAY = new int[0];
+ private static final HdrConversionMode HDR_CONVERSION_MODE_UNSUPPORTED = new HdrConversionMode(
+ HDR_CONVERSION_UNSUPPORTED);
private final Context mContext;
private final DisplayManagerHandler mHandler;
@@ -250,6 +258,10 @@ public final class DisplayManagerService extends SystemService {
@GuardedBy("mSyncRoot")
private boolean mAreUserDisabledHdrTypesAllowed = true;
+ // This value indicates whether or not HDR output control is enabled.
+ // It is read from DeviceConfig and is updated via a listener if the config changes.
+ private volatile boolean mIsHdrOutputControlEnabled;
+
// Display mode chosen by user.
private Display.Mode mUserPreferredMode;
// HDR conversion mode chosen by user
@@ -674,6 +686,11 @@ public final class DisplayManagerService extends SystemService {
synchronized (mSyncRoot) {
mSafeMode = safeMode;
mSystemReady = true;
+ mIsHdrOutputControlEnabled = isDeviceConfigHdrOutputControlEnabled();
+ DeviceConfig.addOnPropertiesChangedListener(NAMESPACE_DISPLAY_MANAGER,
+ BackgroundThread.getExecutor(),
+ properties -> mIsHdrOutputControlEnabled =
+ isDeviceConfigHdrOutputControlEnabled());
// Just in case the top inset changed before the system was ready. At this point, any
// relevant configuration should be in place.
recordTopInsetLocked(mLogicalDisplayMapper.getDisplayLocked(Display.DEFAULT_DISPLAY));
@@ -681,7 +698,9 @@ public final class DisplayManagerService extends SystemService {
updateSettingsLocked();
updateUserDisabledHdrTypesFromSettingsLocked();
updateUserPreferredDisplayModeSettingsLocked();
- updateHdrConversionModeSettingsLocked();
+ if (mIsHdrOutputControlEnabled) {
+ updateHdrConversionModeSettingsLocked();
+ }
}
mDisplayModeDirector.setDesiredDisplayModeSpecsListener(
@@ -702,6 +721,12 @@ public final class DisplayManagerService extends SystemService {
mContext.registerReceiver(mIdleModeReceiver, filter);
}
+ private boolean isDeviceConfigHdrOutputControlEnabled() {
+ return DeviceConfig.getBoolean(NAMESPACE_DISPLAY_MANAGER,
+ HDR_OUTPUT_CONTROL_FLAG,
+ true);
+ }
+
@VisibleForTesting
Handler getDisplayHandler() {
return mHandler;
@@ -2080,8 +2105,7 @@ public final class DisplayManagerService extends SystemService {
}
}
- // TODO (b/264979880) - Add unit test for HDR output control methods.
- private void setHdrConversionModeInternal(HdrConversionMode hdrConversionMode) {
+ void setHdrConversionModeInternal(HdrConversionMode hdrConversionMode) {
if (!mInjector.getHdrOutputConversionSupport()) {
return;
}
@@ -2115,9 +2139,9 @@ public final class DisplayManagerService extends SystemService {
}
}
- private HdrConversionMode getHdrConversionModeSettingInternal() {
+ HdrConversionMode getHdrConversionModeSettingInternal() {
if (!mInjector.getHdrOutputConversionSupport()) {
- return new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_UNSUPPORTED);
+ return HDR_CONVERSION_MODE_UNSUPPORTED;
}
synchronized (mSyncRoot) {
if (mHdrConversionMode != null) {
@@ -2129,7 +2153,7 @@ public final class DisplayManagerService extends SystemService {
private HdrConversionMode getHdrConversionModeInternal() {
if (!mInjector.getHdrOutputConversionSupport()) {
- return new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_UNSUPPORTED);
+ return HDR_CONVERSION_MODE_UNSUPPORTED;
}
HdrConversionMode mode;
synchronized (mSyncRoot) {
@@ -3948,6 +3972,9 @@ public final class DisplayManagerService extends SystemService {
@Override // Binder call
public void setHdrConversionMode(HdrConversionMode hdrConversionMode) {
+ if (!mIsHdrOutputControlEnabled) {
+ return;
+ }
mContext.enforceCallingOrSelfPermission(
Manifest.permission.MODIFY_HDR_CONVERSION_MODE,
"Permission required to set the HDR conversion mode.");
@@ -3961,6 +3988,9 @@ public final class DisplayManagerService extends SystemService {
@Override // Binder call
public HdrConversionMode getHdrConversionModeSetting() {
+ if (!mIsHdrOutputControlEnabled) {
+ return HDR_CONVERSION_MODE_UNSUPPORTED;
+ }
final long token = Binder.clearCallingIdentity();
try {
return getHdrConversionModeSettingInternal();
@@ -3971,6 +4001,9 @@ public final class DisplayManagerService extends SystemService {
@Override // Binder call
public HdrConversionMode getHdrConversionMode() {
+ if (!mIsHdrOutputControlEnabled) {
+ return HDR_CONVERSION_MODE_UNSUPPORTED;
+ }
final long token = Binder.clearCallingIdentity();
try {
return getHdrConversionModeInternal();
@@ -3982,6 +4015,9 @@ public final class DisplayManagerService extends SystemService {
@Display.HdrCapabilities.HdrType
@Override // Binder call
public int[] getSupportedHdrOutputTypes() {
+ if (!mIsHdrOutputControlEnabled) {
+ return EMPTY_ARRAY;
+ }
final long token = Binder.clearCallingIdentity();
try {
return getSupportedHdrOutputTypesInternal();
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index d4877eb4973d..84fe8f21b764 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -885,7 +885,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
final boolean isInTransition = mLogicalDisplay.isInTransitionLocked();
final String brightnessThrottlingDataId =
mLogicalDisplay.getBrightnessThrottlingDataIdLocked();
- mHandler.post(() -> {
+ mHandler.postAtTime(() -> {
boolean changed = false;
if (mDisplayDevice != device) {
changed = true;
@@ -916,7 +916,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
if (changed) {
updatePowerState();
}
- });
+ }, mClock.uptimeMillis());
}
/**
@@ -940,10 +940,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mAutomaticBrightnessController.stop();
}
- if (mScreenOffBrightnessSensorController != null) {
- mScreenOffBrightnessSensorController.stop();
- }
-
if (mBrightnessSetting != null) {
mBrightnessSetting.unregisterListener(mBrightnessSettingListener);
}
@@ -1190,6 +1186,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
if (mScreenOffBrightnessSensorController != null) {
mScreenOffBrightnessSensorController.stop();
+ mScreenOffBrightnessSensorController = null;
}
loadScreenOffBrightnessSensor();
int[] sensorValueToLux = mDisplayDeviceConfig.getScreenOffBrightnessSensorValueToLux();
@@ -1311,6 +1308,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mPowerState.stop();
mPowerState = null;
}
+
+ if (mScreenOffBrightnessSensorController != null) {
+ mScreenOffBrightnessSensorController.stop();
+ }
}
private void updatePowerState() {
@@ -1538,10 +1539,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// user, or is a temporary adjustment.
boolean userInitiatedChange = (Float.isNaN(brightnessState))
&& (autoBrightnessAdjustmentChanged || userSetBrightnessChanged);
- boolean hadUserBrightnessPoint = false;
+ boolean wasShortTermModelActive = false;
// Configure auto-brightness.
if (mAutomaticBrightnessController != null) {
- hadUserBrightnessPoint = mAutomaticBrightnessController.hasUserDataPoints();
+ wasShortTermModelActive = mAutomaticBrightnessController.hasUserDataPoints();
mAutomaticBrightnessController.configure(autoBrightnessState,
mBrightnessConfiguration,
mLastUserSetScreenBrightness,
@@ -1555,7 +1556,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
: AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED);
if (mBrightnessTracker != null) {
- mBrightnessTracker.setBrightnessConfiguration(mBrightnessConfiguration);
+ mBrightnessTracker.setShouldCollectColorSample(mBrightnessConfiguration != null
+ && mBrightnessConfiguration.shouldCollectColorSamples());
}
boolean updateScreenBrightnessSetting = false;
@@ -1823,7 +1825,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
userInitiatedChange = false;
}
notifyBrightnessTrackerChanged(brightnessState, userInitiatedChange,
- hadUserBrightnessPoint);
+ wasShortTermModelActive);
}
// We save the brightness info *after* the brightness setting has been changed and
@@ -1865,7 +1867,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mTempBrightnessEvent.setRbcStrength(mCdsi != null
? mCdsi.getReduceBrightColorsStrength() : -1);
mTempBrightnessEvent.setPowerFactor(mPowerRequest.screenLowPowerBrightnessFactor);
- mTempBrightnessEvent.setWasShortTermModelActive(hadUserBrightnessPoint);
+ mTempBrightnessEvent.setWasShortTermModelActive(wasShortTermModelActive);
// Temporary is what we use during slider interactions. We avoid logging those so that
// we don't spam logcat when the slider is being used.
boolean tempToTempTransition =
@@ -1886,10 +1888,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
? BrightnessEvent.FLAG_USER_SET : 0));
Slog.i(mTag, newEvent.toString(/* includeTime= */ false));
- // Log all events which are not temporary
- if (newEvent.getReason().getReason() != BrightnessReason.REASON_TEMPORARY) {
- logBrightnessEvent(newEvent, unthrottledBrightnessState);
- }
if (userSetBrightnessChanged) {
logManualBrightnessEvent(newEvent);
}
@@ -2638,7 +2636,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
private void notifyBrightnessTrackerChanged(float brightness, boolean userInitiated,
- boolean hadUserDataPoint) {
+ boolean wasShortTermModelActive) {
final float brightnessInNits = convertToNits(brightness);
if (mUseAutoBrightness && brightnessInNits >= 0.0f
&& mAutomaticBrightnessController != null && mBrightnessTracker != null) {
@@ -2649,7 +2647,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
? mPowerRequest.screenLowPowerBrightnessFactor
: 1.0f;
mBrightnessTracker.notifyBrightnessChanged(brightnessInNits, userInitiated,
- powerFactor, hadUserDataPoint,
+ powerFactor, wasShortTermModelActive,
mAutomaticBrightnessController.isDefaultConfig(), mUniqueDisplayId,
mAutomaticBrightnessController.getLastSensorValues(),
mAutomaticBrightnessController.getLastSensorTimestamps());
@@ -3002,154 +3000,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
}
- // Return bucket index of range_[left]_[right] where
- // left <= nits < right
- private int nitsToRangeIndex(float nits) {
- float[] boundaries = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50, 60, 70, 80,
- 90, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1200,
- 1400, 1600, 1800, 2000, 2250, 2500, 2750, 3000};
- int[] rangeIndex = {
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_UNKNOWN,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_0_1,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_1_2,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_2_3,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_3_4,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_4_5,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_5_6,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_6_7,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_7_8,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_8_9,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_9_10,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_10_20,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_20_30,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_30_40,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_40_50,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_50_60,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_60_70,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_70_80,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_80_90,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_90_100,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_100_200,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_200_300,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_300_400,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_400_500,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_500_600,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_600_700,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_700_800,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_800_900,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_900_1000,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_1000_1200,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_1200_1400,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_1400_1600,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_1600_1800,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_1800_2000,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_2000_2250,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_2250_2500,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_2500_2750,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_2750_3000,
- };
- for (int i = 0; i < boundaries.length; i++) {
- if (nits < boundaries[i]) {
- return rangeIndex[i];
- }
- }
- return FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_3000_INF;
- }
-
- private int convertBrightnessReasonToStatsEnum(int brightnessReason) {
- switch(brightnessReason) {
- case BrightnessReason.REASON_UNKNOWN:
- return FrameworkStatsLog
- .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_UNKNOWN;
- case BrightnessReason.REASON_MANUAL:
- return FrameworkStatsLog
- .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_MANUAL;
- case BrightnessReason.REASON_DOZE:
- return FrameworkStatsLog
- .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_DOZE;
- case BrightnessReason.REASON_DOZE_DEFAULT:
- return FrameworkStatsLog
- .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_DOZE_DEFAULT;
- case BrightnessReason.REASON_AUTOMATIC:
- return FrameworkStatsLog
- .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_AUTOMATIC;
- case BrightnessReason.REASON_SCREEN_OFF:
- return FrameworkStatsLog
- .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_SCREEN_OFF;
- case BrightnessReason.REASON_OVERRIDE:
- return FrameworkStatsLog
- .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_OVERRIDE;
- case BrightnessReason.REASON_TEMPORARY:
- return FrameworkStatsLog
- .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_TEMPORARY;
- case BrightnessReason.REASON_BOOST:
- return FrameworkStatsLog
- .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_BOOST;
- case BrightnessReason.REASON_SCREEN_OFF_BRIGHTNESS_SENSOR:
- return FrameworkStatsLog
- .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_SCREEN_OFF_BRIGHTNESS_SENSOR;
- case BrightnessReason.REASON_FOLLOWER:
- return FrameworkStatsLog
- .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_FOLLOWER;
- }
- return FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_UNKNOWN;
- }
-
- private int convertHbmModeToStatsEnum(int mode) {
- switch(mode) {
- case BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF:
- return FrameworkStatsLog
- .SCREEN_BRIGHTNESS_CHANGED_V2__HBM_MODE__HIGH_BRIGHTNESS_MODE_OFF;
- case BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT:
- return FrameworkStatsLog
- .SCREEN_BRIGHTNESS_CHANGED_V2__HBM_MODE__HIGH_BRIGHTNESS_MODE_SUNLIGHT;
- case BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR:
- return FrameworkStatsLog
- .SCREEN_BRIGHTNESS_CHANGED_V2__HBM_MODE__HIGH_BRIGHTNESS_MODE_HDR;
- }
- return FrameworkStatsLog
- .SCREEN_BRIGHTNESS_CHANGED_V2__HBM_MODE__HIGH_BRIGHTNESS_MODE_OFF;
- }
-
- // unmodifiedBrightness: the brightness value that has not been
- // modified by any modifiers(dimming/throttling/low-power-mode)
- private void logBrightnessEvent(BrightnessEvent event, float unmodifiedBrightness) {
- int modifier = event.getReason().getModifier();
- // It's easier to check if the brightness is at maximum level using the brightness
- // value untouched by any modifiers
- boolean brightnessIsMax = unmodifiedBrightness == event.getHbmMax();
- float brightnessInNits = convertToNits(event.getBrightness());
- float lowPowerModeFactor = event.getPowerFactor();
- int rbcStrength = event.getRbcStrength();
- float hbmMaxNits = convertToNits(event.getHbmMax());
- float thermalCapNits = convertToNits(event.getThermalMax());
-
- if (mLogicalDisplay.getPrimaryDisplayDeviceLocked() != null
- && mLogicalDisplay.getPrimaryDisplayDeviceLocked()
- .getDisplayDeviceInfoLocked().type == Display.TYPE_INTERNAL) {
- FrameworkStatsLog.write(FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2,
- event.getPhysicalDisplayId().hashCode(),
- brightnessInNits,
- convertToNits(unmodifiedBrightness),
- nitsToRangeIndex(brightnessInNits),
- brightnessIsMax,
- (event.getFlags() & BrightnessEvent.FLAG_USER_SET) > 0,
- convertBrightnessReasonToStatsEnum(event.getReason().getReason()),
- convertHbmModeToStatsEnum(event.getHbmMode()),
- (modifier & BrightnessReason.MODIFIER_LOW_POWER) > 0,
- (modifier & BrightnessReason.MODIFIER_THROTTLED) > 0,
- event.isRbcEnabled(),
- event.getLux(),
- event.wasShortTermModelActive(),
- lowPowerModeFactor,
- rbcStrength,
- hbmMaxNits,
- thermalCapNits,
- event.isAutomaticBrightnessEnabled());
- }
- }
-
private void logManualBrightnessEvent(BrightnessEvent event) {
float appliedLowPowerMode = event.isLowPowerModeSet() ? event.getPowerFactor() : -1f;
int appliedRbcStrength = event.isRbcEnabled() ? event.getRbcStrength() : -1;
diff --git a/services/core/java/com/android/server/display/DisplayPowerController2.java b/services/core/java/com/android/server/display/DisplayPowerController2.java
index a92877796a8a..297a6f8a52e5 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController2.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController2.java
@@ -729,7 +729,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
final String brightnessThrottlingDataId =
mLogicalDisplay.getBrightnessThrottlingDataIdLocked();
- mHandler.post(() -> {
+ mHandler.postAtTime(() -> {
boolean changed = false;
if (mDisplayDevice != device) {
changed = true;
@@ -761,7 +761,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
if (changed) {
updatePowerState();
}
- });
+ }, mClock.uptimeMillis());
}
/**
@@ -1028,6 +1028,10 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
mBrightnessEventRingBuffer =
new RingBuffer<>(BrightnessEvent.class, RINGBUFFER_MAX);
+ if (mScreenOffBrightnessSensorController != null) {
+ mScreenOffBrightnessSensorController.stop();
+ mScreenOffBrightnessSensorController = null;
+ }
loadScreenOffBrightnessSensor();
int[] sensorValueToLux = mDisplayDeviceConfig.getScreenOffBrightnessSensorValueToLux();
if (mScreenOffBrightnessSensor != null && sensorValueToLux != null) {
@@ -1133,6 +1137,10 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
mPowerState.stop();
mPowerState = null;
}
+
+ if (mScreenOffBrightnessSensorController != null) {
+ mScreenOffBrightnessSensorController.stop();
+ }
}
private void updatePowerState() {
@@ -1148,6 +1156,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
final int previousPolicy;
boolean mustInitialize = false;
int brightnessAdjustmentFlags = 0;
+ mBrightnessReasonTemp.set(null);
mTempBrightnessEvent.reset();
SparseArray<DisplayPowerControllerInterface> displayBrightnessFollowers;
synchronized (mLock) {
@@ -1249,10 +1258,10 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
// user, or is a temporary adjustment.
boolean userInitiatedChange = (Float.isNaN(brightnessState))
&& (autoBrightnessAdjustmentChanged || userSetBrightnessChanged);
- boolean hadUserBrightnessPoint = false;
+ boolean wasShortTermModelActive = false;
// Configure auto-brightness.
if (mAutomaticBrightnessController != null) {
- hadUserBrightnessPoint = mAutomaticBrightnessController.hasUserDataPoints();
+ wasShortTermModelActive = mAutomaticBrightnessController.hasUserDataPoints();
mAutomaticBrightnessController.configure(autoBrightnessState,
mBrightnessConfiguration,
mDisplayBrightnessController.getLastUserSetScreenBrightness(),
@@ -1266,7 +1275,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
: AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED);
if (mBrightnessTracker != null) {
- mBrightnessTracker.setBrightnessConfiguration(mBrightnessConfiguration);
+ mBrightnessTracker.setShouldCollectColorSample(mBrightnessConfiguration != null
+ && mBrightnessConfiguration.shouldCollectColorSamples());
}
boolean updateScreenBrightnessSetting = false;
@@ -1536,7 +1546,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
userInitiatedChange = false;
}
notifyBrightnessTrackerChanged(brightnessState, userInitiatedChange,
- hadUserBrightnessPoint);
+ wasShortTermModelActive);
}
// We save the brightness info *after* the brightness setting has been changed and
@@ -1578,7 +1588,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
mTempBrightnessEvent.setRbcStrength(mCdsi != null
? mCdsi.getReduceBrightColorsStrength() : -1);
mTempBrightnessEvent.setPowerFactor(mPowerRequest.screenLowPowerBrightnessFactor);
- mTempBrightnessEvent.setWasShortTermModelActive(hadUserBrightnessPoint);
+ mTempBrightnessEvent.setWasShortTermModelActive(wasShortTermModelActive);
mTempBrightnessEvent.setDisplayBrightnessStrategyName(displayBrightnessState
.getDisplayBrightnessStrategyName());
// Temporary is what we use during slider interactions. We avoid logging those so that
@@ -1601,10 +1611,6 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
? BrightnessEvent.FLAG_USER_SET : 0));
Slog.i(mTag, newEvent.toString(/* includeTime= */ false));
- // Log all events which are not temporary
- if (newEvent.getReason().getReason() != BrightnessReason.REASON_TEMPORARY) {
- logBrightnessEvent(newEvent, unthrottledBrightnessState);
- }
if (userSetBrightnessChanged) {
logManualBrightnessEvent(newEvent);
}
@@ -2223,7 +2229,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
}
private void notifyBrightnessTrackerChanged(float brightness, boolean userInitiated,
- boolean hadUserDataPoint) {
+ boolean wasShortTermModelActive) {
final float brightnessInNits = convertToNits(brightness);
if (mUseAutoBrightness && brightnessInNits >= 0.0f
&& mAutomaticBrightnessController != null && mBrightnessTracker != null) {
@@ -2234,7 +2240,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
? mPowerRequest.screenLowPowerBrightnessFactor
: 1.0f;
mBrightnessTracker.notifyBrightnessChanged(brightnessInNits, userInitiated,
- powerFactor, hadUserDataPoint,
+ powerFactor, wasShortTermModelActive,
mAutomaticBrightnessController.isDefaultConfig(), mUniqueDisplayId,
mAutomaticBrightnessController.getLastSensorValues(),
mAutomaticBrightnessController.getLastSensorTimestamps());
@@ -2541,154 +2547,6 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
return mDisplayId == Display.DEFAULT_DISPLAY || mBootCompleted;
}
- // Return bucket index of range_[left]_[right] where
- // left <= nits < right
- private int nitsToRangeIndex(float nits) {
- float[] boundaries = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50, 60, 70, 80,
- 90, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1200,
- 1400, 1600, 1800, 2000, 2250, 2500, 2750, 3000};
- int[] rangeIndex = {
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_UNKNOWN,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_0_1,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_1_2,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_2_3,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_3_4,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_4_5,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_5_6,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_6_7,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_7_8,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_8_9,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_9_10,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_10_20,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_20_30,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_30_40,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_40_50,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_50_60,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_60_70,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_70_80,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_80_90,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_90_100,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_100_200,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_200_300,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_300_400,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_400_500,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_500_600,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_600_700,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_700_800,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_800_900,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_900_1000,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_1000_1200,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_1200_1400,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_1400_1600,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_1600_1800,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_1800_2000,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_2000_2250,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_2250_2500,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_2500_2750,
- FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_2750_3000,
- };
- for (int i = 0; i < boundaries.length; i++) {
- if (nits < boundaries[i]) {
- return rangeIndex[i];
- }
- }
- return FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_3000_INF;
- }
-
- private int convertBrightnessReasonToStatsEnum(int brightnessReason) {
- switch(brightnessReason) {
- case BrightnessReason.REASON_UNKNOWN:
- return FrameworkStatsLog
- .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_UNKNOWN;
- case BrightnessReason.REASON_MANUAL:
- return FrameworkStatsLog
- .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_MANUAL;
- case BrightnessReason.REASON_DOZE:
- return FrameworkStatsLog
- .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_DOZE;
- case BrightnessReason.REASON_DOZE_DEFAULT:
- return FrameworkStatsLog
- .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_DOZE_DEFAULT;
- case BrightnessReason.REASON_AUTOMATIC:
- return FrameworkStatsLog
- .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_AUTOMATIC;
- case BrightnessReason.REASON_SCREEN_OFF:
- return FrameworkStatsLog
- .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_SCREEN_OFF;
- case BrightnessReason.REASON_OVERRIDE:
- return FrameworkStatsLog
- .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_OVERRIDE;
- case BrightnessReason.REASON_TEMPORARY:
- return FrameworkStatsLog
- .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_TEMPORARY;
- case BrightnessReason.REASON_BOOST:
- return FrameworkStatsLog
- .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_BOOST;
- case BrightnessReason.REASON_SCREEN_OFF_BRIGHTNESS_SENSOR:
- return FrameworkStatsLog
- .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_SCREEN_OFF_BRIGHTNESS_SENSOR;
- case BrightnessReason.REASON_FOLLOWER:
- return FrameworkStatsLog
- .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_FOLLOWER;
- }
- return FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_UNKNOWN;
- }
-
- private int convertHbmModeToStatsEnum(int mode) {
- switch(mode) {
- case BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF:
- return FrameworkStatsLog
- .SCREEN_BRIGHTNESS_CHANGED_V2__HBM_MODE__HIGH_BRIGHTNESS_MODE_OFF;
- case BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT:
- return FrameworkStatsLog
- .SCREEN_BRIGHTNESS_CHANGED_V2__HBM_MODE__HIGH_BRIGHTNESS_MODE_SUNLIGHT;
- case BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR:
- return FrameworkStatsLog
- .SCREEN_BRIGHTNESS_CHANGED_V2__HBM_MODE__HIGH_BRIGHTNESS_MODE_HDR;
- }
- return FrameworkStatsLog
- .SCREEN_BRIGHTNESS_CHANGED_V2__HBM_MODE__HIGH_BRIGHTNESS_MODE_OFF;
- }
-
- // unmodifiedBrightness: the brightness value that has not been
- // modified by any modifiers(dimming/throttling/low-power-mode)
- private void logBrightnessEvent(BrightnessEvent event, float unmodifiedBrightness) {
- int modifier = event.getReason().getModifier();
- // It's easier to check if the brightness is at maximum level using the brightness
- // value untouched by any modifiers
- boolean brightnessIsMax = unmodifiedBrightness == event.getHbmMax();
- float brightnessInNits = convertToNits(event.getBrightness());
- float lowPowerModeFactor = event.getPowerFactor();
- int rbcStrength = event.getRbcStrength();
- float hbmMaxNits = convertToNits(event.getHbmMax());
- float thermalCapNits = convertToNits(event.getThermalMax());
-
- if (mLogicalDisplay.getPrimaryDisplayDeviceLocked() != null
- && mLogicalDisplay.getPrimaryDisplayDeviceLocked()
- .getDisplayDeviceInfoLocked().type == Display.TYPE_INTERNAL) {
- FrameworkStatsLog.write(FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2,
- event.getPhysicalDisplayId().hashCode(),
- brightnessInNits,
- convertToNits(unmodifiedBrightness),
- nitsToRangeIndex(brightnessInNits),
- brightnessIsMax,
- (event.getFlags() & BrightnessEvent.FLAG_USER_SET) > 0,
- convertBrightnessReasonToStatsEnum(event.getReason().getReason()),
- convertHbmModeToStatsEnum(event.getHbmMode()),
- (modifier & BrightnessReason.MODIFIER_LOW_POWER) > 0,
- (modifier & BrightnessReason.MODIFIER_THROTTLED) > 0,
- event.isRbcEnabled(),
- event.getLux(),
- event.wasShortTermModelActive(),
- lowPowerModeFactor,
- rbcStrength,
- hbmMaxNits,
- thermalCapNits,
- event.isAutomaticBrightnessEnabled());
- }
- }
-
private final class DisplayControllerHandler extends Handler {
DisplayControllerHandler(Looper looper) {
super(looper, null, true /*async*/);
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 8f52c97c1f87..8d0689ff8fe5 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -42,10 +42,12 @@ import android.view.DisplayShape;
import android.view.RoundedCorners;
import android.view.SurfaceControl;
+import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.display.BrightnessSynchronizer;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.LocalServices;
+import com.android.server.display.mode.DisplayModeDirector;
import com.android.server.lights.LightsManager;
import com.android.server.lights.LogicalLight;
@@ -674,14 +676,13 @@ final class LocalDisplayAdapter extends DisplayAdapter {
mInfo.flags |= DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY;
if (mIsFirstDisplay) {
- if (res.getBoolean(com.android.internal.R.bool.config_mainBuiltInDisplayIsRound)
+ if (res.getBoolean(R.bool.config_mainBuiltInDisplayIsRound)
|| (Build.IS_EMULATOR
&& SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false))) {
mInfo.flags |= DisplayDeviceInfo.FLAG_ROUND;
}
} else {
- if (!res.getBoolean(
- com.android.internal.R.bool.config_localDisplaysMirrorContent)) {
+ if (!res.getBoolean(R.bool.config_localDisplaysMirrorContent)) {
mInfo.flags |= DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY;
}
@@ -710,18 +711,23 @@ final class LocalDisplayAdapter extends DisplayAdapter {
mInfo.displayShape = DisplayShape.fromResources(
res, mInfo.uniqueId, maxWidth, maxHeight, mInfo.width, mInfo.height);
+ mInfo.name = getDisplayDeviceConfig().getName();
+
if (mStaticDisplayInfo.isInternal) {
mInfo.type = Display.TYPE_INTERNAL;
mInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL;
mInfo.flags |= DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
- mInfo.name = res.getString(
- com.android.internal.R.string.display_manager_built_in_display_name);
+ if (mInfo.name == null) {
+ mInfo.name = res.getString(R.string.display_manager_built_in_display_name);
+ }
} else {
mInfo.type = Display.TYPE_EXTERNAL;
mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL;
mInfo.flags |= DisplayDeviceInfo.FLAG_PRESENTATION;
- mInfo.name = getContext().getResources().getString(
- com.android.internal.R.string.display_manager_hdmi_display_name);
+ if (mInfo.name == null) {
+ mInfo.name = getContext().getResources().getString(
+ R.string.display_manager_hdmi_display_name);
+ }
}
mInfo.frameRateOverrides = mFrameRateOverrides;
@@ -1254,8 +1260,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
return false;
}
final Resources res = getOverlayContext().getResources();
- int[] ports = res.getIntArray(
- com.android.internal.R.array.config_localPrivateDisplayPorts);
+ int[] ports = res.getIntArray(R.array.config_localPrivateDisplayPorts);
if (ports != null) {
int port = physicalAddress.getPort();
for (int p : ports) {
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index fc90db66c1cb..dee4cdea65fe 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -33,6 +33,7 @@ import android.view.Surface;
import android.view.SurfaceControl;
import com.android.server.display.layout.Layout;
+import com.android.server.display.mode.DisplayModeDirector;
import com.android.server.wm.utils.InsetUtils;
import java.io.PrintWriter;
@@ -188,7 +189,7 @@ final class LogicalDisplay {
mTempFrameRateOverride = new SparseArray<>();
mIsEnabled = true;
mIsInTransition = false;
- mBrightnessThrottlingDataId = DisplayDeviceConfig.DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID;
+ mBrightnessThrottlingDataId = DisplayDeviceConfig.DEFAULT_ID;
}
public void setDevicePositionLocked(int position) {
@@ -343,6 +344,21 @@ final class LogicalDisplay {
mInfo.set(null);
}
}
+ /**
+ * Updates refreshRateThermalThrottling
+ *
+ * @param refreshRanges new refreshRateThermalThrottling ranges limited by layout or default
+ */
+ public void updateRefreshRateThermalThrottling(
+ @Nullable SparseArray<SurfaceControl.RefreshRateRange> refreshRanges) {
+ if (refreshRanges == null) {
+ refreshRanges = new SparseArray<>();
+ }
+ if (!mBaseDisplayInfo.refreshRateThermalThrottling.contentEquals(refreshRanges)) {
+ mBaseDisplayInfo.refreshRateThermalThrottling = refreshRanges;
+ mInfo.set(null);
+ }
+ }
/**
* Updates the state of the logical display based on the available display devices.
@@ -571,7 +587,7 @@ final class LogicalDisplay {
DisplayDevice device,
boolean isBlanked) {
// Set the layer stack.
- device.setLayerStackLocked(t, isBlanked ? BLANK_LAYER_STACK : mLayerStack);
+ device.setLayerStackLocked(t, isBlanked ? BLANK_LAYER_STACK : mLayerStack, mDisplayId);
// Also inform whether the device is the same one sent to inputflinger for its layerstack.
// Prevent displays that are disabled from receiving input.
// TODO(b/188914255): Remove once input can dispatch against device vs layerstack.
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index 2ac7d9d1a73e..e290b7a8b708 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -1013,19 +1013,23 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
if (newDisplay != oldDisplay) {
newDisplay.swapDisplaysLocked(oldDisplay);
}
+ DisplayDeviceConfig config = device.getDisplayDeviceConfig();
newDisplay.setDevicePositionLocked(displayLayout.getPosition());
newDisplay.setLeadDisplayLocked(displayLayout.getLeadDisplayId());
newDisplay.updateLayoutLimitedRefreshRateLocked(
- device.getDisplayDeviceConfig().getRefreshRange(
- displayLayout.getRefreshRateZoneId()
+ config.getRefreshRange(displayLayout.getRefreshRateZoneId())
+ );
+ newDisplay.updateRefreshRateThermalThrottling(
+ config.getRefreshRateThrottlingData(
+ displayLayout.getRefreshRateThermalThrottlingMapId()
)
);
setEnabledLocked(newDisplay, displayLayout.isEnabled());
newDisplay.setBrightnessThrottlingDataIdLocked(
displayLayout.getBrightnessThrottlingMapId() == null
- ? DisplayDeviceConfig.DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID
+ ? DisplayDeviceConfig.DEFAULT_ID
: displayLayout.getBrightnessThrottlingMapId());
newDisplay.setDisplayGroupNameLocked(displayLayout.getDisplayGroupName());
diff --git a/services/core/java/com/android/server/display/OWNERS b/services/core/java/com/android/server/display/OWNERS
index 8e3460175158..fcaa95731408 100644
--- a/services/core/java/com/android/server/display/OWNERS
+++ b/services/core/java/com/android/server/display/OWNERS
@@ -4,5 +4,7 @@ hackbod@google.com
ogunwale@google.com
santoscordon@google.com
flc@google.com
+wilczynskip@google.com
+brup@google.com
per-file ColorDisplayService.java=christyfranks@google.com
diff --git a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
index 3e67f0a466d7..2ce7690ecc3f 100644
--- a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
@@ -36,6 +36,7 @@ import android.view.SurfaceControl;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.display.mode.DisplayModeDirector;
import java.io.PrintWriter;
import java.util.ArrayList;
diff --git a/services/core/java/com/android/server/display/brightness/BrightnessEvent.java b/services/core/java/com/android/server/display/brightness/BrightnessEvent.java
index 8b09571fe920..aff80de0011d 100644
--- a/services/core/java/com/android/server/display/brightness/BrightnessEvent.java
+++ b/services/core/java/com/android/server/display/brightness/BrightnessEvent.java
@@ -100,7 +100,7 @@ public final class BrightnessEvent {
* A utility to reset the BrightnessEvent to default values
*/
public void reset() {
- mReason.set(null);
+ mReason = new BrightnessReason();
mTime = SystemClock.uptimeMillis();
mPhysicalDisplayId = "";
// Lux values
diff --git a/services/core/java/com/android/server/display/layout/Layout.java b/services/core/java/com/android/server/display/layout/Layout.java
index f1e885e982e1..6a4d23b18763 100644
--- a/services/core/java/com/android/server/display/layout/Layout.java
+++ b/services/core/java/com/android/server/display/layout/Layout.java
@@ -257,6 +257,9 @@ public class Layout {
@Nullable
private String mRefreshRateZoneId;
+ @Nullable
+ private String mRefreshRateThermalThrottlingMapId;
+
Display(@NonNull DisplayAddress address, int logicalDisplayId, boolean isEnabled,
@NonNull String displayGroupName, String brightnessThrottlingMapId, int position,
int leadDisplayId) {
@@ -286,6 +289,7 @@ public class Layout {
+ ", brightnessThrottlingMapId: " + mBrightnessThrottlingMapId
+ ", mRefreshRateZoneId: " + mRefreshRateZoneId
+ ", mLeadDisplayId: " + mLeadDisplayId
+ + ", mRefreshRateThermalThrottlingMapId: " + mRefreshRateThermalThrottlingMapId
+ "}";
}
@@ -305,7 +309,9 @@ public class Layout {
&& Objects.equals(mBrightnessThrottlingMapId,
otherDisplay.mBrightnessThrottlingMapId)
&& Objects.equals(otherDisplay.mRefreshRateZoneId, this.mRefreshRateZoneId)
- && this.mLeadDisplayId == otherDisplay.mLeadDisplayId;
+ && this.mLeadDisplayId == otherDisplay.mLeadDisplayId
+ && Objects.equals(mRefreshRateThermalThrottlingMapId,
+ otherDisplay.mRefreshRateThermalThrottlingMapId);
}
@Override
@@ -319,6 +325,7 @@ public class Layout {
result = 31 * result + mBrightnessThrottlingMapId.hashCode();
result = 31 * result + Objects.hashCode(mRefreshRateZoneId);
result = 31 * result + mLeadDisplayId;
+ result = 31 * result + Objects.hashCode(mRefreshRateThermalThrottlingMapId);
return result;
}
@@ -388,5 +395,13 @@ public class Layout {
public int getLeadDisplayId() {
return mLeadDisplayId;
}
+
+ public void setRefreshRateThermalThrottlingMapId(String refreshRateThermalThrottlingMapId) {
+ mRefreshRateThermalThrottlingMapId = refreshRateThermalThrottlingMapId;
+ }
+
+ public String getRefreshRateThermalThrottlingMapId() {
+ return mRefreshRateThermalThrottlingMapId;
+ }
}
}
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
index 31f5ab7dfe98..db6944d011c9 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.display;
+package com.android.server.display.mode;
import static android.hardware.display.DisplayManager.DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED;
import static android.hardware.display.DisplayManagerInternal.REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE;
@@ -67,6 +67,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.display.BrightnessSynchronizer;
import com.android.internal.os.BackgroundThread;
import com.android.server.LocalServices;
+import com.android.server.display.DisplayDeviceConfig;
import com.android.server.display.utils.AmbientFilter;
import com.android.server.display.utils.AmbientFilterFactory;
import com.android.server.display.utils.SensorUtils;
@@ -214,12 +215,16 @@ public class DisplayModeDirector {
mUdfpsObserver.observe();
}
+ /**
+ * Enables or disables component logging
+ */
public void setLoggingEnabled(boolean loggingEnabled) {
if (mLoggingEnabled == loggingEnabled) {
return;
}
mLoggingEnabled = loggingEnabled;
mBrightnessObserver.setLoggingEnabled(loggingEnabled);
+ mSkinThermalStatusObserver.setLoggingEnabled(loggingEnabled);
}
@NonNull
@@ -1574,7 +1579,10 @@ public class DisplayModeDirector {
}
}
- final class AppRequestObserver {
+ /**
+ * Responsible for keeping track of app requested refresh rates per display
+ */
+ public final class AppRequestObserver {
private final SparseArray<Display.Mode> mAppRequestedModeByDisplay;
private final SparseArray<RefreshRateRange> mAppPreferredRefreshRateRangeByDisplay;
@@ -1583,6 +1591,9 @@ public class DisplayModeDirector {
mAppPreferredRefreshRateRangeByDisplay = new SparseArray<>();
}
+ /**
+ * Sets refresh rates from app request
+ */
public void setAppRequest(int displayId, int modeId, float requestedMinRefreshRateRange,
float requestedMaxRefreshRateRange) {
synchronized (mLock) {
@@ -1665,7 +1676,7 @@ public class DisplayModeDirector {
return null;
}
- public void dumpLocked(PrintWriter pw) {
+ private void dumpLocked(PrintWriter pw) {
pw.println(" AppRequestObserver");
pw.println(" mAppRequestedModeByDisplay:");
for (int i = 0; i < mAppRequestedModeByDisplay.size(); i++) {
@@ -1794,7 +1805,7 @@ public class DisplayModeDirector {
*/
@VisibleForTesting
public class BrightnessObserver implements DisplayManager.DisplayListener {
- private final static int LIGHT_SENSOR_RATE_MS = 250;
+ private static final int LIGHT_SENSOR_RATE_MS = 250;
private int[] mLowDisplayBrightnessThresholds;
private int[] mLowAmbientBrightnessThresholds;
private int[] mHighDisplayBrightnessThresholds;
@@ -2019,7 +2030,7 @@ public class DisplayModeDirector {
return mLowAmbientBrightnessThresholds;
}
- public void observe(SensorManager sensorManager) {
+ private void observe(SensorManager sensorManager) {
mSensorManager = sensorManager;
mBrightness = getBrightness(Display.DEFAULT_DISPLAY);
@@ -2064,11 +2075,11 @@ public class DisplayModeDirector {
mDeviceConfigDisplaySettings.startListening();
mInjector.registerDisplayListener(this, mHandler,
- DisplayManager.EVENT_FLAG_DISPLAY_CHANGED |
- DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS);
+ DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
+ | DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS);
}
- public void setLoggingEnabled(boolean loggingEnabled) {
+ private void setLoggingEnabled(boolean loggingEnabled) {
if (mLoggingEnabled == loggingEnabled) {
return;
}
@@ -2076,7 +2087,8 @@ public class DisplayModeDirector {
mLightSensorListener.setLoggingEnabled(loggingEnabled);
}
- public void onRefreshRateSettingChangedLocked(float min, float max) {
+ @VisibleForTesting
+ void onRefreshRateSettingChangedLocked(float min, float max) {
boolean changeable = (max - min > 1f && max > 60f);
if (mRefreshRateChangeable != changeable) {
mRefreshRateChangeable = changeable;
@@ -2089,14 +2101,14 @@ public class DisplayModeDirector {
}
}
- public void onLowPowerModeEnabledLocked(boolean b) {
+ private void onLowPowerModeEnabledLocked(boolean b) {
if (mLowPowerModeEnabled != b) {
mLowPowerModeEnabled = b;
updateSensorStatus();
}
}
- public void onDeviceConfigLowBrightnessThresholdsChanged(int[] displayThresholds,
+ private void onDeviceConfigLowBrightnessThresholdsChanged(int[] displayThresholds,
int[] ambientThresholds) {
if (displayThresholds != null && ambientThresholds != null
&& displayThresholds.length == ambientThresholds.length) {
@@ -2123,7 +2135,7 @@ public class DisplayModeDirector {
}
}
- public void onDeviceConfigHighBrightnessThresholdsChanged(int[] displayThresholds,
+ private void onDeviceConfigHighBrightnessThresholdsChanged(int[] displayThresholds,
int[] ambientThresholds) {
if (displayThresholds != null && ambientThresholds != null
&& displayThresholds.length == ambientThresholds.length) {
@@ -2150,7 +2162,7 @@ public class DisplayModeDirector {
}
}
- public void dumpLocked(PrintWriter pw) {
+ void dumpLocked(PrintWriter pw) {
pw.println(" BrightnessObserver");
pw.println(" mAmbientLux: " + mAmbientLux);
pw.println(" mBrightness: " + mBrightness);
@@ -2400,7 +2412,7 @@ public class DisplayModeDirector {
}
@VisibleForTesting
- public void setDefaultDisplayState(int state) {
+ void setDefaultDisplayState(int state) {
if (mLoggingEnabled) {
Slog.d(TAG, "setDefaultDisplayState: mDefaultDisplayState = "
+ mDefaultDisplayState + ", state = " + state);
@@ -2475,7 +2487,7 @@ public class DisplayModeDirector {
}
private final class LightSensorEventListener implements SensorEventListener {
- final private static int INJECT_EVENTS_INTERVAL_MS = LIGHT_SENSOR_RATE_MS;
+ private static final int INJECT_EVENTS_INTERVAL_MS = LIGHT_SENSOR_RATE_MS;
private float mLastSensorData;
private long mTimestamp;
private boolean mLoggingEnabled;
@@ -2658,7 +2670,7 @@ public class DisplayModeDirector {
}
}
- private static final class SensorObserver implements ProximityActiveListener,
+ protected static final class SensorObserver implements ProximityActiveListener,
DisplayManager.DisplayListener {
private final String mProximitySensorName = null;
private final String mProximitySensorType = Sensor.STRING_TYPE_PROXIMITY;
@@ -2876,10 +2888,10 @@ public class DisplayModeDirector {
}
final int hbmMode = info.highBrightnessMode;
- final boolean isHbmActive = hbmMode != BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF &&
- info.adjustedBrightness > info.highBrightnessTransitionPoint;
- if (hbmMode == mHbmMode.get(displayId) &&
- isHbmActive == mHbmActive.get(displayId)) {
+ final boolean isHbmActive = hbmMode != BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF
+ && info.adjustedBrightness > info.highBrightnessTransitionPoint;
+ if (hbmMode == mHbmMode.get(displayId)
+ && isHbmActive == mHbmActive.get(displayId)) {
// no change, ignore.
return;
}
@@ -2901,7 +2913,7 @@ public class DisplayModeDirector {
Vote vote = null;
if (mHbmActive.get(displayId, false)) {
final int hbmMode =
- mHbmMode.get(displayId, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF);
+ mHbmMode.get(displayId, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF);
if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT) {
// Device resource properties take priority over DisplayDeviceConfig
if (mRefreshRateInHbmSunlight > 0) {
@@ -2909,7 +2921,7 @@ public class DisplayModeDirector {
mRefreshRateInHbmSunlight);
} else {
final List<RefreshRateLimitation> limits =
- mDisplayManagerInternal.getRefreshRateLimitations(displayId);
+ mDisplayManagerInternal.getRefreshRateLimitations(displayId);
for (int i = 0; limits != null && i < limits.size(); i++) {
final RefreshRateLimitation limitation = limits.get(i);
if (limitation.type == REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE) {
@@ -2919,8 +2931,8 @@ public class DisplayModeDirector {
}
}
}
- } else if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR &&
- mRefreshRateInHbmHdr > 0) {
+ } else if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR
+ && mRefreshRateInHbmHdr > 0) {
// HBM for HDR vote isn't supported through DisplayDeviceConfig yet, so look for
// a vote from Device properties
vote = Vote.forPhysicalRefreshRates(mRefreshRateInHbmHdr, mRefreshRateInHbmHdr);
@@ -2941,56 +2953,7 @@ public class DisplayModeDirector {
}
}
- private final class SkinThermalStatusObserver extends IThermalEventListener.Stub {
- private final BallotBox mBallotBox;
- private final Injector mInjector;
-
- private @Temperature.ThrottlingStatus int mStatus = -1;
-
- SkinThermalStatusObserver(Injector injector, BallotBox ballotBox) {
- mInjector = injector;
- mBallotBox = ballotBox;
- }
-
- @Override
- public void notifyThrottling(Temperature temp) {
- mStatus = temp.getStatus();
- if (mLoggingEnabled) {
- Slog.d(TAG, "New thermal throttling status "
- + ", current thermal status = " + mStatus);
- }
- final Vote vote;
- if (mStatus >= Temperature.THROTTLING_CRITICAL) {
- vote = Vote.forRenderFrameRates(0f, 60f);
- } else {
- vote = null;
- }
- mBallotBox.vote(GLOBAL_ID, Vote.PRIORITY_SKIN_TEMPERATURE, vote);
- }
-
- public void observe() {
- IThermalService thermalService = mInjector.getThermalService();
- if (thermalService == null) {
- Slog.w(TAG, "Could not observe thermal status. Service not available");
- return;
- }
- try {
- thermalService.registerThermalEventListenerWithType(this, Temperature.TYPE_SKIN);
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to register thermal status listener", e);
- }
- }
-
- void dumpLocked(PrintWriter writer) {
- writer.println(" SkinThermalStatusObserver:");
- writer.println(" mStatus: " + mStatus);
- }
- }
-
private class DeviceConfigDisplaySettings implements DeviceConfig.OnPropertiesChangedListener {
- public DeviceConfigDisplaySettings() {
- }
-
public void startListening() {
mDeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
BackgroundThread.getExecutor(), this);
@@ -3001,8 +2964,8 @@ public class DisplayModeDirector {
*/
public int[] getLowDisplayBrightnessThresholds() {
return getIntArrayProperty(
- DisplayManager.DeviceConfig.
- KEY_FIXED_REFRESH_RATE_LOW_DISPLAY_BRIGHTNESS_THRESHOLDS);
+ DisplayManager.DeviceConfig
+ .KEY_FIXED_REFRESH_RATE_LOW_DISPLAY_BRIGHTNESS_THRESHOLDS);
}
/*
@@ -3010,8 +2973,8 @@ public class DisplayModeDirector {
*/
public int[] getLowAmbientBrightnessThresholds() {
return getIntArrayProperty(
- DisplayManager.DeviceConfig.
- KEY_FIXED_REFRESH_RATE_LOW_AMBIENT_BRIGHTNESS_THRESHOLDS);
+ DisplayManager.DeviceConfig
+ .KEY_FIXED_REFRESH_RATE_LOW_AMBIENT_BRIGHTNESS_THRESHOLDS);
}
public int getRefreshRateInLowZone() {
@@ -3176,11 +3139,15 @@ public class DisplayModeDirector {
void registerDisplayListener(@NonNull DisplayManager.DisplayListener listener,
Handler handler, long flags);
+ Display[] getDisplays();
+
+ boolean getDisplayInfo(int displayId, DisplayInfo displayInfo);
+
BrightnessInfo getBrightnessInfo(int displayId);
boolean isDozeState(Display d);
- IThermalService getThermalService();
+ boolean registerThermalServiceListener(IThermalEventListener listener);
boolean supportsFrameRateOverride();
}
@@ -3214,6 +3181,20 @@ public class DisplayModeDirector {
}
@Override
+ public Display[] getDisplays() {
+ return getDisplayManager().getDisplays(DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED);
+ }
+
+ @Override
+ public boolean getDisplayInfo(int displayId, DisplayInfo displayInfo) {
+ Display display = getDisplayManager().getDisplay(displayId);
+ if (display != null) {
+ return display.getDisplayInfo(displayInfo);
+ }
+ return false;
+ }
+
+ @Override
public BrightnessInfo getBrightnessInfo(int displayId) {
final Display display = getDisplayManager().getDisplay(displayId);
if (display != null) {
@@ -3231,9 +3212,20 @@ public class DisplayModeDirector {
}
@Override
- public IThermalService getThermalService() {
- return IThermalService.Stub.asInterface(
- ServiceManager.getService(Context.THERMAL_SERVICE));
+ public boolean registerThermalServiceListener(IThermalEventListener listener) {
+ IThermalService thermalService = getThermalService();
+ if (thermalService == null) {
+ Slog.w(TAG, "Could not observe thermal status. Service not available");
+ return false;
+ }
+ try {
+ thermalService.registerThermalEventListenerWithType(listener,
+ Temperature.TYPE_SKIN);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to register thermal status listener", e);
+ return false;
+ }
+ return true;
}
@Override
@@ -3247,6 +3239,11 @@ public class DisplayModeDirector {
}
return mDisplayManager;
}
+
+ private IThermalService getThermalService() {
+ return IThermalService.Stub.asInterface(
+ ServiceManager.getService(Context.THERMAL_SERVICE));
+ }
}
interface BallotBox {
diff --git a/services/core/java/com/android/server/display/mode/SkinThermalStatusObserver.java b/services/core/java/com/android/server/display/mode/SkinThermalStatusObserver.java
new file mode 100644
index 000000000000..1bb34abe9025
--- /dev/null
+++ b/services/core/java/com/android/server/display/mode/SkinThermalStatusObserver.java
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display.mode;
+
+import android.annotation.Nullable;
+import android.hardware.display.DisplayManager;
+import android.os.Handler;
+import android.os.IThermalEventListener;
+import android.os.Temperature;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.view.Display;
+import android.view.DisplayInfo;
+import android.view.SurfaceControl;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BackgroundThread;
+
+import java.io.PrintWriter;
+
+final class SkinThermalStatusObserver extends IThermalEventListener.Stub implements
+ DisplayManager.DisplayListener {
+ private static final String TAG = "SkinThermalStatusObserver";
+
+ private final DisplayModeDirector.BallotBox mBallotBox;
+ private final DisplayModeDirector.Injector mInjector;
+
+ private boolean mLoggingEnabled;
+
+ private final Handler mHandler;
+ private final Object mThermalObserverLock = new Object();
+ @GuardedBy("mThermalObserverLock")
+ @Temperature.ThrottlingStatus
+ private int mStatus = -1;
+ @GuardedBy("mThermalObserverLock")
+ private final SparseArray<SparseArray<SurfaceControl.RefreshRateRange>>
+ mThermalThrottlingByDisplay = new SparseArray<>();
+
+ SkinThermalStatusObserver(DisplayModeDirector.Injector injector,
+ DisplayModeDirector.BallotBox ballotBox) {
+ this(injector, ballotBox, BackgroundThread.getHandler());
+ }
+
+ @VisibleForTesting
+ SkinThermalStatusObserver(DisplayModeDirector.Injector injector,
+ DisplayModeDirector.BallotBox ballotBox, Handler handler) {
+ mInjector = injector;
+ mBallotBox = ballotBox;
+ mHandler = handler;
+ }
+
+ void observe() {
+ // if failed to register thermal service listener, don't register display listener
+ if (!mInjector.registerThermalServiceListener(this)) {
+ return;
+ }
+
+ mInjector.registerDisplayListener(this, mHandler,
+ DisplayManager.EVENT_FLAG_DISPLAY_ADDED | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
+ | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED);
+
+ populateInitialDisplayInfo();
+ }
+
+ void setLoggingEnabled(boolean enabled) {
+ mLoggingEnabled = enabled;
+ }
+
+ @Override
+ public void notifyThrottling(Temperature temp) {
+ @Temperature.ThrottlingStatus int currentStatus = temp.getStatus();
+ synchronized (mThermalObserverLock) {
+ mStatus = currentStatus;
+ mHandler.post(this::updateVotes);
+ }
+
+ if (mLoggingEnabled) {
+ Slog.d(TAG, "New thermal throttling status " + ", current thermal status = "
+ + currentStatus);
+ }
+ }
+
+ //region DisplayManager.DisplayListener
+ @Override
+ public void onDisplayAdded(int displayId) {
+ updateRefreshRateThermalThrottling(displayId);
+ if (mLoggingEnabled) {
+ Slog.d(TAG, "Display added:" + displayId);
+ }
+ }
+
+ @Override
+ public void onDisplayRemoved(int displayId) {
+ synchronized (mThermalObserverLock) {
+ mThermalThrottlingByDisplay.remove(displayId);
+ mHandler.post(() -> mBallotBox.vote(displayId,
+ DisplayModeDirector.Vote.PRIORITY_SKIN_TEMPERATURE, null));
+ }
+ if (mLoggingEnabled) {
+ Slog.d(TAG, "Display removed and voted: displayId=" + displayId);
+ }
+ }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ updateRefreshRateThermalThrottling(displayId);
+ if (mLoggingEnabled) {
+ Slog.d(TAG, "Display changed:" + displayId);
+ }
+ }
+ //endregion
+
+ private void populateInitialDisplayInfo() {
+ DisplayInfo info = new DisplayInfo();
+ Display[] displays = mInjector.getDisplays();
+ int size = displays.length;
+ SparseArray<SparseArray<SurfaceControl.RefreshRateRange>> localMap = new SparseArray<>(
+ size);
+ for (Display d : displays) {
+ final int displayId = d.getDisplayId();
+ d.getDisplayInfo(info);
+ localMap.put(displayId, info.refreshRateThermalThrottling);
+ }
+ synchronized (mThermalObserverLock) {
+ for (int i = 0; i < size; i++) {
+ mThermalThrottlingByDisplay.put(localMap.keyAt(i), localMap.valueAt(i));
+ }
+ }
+ if (mLoggingEnabled) {
+ Slog.d(TAG, "Display initial info:" + localMap);
+ }
+ }
+
+ private void updateRefreshRateThermalThrottling(int displayId) {
+ DisplayInfo displayInfo = new DisplayInfo();
+ mInjector.getDisplayInfo(displayId, displayInfo);
+ SparseArray<SurfaceControl.RefreshRateRange> throttlingMap =
+ displayInfo.refreshRateThermalThrottling;
+
+ synchronized (mThermalObserverLock) {
+ mThermalThrottlingByDisplay.put(displayId, throttlingMap);
+ mHandler.post(() -> updateVoteForDisplay(displayId));
+ }
+ if (mLoggingEnabled) {
+ Slog.d(TAG,
+ "Thermal throttling updated: display=" + displayId + ", map=" + throttlingMap);
+ }
+ }
+
+ //region in mHandler thread
+ private void updateVotes() {
+ @Temperature.ThrottlingStatus int localStatus;
+ SparseArray<SparseArray<SurfaceControl.RefreshRateRange>> localMap;
+
+ synchronized (mThermalObserverLock) {
+ localStatus = mStatus;
+ localMap = mThermalThrottlingByDisplay.clone();
+ }
+ if (mLoggingEnabled) {
+ Slog.d(TAG, "Updating votes for status=" + localStatus + ", map=" + localMap);
+ }
+ int size = localMap.size();
+ for (int i = 0; i < size; i++) {
+ reportThrottlingIfNeeded(localMap.keyAt(i), localStatus, localMap.valueAt(i));
+ }
+ }
+
+ private void updateVoteForDisplay(int displayId) {
+ @Temperature.ThrottlingStatus int localStatus;
+ SparseArray<SurfaceControl.RefreshRateRange> localMap;
+
+ synchronized (mThermalObserverLock) {
+ localStatus = mStatus;
+ localMap = mThermalThrottlingByDisplay.get(displayId);
+ }
+ if (mLoggingEnabled) {
+ Slog.d(TAG, "Updating votes for status=" + localStatus + ", display =" + displayId
+ + ", map=" + localMap);
+ }
+ reportThrottlingIfNeeded(displayId, localStatus, localMap);
+ }
+
+ private void reportThrottlingIfNeeded(int displayId,
+ @Temperature.ThrottlingStatus int currentStatus,
+ SparseArray<SurfaceControl.RefreshRateRange> throttlingMap) {
+ if (currentStatus == -1) { // no throttling status reported from thermal sensor yet
+ return;
+ }
+
+ if (throttlingMap.size() == 0) { // map is not configured, using default behaviour
+ fallbackReportThrottlingIfNeeded(displayId, currentStatus);
+ return;
+ }
+
+ SurfaceControl.RefreshRateRange foundRange = findBestMatchingRefreshRateRange(currentStatus,
+ throttlingMap);
+ // if status <= currentStatus not found in the map reset vote
+ DisplayModeDirector.Vote vote = null;
+ if (foundRange != null) { // otherwise vote with found range
+ vote = DisplayModeDirector.Vote.forRenderFrameRates(foundRange.min, foundRange.max);
+ }
+ mBallotBox.vote(displayId, DisplayModeDirector.Vote.PRIORITY_SKIN_TEMPERATURE, vote);
+ if (mLoggingEnabled) {
+ Slog.d(TAG, "Voted: vote=" + vote + ", display =" + displayId);
+ }
+ }
+
+ @Nullable
+ private SurfaceControl.RefreshRateRange findBestMatchingRefreshRateRange(
+ @Temperature.ThrottlingStatus int currentStatus,
+ SparseArray<SurfaceControl.RefreshRateRange> throttlingMap) {
+ SurfaceControl.RefreshRateRange foundRange = null;
+ for (int status = currentStatus; status >= 0; status--) {
+ foundRange = throttlingMap.get(status);
+ if (foundRange != null) {
+ break;
+ }
+ }
+ return foundRange;
+ }
+
+ private void fallbackReportThrottlingIfNeeded(int displayId,
+ @Temperature.ThrottlingStatus int currentStatus) {
+ DisplayModeDirector.Vote vote = null;
+ if (currentStatus >= Temperature.THROTTLING_CRITICAL) {
+ vote = DisplayModeDirector.Vote.forRenderFrameRates(0f, 60f);
+ }
+ mBallotBox.vote(displayId, DisplayModeDirector.Vote.PRIORITY_SKIN_TEMPERATURE, vote);
+ if (mLoggingEnabled) {
+ Slog.d(TAG, "Voted(fallback): vote=" + vote + ", display =" + displayId);
+ }
+ }
+ //endregion
+
+ void dumpLocked(PrintWriter writer) {
+ @Temperature.ThrottlingStatus int localStatus;
+ SparseArray<SparseArray<SurfaceControl.RefreshRateRange>> localMap;
+
+ synchronized (mThermalObserverLock) {
+ localStatus = mStatus;
+ localMap = mThermalThrottlingByDisplay.clone();
+ }
+
+ writer.println(" SkinThermalStatusObserver:");
+ writer.println(" mStatus: " + localStatus);
+ writer.println(" mThermalThrottlingByDisplay: " + localMap);
+ }
+}
diff --git a/services/core/java/com/android/server/dreams/DreamController.java b/services/core/java/com/android/server/dreams/DreamController.java
index 3bc4b543750e..3e2efdd7db85 100644
--- a/services/core/java/com/android/server/dreams/DreamController.java
+++ b/services/core/java/com/android/server/dreams/DreamController.java
@@ -158,15 +158,14 @@ final class DreamController {
final DreamRecord oldDream = mCurrentDream;
mCurrentDream = new DreamRecord(token, name, isPreviewMode, canDoze, userId, wakeLock);
if (oldDream != null) {
- if (!oldDream.mWakingGently) {
- // We will stop these previous dreams once the new dream is started.
- mPreviousDreams.add(oldDream);
- } else if (Objects.equals(oldDream.mName, mCurrentDream.mName)) {
+ if (Objects.equals(oldDream.mName, mCurrentDream.mName)) {
// We are attempting to start a dream that is currently waking up gently.
// Let's silently stop the old instance here to clear the dream state.
// This should happen after the new mCurrentDream is set to avoid announcing
// a "dream stopped" state.
stopDreamInstance(/* immediately */ true, "restarting same dream", oldDream);
+ } else {
+ mPreviousDreams.add(oldDream);
}
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 3563938a9c3c..c0deb3f8274b 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -700,6 +700,7 @@ public class HdmiControlService extends SystemService {
}
if (mCecController == null) {
Slog.i(TAG, "Device does not support HDMI-CEC.");
+ return;
}
if (mMhlController == null) {
mMhlController = HdmiMhlControllerStub.create(this);
@@ -713,9 +714,6 @@ public class HdmiControlService extends SystemService {
if (mEarcController == null) {
Slog.i(TAG, "Device does not support eARC.");
}
- if (mCecController == null && mEarcController == null) {
- return;
- }
mHdmiCecNetwork = new HdmiCecNetwork(this, mCecController, mMhlController);
if (isCecControlEnabled()) {
initializeCec(INITIATED_BY_BOOT_UP);
diff --git a/services/core/java/com/android/server/health/HealthServiceWrapperAidl.java b/services/core/java/com/android/server/health/HealthServiceWrapperAidl.java
index c4113198ae1d..1153cc37e3da 100644
--- a/services/core/java/com/android/server/health/HealthServiceWrapperAidl.java
+++ b/services/core/java/com/android/server/health/HealthServiceWrapperAidl.java
@@ -18,6 +18,7 @@ package com.android.server.health;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.hardware.health.BatteryHealthData;
import android.hardware.health.HealthInfo;
import android.hardware.health.IHealth;
import android.os.BatteryManager;
@@ -113,6 +114,7 @@ class HealthServiceWrapperAidl extends HealthServiceWrapper {
private int getPropertyInternal(int id, BatteryProperty prop) throws RemoteException {
IHealth service = mLastService.get();
if (service == null) throw new RemoteException("no health service");
+ BatteryHealthData healthData;
try {
switch (id) {
case BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER:
@@ -133,6 +135,21 @@ class HealthServiceWrapperAidl extends HealthServiceWrapper {
case BatteryManager.BATTERY_PROPERTY_ENERGY_COUNTER:
prop.setLong(service.getEnergyCounterNwh());
break;
+ case BatteryManager.BATTERY_PROPERTY_MANUFACTURING_DATE:
+ healthData = service.getBatteryHealthData();
+ prop.setLong(healthData.batteryManufacturingDateSeconds);
+ break;
+ case BatteryManager.BATTERY_PROPERTY_FIRST_USAGE_DATE:
+ healthData = service.getBatteryHealthData();
+ prop.setLong(healthData.batteryFirstUsageSeconds);
+ break;
+ case BatteryManager.BATTERY_PROPERTY_CHARGING_POLICY:
+ prop.setLong(service.getChargingPolicy());
+ break;
+ case BatteryManager.BATTERY_PROPERTY_STATE_OF_HEALTH:
+ healthData = service.getBatteryHealthData();
+ prop.setLong(healthData.batteryStateOfHealth);
+ break;
}
} catch (UnsupportedOperationException e) {
// Leave prop untouched.
diff --git a/services/core/java/com/android/server/input/KeyboardLayoutManager.java b/services/core/java/com/android/server/input/KeyboardLayoutManager.java
index 9e8b9f15a7c5..e0253fc3d30c 100644
--- a/services/core/java/com/android/server/input/KeyboardLayoutManager.java
+++ b/services/core/java/com/android/server/input/KeyboardLayoutManager.java
@@ -343,9 +343,9 @@ final class KeyboardLayoutManager implements InputManager.InputDeviceListener {
private void visitAllKeyboardLayouts(KeyboardLayoutVisitor visitor) {
final PackageManager pm = mContext.getPackageManager();
Intent intent = new Intent(InputManager.ACTION_QUERY_KEYBOARD_LAYOUTS);
- for (ResolveInfo resolveInfo : pm.queryBroadcastReceivers(intent,
+ for (ResolveInfo resolveInfo : pm.queryBroadcastReceiversAsUser(intent,
PackageManager.GET_META_DATA | PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE)) {
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, UserHandle.USER_SYSTEM)) {
final ActivityInfo activityInfo = resolveInfo.activityInfo;
final int priority = resolveInfo.priority;
visitKeyboardLayoutsInPackage(pm, activityInfo, null, priority, visitor);
@@ -464,7 +464,7 @@ final class KeyboardLayoutManager implements InputManager.InputDeviceListener {
return LocaleList.forLanguageTags(languageTags.replace('|', ','));
}
- private static String getLayoutDescriptor(@NonNull InputDeviceIdentifier identifier) {
+ private String getLayoutDescriptor(@NonNull InputDeviceIdentifier identifier) {
Objects.requireNonNull(identifier, "identifier must not be null");
Objects.requireNonNull(identifier.getDescriptor(), "descriptor must not be null");
@@ -474,7 +474,21 @@ final class KeyboardLayoutManager implements InputManager.InputDeviceListener {
// If vendor id and product id is available, use it as keys. This allows us to have the
// same setup for all keyboards with same product and vendor id. i.e. User can swap 2
// identical keyboards and still get the same setup.
- return "vendor:" + identifier.getVendorId() + ",product:" + identifier.getProductId();
+ StringBuilder key = new StringBuilder();
+ key.append("vendor:").append(identifier.getVendorId()).append(",product:").append(
+ identifier.getProductId());
+
+ InputDevice inputDevice = getInputDevice(identifier);
+ Objects.requireNonNull(inputDevice, "Input device must not be null");
+ // Some keyboards can have same product ID and vendor ID but different Keyboard info like
+ // language tag and layout type.
+ if (!TextUtils.isEmpty(inputDevice.getKeyboardLanguageTag())) {
+ key.append(",languageTag:").append(inputDevice.getKeyboardLanguageTag());
+ }
+ if (!TextUtils.isEmpty(inputDevice.getKeyboardLayoutType())) {
+ key.append(",layoutType:").append(inputDevice.getKeyboardLanguageTag());
+ }
+ return key.toString();
}
@Nullable
@@ -1075,7 +1089,7 @@ final class KeyboardLayoutManager implements InputManager.InputDeviceListener {
identifier.getDescriptor()) : null;
}
- private static String createLayoutKey(InputDeviceIdentifier identifier, int userId,
+ private String createLayoutKey(InputDeviceIdentifier identifier, int userId,
@NonNull InputMethodSubtypeHandle subtypeHandle) {
Objects.requireNonNull(subtypeHandle, "subtypeHandle must not be null");
return "layoutDescriptor:" + getLayoutDescriptor(identifier) + ",userId:" + userId
diff --git a/services/core/java/com/android/server/inputmethod/HandwritingModeController.java b/services/core/java/com/android/server/inputmethod/HandwritingModeController.java
index 1c7294f8a9d5..eb4dba63dea9 100644
--- a/services/core/java/com/android/server/inputmethod/HandwritingModeController.java
+++ b/services/core/java/com/android/server/inputmethod/HandwritingModeController.java
@@ -20,12 +20,14 @@ import static android.view.InputDevice.SOURCE_STYLUS;
import android.Manifest;
import android.annotation.AnyThread;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.UiThread;
import android.hardware.input.InputManager;
import android.os.IBinder;
import android.os.Looper;
+import android.text.TextUtils;
import android.util.Slog;
import android.view.BatchedInputEventReceiver;
import android.view.Choreographer;
@@ -35,6 +37,8 @@ import android.view.InputEvent;
import android.view.InputEventReceiver;
import android.view.MotionEvent;
import android.view.SurfaceControl;
+import android.view.View;
+import android.view.inputmethod.InputMethodManager;
import com.android.server.LocalServices;
import com.android.server.input.InputManagerInternal;
@@ -52,6 +56,9 @@ final class HandwritingModeController {
// TODO(b/210039666): flip the flag.
static final boolean DEBUG = true;
private static final int EVENT_BUFFER_SIZE = 100;
+ // A longer event buffer used for handwriting delegation
+ // TODO(b/210039666): make this device touch sampling rate dependent.
+ private static final int LONG_EVENT_BUFFER = EVENT_BUFFER_SIZE * 20;
// This must be the looper for the UiThread.
private final Looper mLooper;
@@ -63,6 +70,9 @@ final class HandwritingModeController {
private Runnable mInkWindowInitRunnable;
private boolean mRecordingGesture;
private int mCurrentDisplayId;
+ // when set, package names are used for handwriting delegation.
+ private @Nullable String mDelegatePackageName;
+ private @Nullable String mDelegatorPackageName;
private HandwritingEventReceiverSurface mHandwritingSurface;
@@ -137,6 +147,41 @@ final class HandwritingModeController {
return mRecordingGesture;
}
+ boolean hasOngoingStylusHandwritingSession() {
+ return mHandwritingSurface != null && mHandwritingSurface.isIntercepting();
+ }
+
+ /**
+ * Prepare delegation of stylus handwriting to a different editor
+ * @see InputMethodManager#prepareStylusHandwritingDelegation(View, String)
+ */
+ void prepareStylusHandwritingDelegation(
+ @NonNull String delegatePackageName, @NonNull String delegatorPackageName) {
+ mDelegatePackageName = delegatePackageName;
+ mDelegatorPackageName = delegatorPackageName;
+ ((ArrayList) mHandwritingBuffer).ensureCapacity(LONG_EVENT_BUFFER);
+ // TODO(b/210039666): cancel delegation after a timeout or next input method client binding.
+ }
+
+ @Nullable String getDelegatePackageName() {
+ return mDelegatePackageName;
+ }
+
+ @Nullable String getDelegatorPackageName() {
+ return mDelegatorPackageName;
+ }
+
+ /**
+ * Clear any pending handwriting delegation info.
+ */
+ void clearPendingHandwritingDelegation() {
+ if (DEBUG) {
+ Slog.d(TAG, "clearPendingHandwritingDelegation");
+ }
+ mDelegatorPackageName = null;
+ mDelegatePackageName = null;
+ }
+
/**
* Starts a {@link HandwritingSession} to transfer to the IME.
*
@@ -223,6 +268,7 @@ final class HandwritingModeController {
}
}
+ clearPendingHandwritingDelegation();
mRecordingGesture = false;
}
@@ -259,7 +305,10 @@ final class HandwritingModeController {
mInkWindowInitRunnable = null;
}
- if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
+ // If handwriting delegation is ongoing, don't clear the buffer so that multiple strokes
+ // can be buffered across windows.
+ if (TextUtils.isEmpty(mDelegatePackageName)
+ && (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL)) {
mRecordingGesture = false;
mHandwritingBuffer.clear();
return;
diff --git a/services/core/java/com/android/server/inputmethod/ImeTrackerService.java b/services/core/java/com/android/server/inputmethod/ImeTrackerService.java
index da65f27688d8..2efb0beaa567 100644
--- a/services/core/java/com/android/server/inputmethod/ImeTrackerService.java
+++ b/services/core/java/com/android/server/inputmethod/ImeTrackerService.java
@@ -24,13 +24,14 @@ import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
+import android.util.Log;
import android.view.inputmethod.ImeTracker;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.inputmethod.IImeTracker;
import com.android.internal.inputmethod.InputMethodDebug;
import com.android.internal.inputmethod.SoftInputShowHideReason;
import com.android.internal.util.FrameworkStatsLog;
-import com.android.internal.view.IImeTracker;
import java.io.PrintWriter;
import java.time.Instant;
@@ -53,7 +54,7 @@ import java.util.concurrent.atomic.AtomicInteger;
@SuppressWarnings("GuardedBy")
public final class ImeTrackerService extends IImeTracker.Stub {
- static final String TAG = "ImeTrackerService";
+ private static final String TAG = ImeTracker.TAG;
/** The threshold in milliseconds after which a history entry is considered timed out. */
private static final long TIMEOUT_MS = 10_000;
@@ -71,67 +72,71 @@ public final class ImeTrackerService extends IImeTracker.Stub {
@NonNull
@Override
- public synchronized IBinder onRequestShow(int uid, @ImeTracker.Origin int origin,
- @SoftInputShowHideReason int reason) {
- final IBinder binder = new Binder();
- final History.Entry entry = new History.Entry(uid, ImeTracker.TYPE_SHOW,
- ImeTracker.STATUS_RUN, origin, reason);
+ public synchronized ImeTracker.Token onRequestShow(@NonNull String tag, int uid,
+ @ImeTracker.Origin int origin, @SoftInputShowHideReason int reason) {
+ final var binder = new Binder();
+ final var token = new ImeTracker.Token(binder, tag);
+ final var entry = new History.Entry(tag, uid, ImeTracker.TYPE_SHOW, ImeTracker.STATUS_RUN,
+ origin, reason);
mHistory.addEntry(binder, entry);
// Register a delayed task to handle the case where the new entry times out.
mHandler.postDelayed(() -> {
synchronized (ImeTrackerService.this) {
- mHistory.setFinished(binder, ImeTracker.STATUS_TIMEOUT, ImeTracker.PHASE_NOT_SET);
+ mHistory.setFinished(token, ImeTracker.STATUS_TIMEOUT, ImeTracker.PHASE_NOT_SET);
}
}, TIMEOUT_MS);
- return binder;
+ return token;
}
@NonNull
@Override
- public synchronized IBinder onRequestHide(int uid, @ImeTracker.Origin int origin,
- @SoftInputShowHideReason int reason) {
- final IBinder binder = new Binder();
- final History.Entry entry = new History.Entry(uid, ImeTracker.TYPE_HIDE,
- ImeTracker.STATUS_RUN, origin, reason);
+ public synchronized ImeTracker.Token onRequestHide(@NonNull String tag, int uid,
+ @ImeTracker.Origin int origin, @SoftInputShowHideReason int reason) {
+ final var binder = new Binder();
+ final var token = new ImeTracker.Token(binder, tag);
+ final var entry = new History.Entry(tag, uid, ImeTracker.TYPE_HIDE, ImeTracker.STATUS_RUN,
+ origin, reason);
mHistory.addEntry(binder, entry);
// Register a delayed task to handle the case where the new entry times out.
mHandler.postDelayed(() -> {
synchronized (ImeTrackerService.this) {
- mHistory.setFinished(binder, ImeTracker.STATUS_TIMEOUT, ImeTracker.PHASE_NOT_SET);
+ mHistory.setFinished(token, ImeTracker.STATUS_TIMEOUT, ImeTracker.PHASE_NOT_SET);
}
}, TIMEOUT_MS);
- return binder;
+ return token;
}
@Override
- public synchronized void onProgress(@NonNull IBinder statsToken, @ImeTracker.Phase int phase) {
- final History.Entry entry = mHistory.getEntry(statsToken);
+ public synchronized void onProgress(@NonNull IBinder binder, @ImeTracker.Phase int phase) {
+ final var entry = mHistory.getEntry(binder);
if (entry == null) return;
entry.mPhase = phase;
}
@Override
- public synchronized void onFailed(@NonNull IBinder statsToken, @ImeTracker.Phase int phase) {
+ public synchronized void onFailed(@NonNull ImeTracker.Token statsToken,
+ @ImeTracker.Phase int phase) {
mHistory.setFinished(statsToken, ImeTracker.STATUS_FAIL, phase);
}
@Override
- public synchronized void onCancelled(@NonNull IBinder statsToken, @ImeTracker.Phase int phase) {
+ public synchronized void onCancelled(@NonNull ImeTracker.Token statsToken,
+ @ImeTracker.Phase int phase) {
mHistory.setFinished(statsToken, ImeTracker.STATUS_CANCEL, phase);
}
@Override
- public synchronized void onShown(@NonNull IBinder statsToken) {
+ public synchronized void onShown(@NonNull ImeTracker.Token statsToken) {
mHistory.setFinished(statsToken, ImeTracker.STATUS_SUCCESS, ImeTracker.PHASE_NOT_SET);
}
@Override
- public synchronized void onHidden(@NonNull IBinder statsToken) {
+ public synchronized void onHidden(@NonNull ImeTracker.Token statsToken) {
mHistory.setFinished(statsToken, ImeTracker.STATUS_SUCCESS, ImeTracker.PHASE_NOT_SET);
}
@@ -141,9 +146,9 @@ public final class ImeTrackerService extends IImeTracker.Stub {
* @param statsToken the token corresponding to the current IME request.
* @param requestWindowName the name of the window that created the IME request.
*/
- public synchronized void onImmsUpdate(@NonNull IBinder statsToken,
+ public synchronized void onImmsUpdate(@NonNull ImeTracker.Token statsToken,
@NonNull String requestWindowName) {
- final History.Entry entry = mHistory.getEntry(statsToken);
+ final var entry = mHistory.getEntry(statsToken.getBinder());
if (entry == null) return;
entry.mRequestWindowName = requestWindowName;
@@ -181,17 +186,17 @@ public final class ImeTrackerService extends IImeTracker.Stub {
/** Latest entry sequence number. */
private static final AtomicInteger sSequenceNumber = new AtomicInteger(0);
- /** Adds a live entry. */
+ /** Adds a live entry corresponding to the given IME tracking token's binder. */
@GuardedBy("ImeTrackerService.this")
- private void addEntry(@NonNull IBinder statsToken, @NonNull Entry entry) {
- mLiveEntries.put(statsToken, entry);
+ private void addEntry(@NonNull IBinder binder, @NonNull Entry entry) {
+ mLiveEntries.put(binder, entry);
}
- /** Gets the entry corresponding to the given IME tracking token, if it exists. */
+ /** Gets the entry corresponding to the given IME tracking token's binder, if it exists. */
@Nullable
@GuardedBy("ImeTrackerService.this")
- private Entry getEntry(@NonNull IBinder statsToken) {
- return mLiveEntries.get(statsToken);
+ private Entry getEntry(@NonNull IBinder binder) {
+ return mLiveEntries.get(binder);
}
/**
@@ -204,10 +209,21 @@ public final class ImeTrackerService extends IImeTracker.Stub {
* (or {@link ImeTracker#PHASE_NOT_SET} otherwise).
*/
@GuardedBy("ImeTrackerService.this")
- private void setFinished(@NonNull IBinder statsToken, @ImeTracker.Status int status,
- @ImeTracker.Phase int phase) {
- final Entry entry = mLiveEntries.remove(statsToken);
- if (entry == null) return;
+ private void setFinished(@NonNull ImeTracker.Token statsToken,
+ @ImeTracker.Status int status, @ImeTracker.Phase int phase) {
+ final var entry = mLiveEntries.remove(statsToken.getBinder());
+ if (entry == null) {
+ // This will be unconditionally called through the postDelayed above to handle
+ // potential timeouts, and is thus intentionally dropped to avoid having to manually
+ // save and remove the registered callback. Only timeout calls are expected.
+ if (status != ImeTracker.STATUS_TIMEOUT) {
+ Log.i(TAG, statsToken.getTag()
+ + ": setFinished on previously finished token at "
+ + ImeTracker.Debug.phaseToString(phase) + " with "
+ + ImeTracker.Debug.statusToString(status));
+ }
+ return;
+ }
entry.mDuration = System.currentTimeMillis() - entry.mStartTime;
entry.mStatus = status;
@@ -216,6 +232,13 @@ public final class ImeTrackerService extends IImeTracker.Stub {
entry.mPhase = phase;
}
+ if (status == ImeTracker.STATUS_TIMEOUT) {
+ // All events other than timeouts are already logged in the client-side ImeTracker.
+ Log.i(TAG, statsToken.getTag() + ": setFinished at "
+ + ImeTracker.Debug.phaseToString(entry.mPhase) + " with "
+ + ImeTracker.Debug.statusToString(status));
+ }
+
// Remove excess entries overflowing capacity (plus one for the new entry).
while (mEntries.size() >= CAPACITY) {
mEntries.remove();
@@ -232,21 +255,22 @@ public final class ImeTrackerService extends IImeTracker.Stub {
/** Dumps the contents of the circular buffer. */
@GuardedBy("ImeTrackerService.this")
private void dump(@NonNull PrintWriter pw, @NonNull String prefix) {
- final DateTimeFormatter formatter =
- DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS", Locale.US)
- .withZone(ZoneId.systemDefault());
+ final var formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS", Locale.US)
+ .withZone(ZoneId.systemDefault());
pw.print(prefix);
- pw.println("ImeTrackerService#History.mLiveEntries:");
+ pw.println("ImeTrackerService#History.mLiveEntries: "
+ + mLiveEntries.size() + " elements");
- for (final Entry entry: mLiveEntries.values()) {
+ for (final var entry: mLiveEntries.values()) {
dumpEntry(entry, pw, prefix, formatter);
}
pw.print(prefix);
- pw.println("ImeTrackerService#History.mEntries:");
+ pw.println("ImeTrackerService#History.mEntries: "
+ + mEntries.size() + " elements");
- for (final Entry entry: mEntries) {
+ for (final var entry: mEntries) {
dumpEntry(entry, pw, prefix, formatter);
}
}
@@ -255,34 +279,22 @@ public final class ImeTrackerService extends IImeTracker.Stub {
private void dumpEntry(@NonNull Entry entry, @NonNull PrintWriter pw,
@NonNull String prefix, @NonNull DateTimeFormatter formatter) {
pw.print(prefix);
- pw.println("ImeTrackerService#History #" + entry.mSequenceNumber + ":");
-
- pw.print(prefix);
- pw.println(" startTime=" + formatter.format(Instant.ofEpochMilli(entry.mStartTime)));
-
- pw.print(prefix);
- pw.println(" duration=" + entry.mDuration + "ms");
+ pw.print(" #" + entry.mSequenceNumber);
+ pw.print(" " + ImeTracker.Debug.typeToString(entry.mType));
+ pw.print(" - " + ImeTracker.Debug.statusToString(entry.mStatus));
+ pw.print(" - " + entry.mTag);
+ pw.println(" (" + entry.mDuration + "ms):");
pw.print(prefix);
- pw.print(" type=" + ImeTracker.Debug.typeToString(entry.mType));
+ pw.print(" startTime=" + formatter.format(Instant.ofEpochMilli(entry.mStartTime)));
+ pw.println(" " + ImeTracker.Debug.originToString(entry.mOrigin));
pw.print(prefix);
- pw.print(" status=" + ImeTracker.Debug.statusToString(entry.mStatus));
+ pw.print(" reason=" + InputMethodDebug.softInputDisplayReasonToString(entry.mReason));
+ pw.println(" " + ImeTracker.Debug.phaseToString(entry.mPhase));
pw.print(prefix);
- pw.print(" origin="
- + ImeTracker.Debug.originToString(entry.mOrigin));
-
- pw.print(prefix);
- pw.print(" reason="
- + InputMethodDebug.softInputDisplayReasonToString(entry.mReason));
-
- pw.print(prefix);
- pw.print(" phase="
- + ImeTracker.Debug.phaseToString(entry.mPhase));
-
- pw.print(prefix);
- pw.print(" requestWindowName=" + entry.mRequestWindowName);
+ pw.println(" requestWindowName=" + entry.mRequestWindowName);
}
/** A history entry. */
@@ -291,6 +303,10 @@ public final class ImeTrackerService extends IImeTracker.Stub {
/** The entry's sequence number in the history. */
private final int mSequenceNumber = sSequenceNumber.getAndIncrement();
+ /** Logging tag, of the shape "component:random_hexadecimal". */
+ @NonNull
+ private final String mTag;
+
/** Uid of the client that requested the IME. */
private final int mUid;
@@ -323,13 +339,15 @@ public final class ImeTrackerService extends IImeTracker.Stub {
/**
* Name of the window that created the IME request.
*
- * Note: This is later set through {@link #onImmsUpdate(IBinder, String)}.
+ * Note: This is later set through {@link #onImmsUpdate}.
*/
@NonNull
private String mRequestWindowName = "not set";
- private Entry(int uid, @ImeTracker.Type int type, @ImeTracker.Status int status,
- @ImeTracker.Origin int origin, @SoftInputShowHideReason int reason) {
+ private Entry(@NonNull String tag, int uid, @ImeTracker.Type int type,
+ @ImeTracker.Status int status, @ImeTracker.Origin int origin,
+ @SoftInputShowHideReason int reason) {
+ mTag = tag;
mUid = uid;
mType = type;
mStatus = status;
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java
index 0ea64abbe548..8c7658e53dcd 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java
@@ -178,6 +178,14 @@ public abstract class InputMethodManagerInternal {
public abstract void unbindAccessibilityFromCurrentClient(int accessibilityConnectionId);
/**
+ * Switch the keyboard layout in response to a keyboard shortcut.
+ *
+ * @param direction {@code 1} to switch to the next subtype, {@code -1} to switch to the
+ * previous subtype.
+ */
+ public abstract void switchKeyboardLayout(int direction);
+
+ /**
* Fake implementation of {@link InputMethodManagerInternal}. All the methods do nothing.
*/
private static final InputMethodManagerInternal NOP =
@@ -256,6 +264,10 @@ public abstract class InputMethodManagerInternal {
@Override
public void maybeFinishStylusHandwriting() {
}
+
+ @Override
+ public void switchKeyboardLayout(int direction) {
+ }
};
/**
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index f5875abe17e6..91f91f86d275 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -145,6 +145,7 @@ import com.android.internal.content.PackageMonitor;
import com.android.internal.infra.AndroidFuture;
import com.android.internal.inputmethod.DirectBootAwareness;
import com.android.internal.inputmethod.IAccessibilityInputMethodSession;
+import com.android.internal.inputmethod.IImeTracker;
import com.android.internal.inputmethod.IInlineSuggestionsRequestCallback;
import com.android.internal.inputmethod.IInputContentUriToken;
import com.android.internal.inputmethod.IInputMethod;
@@ -168,7 +169,6 @@ import com.android.internal.os.TransferPipe;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.ConcurrentUtils;
import com.android.internal.util.DumpUtils;
-import com.android.internal.view.IImeTracker;
import com.android.internal.view.IInputMethodManager;
import com.android.server.AccessibilityManagerInternal;
import com.android.server.EventLogTags;
@@ -236,6 +236,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
private static final int MSG_FINISH_HANDWRITING = 1110;
private static final int MSG_REMOVE_HANDWRITING_WINDOW = 1120;
+ private static final int MSG_PREPARE_HANDWRITING_DELEGATION = 1130;
+
private static final int MSG_SET_INTERACTIVE = 3030;
private static final int MSG_HARD_KEYBOARD_SWITCH_CHANGED = 4000;
@@ -530,6 +532,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
/**
* The client that is currently bound to an input method.
*/
+ @Nullable
private ClientState mCurClient;
/**
@@ -555,11 +558,26 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
int mCurFocusedWindowSoftInputMode;
/**
- * The client by which {@link #mCurFocusedWindow} was reported.
+ * The client by which {@link #mCurFocusedWindow} was reported. This gets updated whenever an
+ * IME-focusable window gained focus (without necessarily starting an input connection),
+ * while {@link #mCurClient} only gets updated when we actually start an input connection.
+ *
+ * @see #mCurFocusedWindow
*/
+ @Nullable
ClientState mCurFocusedWindowClient;
/**
+ * The editor info by which {@link #mCurFocusedWindow} was reported. This differs from
+ * {@link #mCurEditorInfo} the same way {@link #mCurFocusedWindowClient} differs
+ * from {@link #mCurClient}.
+ *
+ * @see #mCurFocusedWindow
+ */
+ @Nullable
+ EditorInfo mCurFocusedWindowEditorInfo;
+
+ /**
* The {@link IRemoteInputConnection} last provided by the current client.
*/
IRemoteInputConnection mCurInputConnection;
@@ -578,6 +596,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
/**
* The {@link EditorInfo} last provided by the current client.
*/
+ @Nullable
EditorInfo mCurEditorInfo;
/**
@@ -1391,6 +1410,22 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
}
@Override
+ public void onPackageDataCleared(String packageName, int uid) {
+ boolean changed = false;
+ for (InputMethodInfo imi : mMethodList) {
+ if (imi.getPackageName().equals(packageName)) {
+ mAdditionalSubtypeMap.remove(imi.getId());
+ changed = true;
+ }
+ }
+ if (changed) {
+ AdditionalSubtypeUtils.save(
+ mAdditionalSubtypeMap, mMethodMap, mSettings.getCurrentUserId());
+ mChangedPackages.add(packageName);
+ }
+ }
+
+ @Override
public void onFinishPackageChanges() {
onFinishPackageChangesInternal();
clearPackageChangeState();
@@ -2060,7 +2095,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
new ArrayMap<>();
AdditionalSubtypeUtils.load(additionalSubtypeMap, userId);
queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, methodMap,
- methodList, directBootAwareness);
+ methodList, directBootAwareness, mSettings.getEnabledInputMethodNames());
settings = new InputMethodSettings(mContext, methodMap, userId, true /* copyOnWrite */);
}
// filter caller's access to input methods
@@ -2263,6 +2298,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
}
if (mCurFocusedWindowClient == cs) {
mCurFocusedWindowClient = null;
+ mCurFocusedWindowEditorInfo = null;
}
}
}
@@ -2689,6 +2725,14 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
}
@AnyThread
+ void schedulePrepareStylusHandwritingDelegation(
+ @NonNull String delegatePackageName, @NonNull String delegatorPackageName) {
+ mHandler.obtainMessage(
+ MSG_PREPARE_HANDWRITING_DELEGATION,
+ new Pair<>(delegatePackageName, delegatorPackageName)).sendToTarget();
+ }
+
+ @AnyThread
void scheduleRemoveStylusHandwritingWindow() {
mHandler.obtainMessage(MSG_REMOVE_HANDWRITING_WINDOW).sendToTarget();
}
@@ -3235,7 +3279,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
notifyInputMethodSubtypeChangedLocked(userId, info, null);
return;
}
- if (newSubtype != oldSubtype) {
+ if (!newSubtype.equals(oldSubtype)) {
setSelectedInputMethodAndSubtypeLocked(info, subtypeId, true);
IInputMethodInvoker curMethod = getCurMethodLocked();
if (curMethod != null) {
@@ -3281,6 +3325,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
if (!canInteractWithImeLocked(uid, client, "showSoftInput", statsToken)) {
ImeTracker.forLogging().onFailed(
statsToken, ImeTracker.PHASE_SERVER_CLIENT_FOCUSED);
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
return false;
}
final long ident = Binder.clearCallingIdentity();
@@ -3304,6 +3349,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
"InputMethodManagerService#startStylusHandwriting");
int uid = Binder.getCallingUid();
synchronized (ImfLock.class) {
+ mHwController.clearPendingHandwritingDelegation();
if (!canInteractWithImeLocked(uid, client, "startStylusHandwriting",
null /* statsToken */)) {
return;
@@ -3331,6 +3377,13 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
"There is no ongoing stylus gesture to start stylus handwriting.");
return;
}
+ if (mHwController.hasOngoingStylusHandwritingSession()) {
+ // prevent duplicate calls to startStylusHandwriting().
+ Slog.e(TAG,
+ "Stylus handwriting session is already ongoing."
+ + " Ignoring startStylusHandwriting().");
+ return;
+ }
if (DEBUG) Slog.v(TAG, "Client requesting Stylus Handwriting to be started");
final IInputMethodInvoker curMethod = getCurMethodLocked();
if (curMethod != null) {
@@ -3345,6 +3398,68 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
}
}
+ @Override
+ public void prepareStylusHandwritingDelegation(
+ @NonNull IInputMethodClient client,
+ @NonNull String delegatePackageName,
+ @NonNull String delegatorPackageName) {
+ if (!verifyClientAndPackageMatch(client, delegatorPackageName)) {
+ Slog.w(TAG, "prepareStylusHandwritingDelegation() fail");
+ throw new IllegalArgumentException("Delegator doesn't match Uid");
+ }
+ schedulePrepareStylusHandwritingDelegation(delegatePackageName, delegatorPackageName);
+ }
+
+ @Override
+ public boolean acceptStylusHandwritingDelegation(
+ @NonNull IInputMethodClient client,
+ @NonNull String delegatePackageName,
+ @NonNull String delegatorPackageName) {
+ if (!verifyDelegator(client, delegatePackageName, delegatorPackageName)) {
+ return false;
+ }
+
+ startStylusHandwriting(client);
+ return true;
+ }
+
+ private boolean verifyClientAndPackageMatch(
+ @NonNull IInputMethodClient client, @NonNull String packageName) {
+ ClientState cs;
+ synchronized (ImfLock.class) {
+ cs = mClients.get(client.asBinder());
+ }
+ if (cs == null) {
+ throw new IllegalArgumentException("unknown client " + client.asBinder());
+ }
+ return InputMethodUtils.checkIfPackageBelongsToUid(
+ mPackageManagerInternal, cs.mUid, packageName);
+ }
+
+ private boolean verifyDelegator(
+ @NonNull IInputMethodClient client,
+ @NonNull String delegatePackageName,
+ @NonNull String delegatorPackageName) {
+ if (!verifyClientAndPackageMatch(client, delegatePackageName)) {
+ Slog.w(TAG, "Delegate package does not belong to the same user. Ignoring"
+ + " startStylusHandwriting");
+ return false;
+ }
+ synchronized (ImfLock.class) {
+ if (!delegatorPackageName.equals(mHwController.getDelegatorPackageName())) {
+ Slog.w(TAG,
+ "Delegator package does not match. Ignoring startStylusHandwriting");
+ return false;
+ }
+ if (!delegatePackageName.equals(mHwController.getDelegatePackageName())) {
+ Slog.w(TAG,
+ "Delegate package does not match. Ignoring startStylusHandwriting");
+ return false;
+ }
+ }
+ return true;
+ }
+
@BinderThread
@Override
public void reportPerceptibleAsync(IBinder windowToken, boolean perceptible) {
@@ -3373,10 +3488,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
// Create statsToken is none exists.
if (statsToken == null) {
- // TODO(b/261565259): to avoid using null, add package name in ClientState
- final String packageName = (mCurEditorInfo != null) ? mCurEditorInfo.packageName : null;
- final int uid = mCurClient != null ? mCurClient.mUid : -1;
- statsToken = ImeTracker.forLogging().onRequestShow(packageName, uid,
+ statsToken = createStatsTokenForFocusedClient(true /* show */,
ImeTracker.ORIGIN_SERVER_START_INPUT, reason);
}
@@ -3450,17 +3562,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
int flags, ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
// Create statsToken is none exists.
if (statsToken == null) {
- // TODO(b/261565259): to avoid using null, add package name in ClientState
- final String packageName = (mCurEditorInfo != null) ? mCurEditorInfo.packageName : null;
- final int uid;
- if (mCurClient != null) {
- uid = mCurClient.mUid;
- } else if (mCurFocusedWindowClient != null) {
- uid = mCurFocusedWindowClient.mUid;
- } else {
- uid = -1;
- }
- statsToken = ImeTracker.forLogging().onRequestHide(packageName, uid,
+ statsToken = createStatsTokenForFocusedClient(false /* show */,
ImeTracker.ORIGIN_SERVER_HIDE_INPUT, reason);
}
@@ -3695,6 +3797,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
mCurFocusedWindow = windowToken;
mCurFocusedWindowSoftInputMode = softInputMode;
mCurFocusedWindowClient = cs;
+ mCurFocusedWindowEditorInfo = editorInfo;
mCurPerceptible = true;
// We want to start input before showing the IME, but after closing
@@ -3964,15 +4067,20 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
if (!calledWithValidTokenLocked(token)) {
return false;
}
- final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethodLocked(
- onlyCurrentIme, mMethodMap.get(getSelectedMethodIdLocked()), mCurrentSubtype);
- if (nextSubtype == null) {
- return false;
- }
- setInputMethodWithSubtypeIdLocked(token, nextSubtype.mImi.getId(),
- nextSubtype.mSubtypeId);
- return true;
+ return switchToNextInputMethodLocked(token, onlyCurrentIme);
+ }
+ }
+
+ @GuardedBy("ImfLock.class")
+ private boolean switchToNextInputMethodLocked(@Nullable IBinder token, boolean onlyCurrentIme) {
+ final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethodLocked(
+ onlyCurrentIme, mMethodMap.get(getSelectedMethodIdLocked()), mCurrentSubtype);
+ if (nextSubtype == null) {
+ return false;
}
+ setInputMethodWithSubtypeIdLocked(token, nextSubtype.mImi.getId(),
+ nextSubtype.mSubtypeId);
+ return true;
}
@BinderThread
@@ -4050,7 +4158,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
new ArrayMap<>();
AdditionalSubtypeUtils.load(additionalSubtypeMap, userId);
queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, methodMap,
- methodList, DirectBootAwareness.AUTO);
+ methodList, DirectBootAwareness.AUTO, mSettings.getEnabledInputMethodNames());
final InputMethodSettings settings = new InputMethodSettings(mContext, methodMap,
userId, false);
settings.setAdditionalInputMethodSubtypes(imiId, toBeAdded, additionalSubtypeMap,
@@ -4623,13 +4731,13 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
mWindowManagerInternal.onToggleImeRequested(
show, mCurFocusedWindow, requestToken, mCurTokenDisplayId);
mSoftInputShowHideHistory.addEntry(new SoftInputShowHideHistory.Entry(
- mCurFocusedWindowClient, mCurEditorInfo, info.focusedWindowName,
+ mCurFocusedWindowClient, mCurFocusedWindowEditorInfo, info.focusedWindowName,
mCurFocusedWindowSoftInputMode, reason, mInFullscreenMode,
info.requestWindowName, info.imeControlTargetName, info.imeLayerTargetName,
info.imeSurfaceParentName));
if (statsToken != null) {
- mImeTrackerService.onImmsUpdate(statsToken.mBinder, info.requestWindowName);
+ mImeTrackerService.onImmsUpdate(statsToken, info.requestWindowName);
}
}
@@ -4852,6 +4960,13 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
}
return true;
}
+ case MSG_PREPARE_HANDWRITING_DELEGATION:
+ synchronized (ImfLock.class) {
+ String delegate = (String) ((Pair) msg.obj).first;
+ String delegator = (String) ((Pair) msg.obj).second;
+ mHwController.prepareStylusHandwritingDelegation(delegate, delegator);
+ }
+ return true;
case MSG_START_HANDWRITING:
synchronized (ImfLock.class) {
IInputMethodInvoker curMethod = getCurMethodLocked();
@@ -4940,7 +5055,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
static void queryInputMethodServicesInternal(Context context,
@UserIdInt int userId, ArrayMap<String, List<InputMethodSubtype>> additionalSubtypeMap,
ArrayMap<String, InputMethodInfo> methodMap, ArrayList<InputMethodInfo> methodList,
- @DirectBootAwareness int directBootAwareness) {
+ @DirectBootAwareness int directBootAwareness, List<String> enabledInputMethodList) {
final Context userAwareContext = context.getUserId() == userId
? context
: context.createContextAsUser(UserHandle.of(userId), 0 /* flags */);
@@ -4973,6 +5088,17 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
methodList.ensureCapacity(services.size());
methodMap.ensureCapacity(services.size());
+ filterInputMethodServices(additionalSubtypeMap, methodMap, methodList,
+ enabledInputMethodList, userAwareContext, services);
+ }
+
+ static void filterInputMethodServices(
+ ArrayMap<String, List<InputMethodSubtype>> additionalSubtypeMap,
+ ArrayMap<String, InputMethodInfo> methodMap, ArrayList<InputMethodInfo> methodList,
+ List<String> enabledInputMethodList, Context userAwareContext,
+ List<ResolveInfo> services) {
+ final ArrayMap<String, Integer> imiPackageCount = new ArrayMap<>();
+
for (int i = 0; i < services.size(); ++i) {
ResolveInfo ri = services.get(i);
ServiceInfo si = ri.serviceInfo;
@@ -4992,10 +5118,21 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
if (imi.isVrOnly()) {
continue; // Skip VR-only IME, which isn't supported for now.
}
- methodList.add(imi);
- methodMap.put(imi.getId(), imi);
- if (DEBUG) {
- Slog.d(TAG, "Found an input method " + imi);
+ final String packageName = si.packageName;
+ // only include IMEs which are from the system, enabled, or below the threshold
+ if (si.applicationInfo.isSystemApp() || enabledInputMethodList.contains(imi.getId())
+ || imiPackageCount.getOrDefault(packageName, 0)
+ < InputMethodInfo.MAX_IMES_PER_PACKAGE) {
+ imiPackageCount.put(packageName,
+ 1 + imiPackageCount.getOrDefault(packageName, 0));
+
+ methodList.add(imi);
+ methodMap.put(imi.getId(), imi);
+ if (DEBUG) {
+ Slog.d(TAG, "Found an input method " + imi);
+ }
+ } else if (DEBUG) {
+ Slog.d(TAG, "Found an input method, but ignored due threshold: " + imi);
}
} catch (Exception e) {
Slog.wtf(TAG, "Unable to load input method " + imeId, e);
@@ -5017,7 +5154,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
mMyPackageMonitor.clearKnownImePackageNamesLocked();
queryInputMethodServicesInternal(mContext, mSettings.getCurrentUserId(),
- mAdditionalSubtypeMap, mMethodMap, mMethodList, DirectBootAwareness.AUTO);
+ mAdditionalSubtypeMap, mMethodMap, mMethodList, DirectBootAwareness.AUTO,
+ mSettings.getEnabledInputMethodNames());
// Construct the set of possible IME packages for onPackageChanged() to avoid false
// negatives when the package state remains to be the same but only the component state is
@@ -5076,7 +5214,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
reenableMinimumNonAuxSystemImes);
final int numImes = defaultEnabledIme.size();
for (int i = 0; i < numImes; ++i) {
- final InputMethodInfo imi = defaultEnabledIme.get(i);
+ final InputMethodInfo imi = defaultEnabledIme.get(i);
if (DEBUG) {
Slog.d(TAG, "--- enable ime = " + imi);
}
@@ -5376,7 +5514,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
new ArrayMap<>();
AdditionalSubtypeUtils.load(additionalSubtypeMap, userId);
queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap,
- methodMap, methodList, DirectBootAwareness.AUTO);
+ methodMap, methodList, DirectBootAwareness.AUTO,
+ mSettings.getEnabledInputMethodNames());
return methodMap;
}
@@ -5632,6 +5771,17 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
mHandler.removeMessages(MSG_FINISH_HANDWRITING);
mHandler.obtainMessage(MSG_FINISH_HANDWRITING).sendToTarget();
}
+
+ @Override
+ public void switchKeyboardLayout(int direction) {
+ synchronized (ImfLock.class) {
+ if (direction > 0) {
+ switchToNextInputMethodLocked(null /* token */, true /* onlyCurrentIme */);
+ } else {
+ // TODO(b/258853866): Support backwards switching.
+ }
+ }
+ }
}
@BinderThread
@@ -5664,9 +5814,11 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
// We cannot simply distinguish a bad IME that reports an arbitrary package name from
// an unfortunate IME whose internal state is already obsolete due to the asynchronous
// nature of our system. Let's compare it with our internal record.
- if (!TextUtils.equals(mCurEditorInfo.packageName, packageName)) {
+ final var curPackageName = mCurEditorInfo != null
+ ? mCurEditorInfo.packageName : null;
+ if (!TextUtils.equals(curPackageName, packageName)) {
Slog.e(TAG, "Ignoring createInputContentUriToken mCurEditorInfo.packageName="
- + mCurEditorInfo.packageName + " packageName=" + packageName);
+ + curPackageName + " packageName=" + packageName);
return null;
}
// This user ID can never bee spoofed.
@@ -6307,19 +6459,21 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
0 /* flags */, null /* resultReceiver */,
SoftInputShowHideReason.HIDE_RESET_SHELL_COMMAND);
mBindingController.unbindCurrentMethod();
- // Reset the current IME
- resetSelectedInputMethodAndSubtypeLocked(null);
- // Also reset the settings of the current IME
- mSettings.putSelectedInputMethod(null);
- // Disable all enabled IMEs.
- for (InputMethodInfo inputMethodInfo :
- mSettings.getEnabledInputMethodListLocked()) {
- setInputMethodEnabledLocked(inputMethodInfo.getId(), false);
+
+ // Enable default IMEs, disable others
+ var toDisable = mSettings.getEnabledInputMethodListLocked();
+ var defaultEnabled = InputMethodInfoUtils.getDefaultEnabledImes(
+ mContext, mMethodList);
+ toDisable.removeAll(defaultEnabled);
+ for (InputMethodInfo info : toDisable) {
+ setInputMethodEnabledLocked(info.getId(), false);
}
- // Re-enable with default enabled IMEs.
- for (InputMethodInfo imi : InputMethodInfoUtils.getDefaultEnabledImes(
- mContext, mMethodList)) {
- setInputMethodEnabledLocked(imi.getId(), true);
+ for (InputMethodInfo info : defaultEnabled) {
+ setInputMethodEnabledLocked(info.getId(), true);
+ }
+ // Choose new default IME, reset to none if no IME available.
+ if (!chooseNewDefaultIMELocked()) {
+ resetSelectedInputMethodAndSubtypeLocked(null);
}
updateInputMethodsFromSettingsLocked(true /* enabledMayChange */);
InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(
@@ -6334,7 +6488,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
new ArrayMap<>();
AdditionalSubtypeUtils.load(additionalSubtypeMap, userId);
queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap,
- methodMap, methodList, DirectBootAwareness.AUTO);
+ methodMap, methodList, DirectBootAwareness.AUTO,
+ mSettings.getEnabledInputMethodNames());
final InputMethodSettings settings = new InputMethodSettings(mContext,
methodMap, userId, false);
@@ -6427,6 +6582,30 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
return mImeTrackerService;
}
+ /**
+ * Creates an IME request tracking token for the current focused client.
+ *
+ * @param show whether this is a show or a hide request.
+ * @param origin the origin of the IME request.
+ * @param reason the reason why the IME request was created.
+ */
+ @NonNull
+ private ImeTracker.Token createStatsTokenForFocusedClient(boolean show,
+ @ImeTracker.Origin int origin, @SoftInputShowHideReason int reason) {
+ final int uid = mCurFocusedWindowClient != null
+ ? mCurFocusedWindowClient.mUid
+ : -1;
+ final var packageName = mCurFocusedWindowEditorInfo != null
+ ? mCurFocusedWindowEditorInfo.packageName
+ : "uid(" + uid + ")";
+
+ if (show) {
+ return ImeTracker.forLogging().onRequestShow(packageName, uid, origin, reason);
+ } else {
+ return ImeTracker.forLogging().onRequestHide(packageName, uid, origin, reason);
+ }
+ }
+
private static final class InputMethodPrivilegedOperationsImpl
extends IInputMethodPrivilegedOperations.Stub {
private final InputMethodManagerService mImms;
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodUtils.java b/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
index 559eb5341632..17536fcb820e 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
@@ -438,6 +438,15 @@ final class InputMethodUtils {
mSubtypeSplitter);
}
+ List<String> getEnabledInputMethodNames() {
+ List<String> result = new ArrayList<>();
+ for (Pair<String, ArrayList<String>> pair :
+ getEnabledInputMethodsAndSubtypeListLocked()) {
+ result.add(pair.first);
+ }
+ return result;
+ }
+
void appendAndPutEnabledInputMethodLocked(String id, boolean reloadInputMethodStr) {
if (reloadInputMethodStr) {
getEnabledInputMethodsStr();
diff --git a/services/core/java/com/android/server/locales/AppSupportedLocalesChangedAtomRecord.java b/services/core/java/com/android/server/locales/AppSupportedLocalesChangedAtomRecord.java
new file mode 100644
index 000000000000..de429f008fcf
--- /dev/null
+++ b/services/core/java/com/android/server/locales/AppSupportedLocalesChangedAtomRecord.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2023 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.locales;
+
+import static android.os.Process.INVALID_UID;
+
+import com.android.internal.util.FrameworkStatsLog;
+
+/**
+ * Holds data used to report the AppSupportedLocalesChanged atom.
+ */
+public final class AppSupportedLocalesChangedAtomRecord {
+ // The uid which invoked this update.
+ final int mCallingUid;
+ // The uid for which the override of app’s supported locales change is being done.
+ int mTargetUid = INVALID_UID;
+ // The total number of locales in the override LocaleConfig.
+ int mNumLocales = -1;
+ // Whether the override is removed LocaleConfig from the storage.
+ boolean mOverrideRemoved = false;
+ // Whether the new override LocaleConfig is the same as the app’s LocaleConfig.
+ boolean mSameAsResConfig = false;
+ // Whether the new override LocaleConfig is the same as the previously effective one. This means
+ // a comparison with the previous override LocaleConfig if there was one, and a comparison with
+ // the resource LocaleConfig if no override was present.
+ boolean mSameAsPrevConfig = false;
+ // Application supported locales changed status.
+ int mStatus = FrameworkStatsLog
+ .APP_SUPPORTED_LOCALES_CHANGED__STATUS__STATUS_UNSPECIFIED;
+
+ AppSupportedLocalesChangedAtomRecord(int callingUid) {
+ this.mCallingUid = callingUid;
+ }
+
+ void setTargetUid(int targetUid) {
+ this.mTargetUid = targetUid;
+ }
+
+ void setNumLocales(int numLocales) {
+ this.mNumLocales = numLocales;
+ }
+
+ void setOverrideRemoved(boolean overrideRemoved) {
+ this.mOverrideRemoved = overrideRemoved;
+ }
+
+ void setSameAsResConfig(boolean sameAsResConfig) {
+ this.mSameAsResConfig = sameAsResConfig;
+ }
+
+ void setSameAsPrevConfig(boolean sameAsPrevConfig) {
+ this.mSameAsPrevConfig = sameAsPrevConfig;
+ }
+
+ void setStatus(int status) {
+ this.mStatus = status;
+ }
+}
diff --git a/services/core/java/com/android/server/locales/LocaleManagerService.java b/services/core/java/com/android/server/locales/LocaleManagerService.java
index 99d30f54ce21..e5f589718deb 100644
--- a/services/core/java/com/android/server/locales/LocaleManagerService.java
+++ b/services/core/java/com/android/server/locales/LocaleManagerService.java
@@ -250,7 +250,7 @@ public class LocaleManagerService extends SystemService {
// set locales if the package name is owned by the app. Next, check if the caller has
// the necessary permission and set locales.
boolean isCallerOwner = isPackageOwnedByCaller(appPackageName, userId,
- atomRecordForMetrics);
+ atomRecordForMetrics, null);
if (!isCallerOwner) {
enforceChangeConfigurationPermission(atomRecordForMetrics);
}
@@ -264,7 +264,7 @@ public class LocaleManagerService extends SystemService {
Binder.restoreCallingIdentity(token);
}
} finally {
- logMetric(atomRecordForMetrics);
+ logAppLocalesMetric(atomRecordForMetrics);
}
}
@@ -355,32 +355,30 @@ public class LocaleManagerService extends SystemService {
}
/**
- * Same as {@link LocaleManagerService#isPackageOwnedByCaller(String, int,
- * AppLocaleChangedAtomRecord)}, but for methods that do not log locale atom.
- */
- private boolean isPackageOwnedByCaller(String appPackageName, int userId) {
- return isPackageOwnedByCaller(appPackageName, userId, /* atomRecordForMetrics= */null);
- }
-
- /**
* Checks if the package is owned by the calling app or not for the given user id.
*
* @throws IllegalArgumentException if package not found for given userid
*/
private boolean isPackageOwnedByCaller(String appPackageName, int userId,
- @Nullable AppLocaleChangedAtomRecord atomRecordForMetrics) {
+ @Nullable AppLocaleChangedAtomRecord atomRecordForMetrics,
+ @Nullable AppSupportedLocalesChangedAtomRecord appSupportedLocalesChangedAtomRecord) {
final int uid = getPackageUid(appPackageName, userId);
if (uid < 0) {
Slog.w(TAG, "Unknown package " + appPackageName + " for user " + userId);
if (atomRecordForMetrics != null) {
atomRecordForMetrics.setStatus(FrameworkStatsLog
.APPLICATION_LOCALES_CHANGED__STATUS__FAILURE_INVALID_TARGET_PACKAGE);
+ } else if (appSupportedLocalesChangedAtomRecord != null) {
+ appSupportedLocalesChangedAtomRecord.setStatus(FrameworkStatsLog
+ .APP_SUPPORTED_LOCALES_CHANGED__STATUS__FAILURE_INVALID_TARGET_PACKAGE);
}
throw new IllegalArgumentException("Unknown package: " + appPackageName
+ " for user " + userId);
}
if (atomRecordForMetrics != null) {
atomRecordForMetrics.setTargetUid(uid);
+ } else if (appSupportedLocalesChangedAtomRecord != null) {
+ appSupportedLocalesChangedAtomRecord.setTargetUid(uid);
}
//Once valid package found, ignore the userId part for validating package ownership
//as apps with INTERACT_ACROSS_USERS permission could be changing locale for different user.
@@ -425,7 +423,7 @@ public class LocaleManagerService extends SystemService {
// current input method, and that app is querying locales of the current foreground app. If
// neither conditions matched, check if the caller has the necessary permission and fetch
// locales.
- if (!isPackageOwnedByCaller(appPackageName, userId)
+ if (!isPackageOwnedByCaller(appPackageName, userId, null, null)
&& !isCallerInstaller(appPackageName, userId)
&& !(isCallerFromCurrentInputMethod(userId)
&& mActivityManagerInternal.isAppForeground(
@@ -550,7 +548,7 @@ public class LocaleManagerService extends SystemService {
return systemLocales;
}
- private void logMetric(@NonNull AppLocaleChangedAtomRecord atomRecordForMetrics) {
+ private void logAppLocalesMetric(@NonNull AppLocaleChangedAtomRecord atomRecordForMetrics) {
FrameworkStatsLog.write(FrameworkStatsLog.APPLICATION_LOCALES_CHANGED,
atomRecordForMetrics.mCallingUid,
atomRecordForMetrics.mTargetUid,
@@ -569,33 +567,39 @@ public class LocaleManagerService extends SystemService {
return;
}
- requireNonNull(appPackageName);
+ AppSupportedLocalesChangedAtomRecord atomRecord = new AppSupportedLocalesChangedAtomRecord(
+ Binder.getCallingUid());
+ try {
+ requireNonNull(appPackageName);
- //Allow apps with INTERACT_ACROSS_USERS permission to set locales for different user.
- userId = mActivityManagerInternal.handleIncomingUser(
- Binder.getCallingPid(), Binder.getCallingUid(), userId,
- false /* allowAll */, ActivityManagerInternal.ALLOW_NON_FULL,
- "setOverrideLocaleConfig", /* callerPackage= */ null);
+ //Allow apps with INTERACT_ACROSS_USERS permission to set locales for different user.
+ userId = mActivityManagerInternal.handleIncomingUser(
+ Binder.getCallingPid(), Binder.getCallingUid(), userId,
+ false /* allowAll */, ActivityManagerInternal.ALLOW_NON_FULL,
+ "setOverrideLocaleConfig", /* callerPackage= */ null);
- // This function handles two types of set operations:
- // 1.) A normal, an app overrides its own LocaleConfig.
- // 2.) A privileged system application or service is granted the necessary permission to
- // override a LocaleConfig of another package.
- if (!isPackageOwnedByCaller(appPackageName, userId)) {
- enforceSetAppSpecificLocaleConfigPermission();
- }
+ // This function handles two types of set operations:
+ // 1.) A normal, an app overrides its own LocaleConfig.
+ // 2.) A privileged system application or service is granted the necessary permission to
+ // override a LocaleConfig of another package.
+ if (!isPackageOwnedByCaller(appPackageName, userId, null, atomRecord)) {
+ enforceSetAppSpecificLocaleConfigPermission(atomRecord);
+ }
- final long token = Binder.clearCallingIdentity();
- try {
- setOverrideLocaleConfigUnchecked(appPackageName, userId, localeConfig);
+ final long token = Binder.clearCallingIdentity();
+ try {
+ setOverrideLocaleConfigUnchecked(appPackageName, userId, localeConfig, atomRecord);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
} finally {
- Binder.restoreCallingIdentity(token);
+ logAppSupportedLocalesChangedMetric(atomRecord);
}
-
- //TODO: Add metrics to monitor the usage by applications
}
+
private void setOverrideLocaleConfigUnchecked(@NonNull String appPackageName,
- @UserIdInt int userId, @Nullable LocaleConfig overridelocaleConfig) {
+ @UserIdInt int userId, @Nullable LocaleConfig overridelocaleConfig,
+ @NonNull AppSupportedLocalesChangedAtomRecord atomRecord) {
synchronized (mWriteLock) {
if (DEBUG) {
Slog.d(TAG,
@@ -609,8 +613,18 @@ public class LocaleManagerService extends SystemService {
Slog.d(TAG, "remove the override LocaleConfig");
file.delete();
}
+ atomRecord.setOverrideRemoved(true);
+ atomRecord.setStatus(FrameworkStatsLog
+ .APP_SUPPORTED_LOCALES_CHANGED__STATUS__SUCCESS);
return;
} else {
+ if (overridelocaleConfig.isSameLocaleConfig(
+ getOverrideLocaleConfig(appPackageName, userId))) {
+ Slog.d(TAG, "the same override, ignore it");
+ atomRecord.setSameAsPrevConfig(true);
+ return;
+ }
+
LocaleList localeList = overridelocaleConfig.getSupportedLocales();
// Normally the LocaleList object should not be null. However we reassign it as the
// empty list in case it happens.
@@ -621,6 +635,7 @@ public class LocaleManagerService extends SystemService {
Slog.d(TAG,
"setOverrideLocaleConfig, localeList: " + localeList.toLanguageTags());
}
+ atomRecord.setNumLocales(localeList.size());
// Store the override LocaleConfig to the file storage.
final AtomicFile atomicFile = new AtomicFile(file);
@@ -633,11 +648,25 @@ public class LocaleManagerService extends SystemService {
if (stream != null) {
atomicFile.failWrite(stream);
}
+ atomRecord.setStatus(FrameworkStatsLog
+ .APP_SUPPORTED_LOCALES_CHANGED__STATUS__FAILURE_WRITE_TO_STORAGE);
return;
}
atomicFile.finishWrite(stream);
// Clear per-app locales if they are not in the override LocaleConfig.
removeUnsupportedAppLocales(appPackageName, userId, overridelocaleConfig);
+ try {
+ Context appContext = mContext.createPackageContext(appPackageName, 0);
+ if (overridelocaleConfig.isSameLocaleConfig(
+ LocaleConfig.fromContextIgnoringOverride(appContext))) {
+ Slog.d(TAG, "setOverrideLocaleConfig, same as the app's LocaleConfig");
+ atomRecord.setSameAsResConfig(true);
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ Slog.e(TAG, "Unknown package name " + appPackageName);
+ }
+ atomRecord.setStatus(FrameworkStatsLog
+ .APP_SUPPORTED_LOCALES_CHANGED__STATUS__SUCCESS);
if (DEBUG) {
Slog.i(TAG, "Successfully written to " + atomicFile);
}
@@ -677,10 +706,17 @@ public class LocaleManagerService extends SystemService {
}
}
- private void enforceSetAppSpecificLocaleConfigPermission() {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.SET_APP_SPECIFIC_LOCALECONFIG,
- "setOverrideLocaleConfig");
+ private void enforceSetAppSpecificLocaleConfigPermission(
+ AppSupportedLocalesChangedAtomRecord atomRecord) {
+ try {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.SET_APP_SPECIFIC_LOCALECONFIG,
+ "setOverrideLocaleConfig");
+ } catch (SecurityException e) {
+ atomRecord.setStatus(FrameworkStatsLog
+ .APP_SUPPORTED_LOCALES_CHANGED__STATUS__FAILURE_PERMISSION_ABSENT);
+ throw e;
+ }
}
/**
@@ -796,4 +832,16 @@ public class LocaleManagerService extends SystemService {
final File dir = new File(Environment.getDataSystemDeDirectory(userId), LOCALE_CONFIGS);
return new File(dir, appPackageName + SUFFIX_FILE_NAME);
}
+
+ private void logAppSupportedLocalesChangedMetric(
+ @NonNull AppSupportedLocalesChangedAtomRecord atomRecord) {
+ FrameworkStatsLog.write(FrameworkStatsLog.APP_SUPPORTED_LOCALES_CHANGED,
+ atomRecord.mCallingUid,
+ atomRecord.mTargetUid,
+ atomRecord.mNumLocales,
+ atomRecord.mOverrideRemoved,
+ atomRecord.mSameAsResConfig,
+ atomRecord.mSameAsPrevConfig,
+ atomRecord.mStatus);
+ }
}
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubService.java b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
index 8f657756eed3..94f12dd7ff01 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubService.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
@@ -370,11 +370,6 @@ public class ContextHubService extends IContextHubService.Stub {
mLastRestartTimestampMap.put(contextHubId,
new AtomicLong(SystemClock.elapsedRealtimeNanos()));
- IContextHubClient client = mClientManager.registerClient(
- contextHubInfo, createDefaultClientCallback(contextHubId),
- /* attributionTag= */ null, mTransactionManager, mContext.getPackageName());
- defaultClientMap.put(contextHubId, client);
-
try {
mContextHubWrapper.registerCallback(contextHubId,
new ContextHubServiceCallback(contextHubId));
@@ -383,6 +378,11 @@ public class ContextHubService extends IContextHubService.Stub {
+ contextHubId + ")", e);
}
+ IContextHubClient client = mClientManager.registerClient(
+ contextHubInfo, createDefaultClientCallback(contextHubId),
+ /* attributionTag= */ null, mTransactionManager, mContext.getPackageName());
+ defaultClientMap.put(contextHubId, client);
+
// Do a query to initialize the service cache list of nanoapps
// TODO(b/194289715): Remove this when old API is deprecated
queryNanoAppsInternal(contextHubId);
@@ -1207,7 +1207,7 @@ public class ContextHubService extends IContextHubService.Stub {
pw.println("");
pw.println("=================== NANOAPPS ====================");
// Dump nanoAppHash
- mNanoAppStateManager.foreachNanoAppInstanceInfo((info) -> pw.println(info));
+ mNanoAppStateManager.foreachNanoAppInstanceInfo(pw::println);
pw.println("");
pw.println("=================== PRELOADED NANOAPPS ====================");
@@ -1255,16 +1255,17 @@ public class ContextHubService extends IContextHubService.Stub {
proto.flush();
}
- /**
- * Dumps preloaded nanoapps to the console
- */
+ /** Dumps preloaded nanoapps to the console */
private void dumpPreloadedNanoapps(PrintWriter pw) {
if (mContextHubWrapper == null) {
return;
}
long[] preloadedNanoappIds = mContextHubWrapper.getPreloadedNanoappIds();
- for (long preloadedNanoappId: preloadedNanoappIds) {
+ if (preloadedNanoappIds == null) {
+ return;
+ }
+ for (long preloadedNanoappId : preloadedNanoappIds) {
pw.print("ID: 0x");
pw.println(Long.toHexString(preloadedNanoappId));
}
diff --git a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
index ca184ee09907..1e32ad613eba 100644
--- a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
+++ b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
@@ -18,6 +18,7 @@ package com.android.server.location.contexthub;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.hardware.contexthub.HostEndpointInfo;
+import android.hardware.contexthub.NanSessionRequest;
import android.hardware.contexthub.V1_0.ContextHub;
import android.hardware.contexthub.V1_0.ContextHubMsg;
import android.hardware.contexthub.V1_0.TransactionResult;
@@ -456,8 +457,8 @@ public abstract class IContextHubWrapper {
});
}
- public void handleNanSessionRequest(boolean enable) {
- // TODO(229888878): Implement
+ public void handleNanSessionRequest(NanSessionRequest request) {
+ // TODO(271471342): Implement
}
@Override
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 4013468481ab..4f28432a20a2 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -33,7 +33,6 @@ import static android.os.UserHandle.USER_SYSTEM;
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD_OR_PIN;
-import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PIN;
import static com.android.internal.widget.LockPatternUtils.CURRENT_LSKF_BASED_PROTECTOR_ID_KEY;
import static com.android.internal.widget.LockPatternUtils.EscrowTokenStateChangeCallback;
@@ -82,7 +81,6 @@ import android.hardware.fingerprint.Fingerprint;
import android.hardware.fingerprint.FingerprintManager;
import android.net.Uri;
import android.os.Binder;
-import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -117,7 +115,6 @@ import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.EventLog;
-import android.util.Log;
import android.util.LongSparseArray;
import android.util.Slog;
import android.util.SparseArray;
@@ -201,7 +198,6 @@ public class LockSettingsService extends ILockSettings.Stub {
private static final String TAG = "LockSettingsService";
private static final String PERMISSION = ACCESS_KEYGUARD_SECURE_STORAGE;
private static final String BIOMETRIC_PERMISSION = MANAGE_BIOMETRIC;
- private static final boolean DEBUG = Build.IS_DEBUGGABLE && Log.isLoggable(TAG, Log.DEBUG);
private static final int PROFILE_KEY_IV_SIZE = 12;
private static final String SEPARATE_PROFILE_CHALLENGE_KEY = "lockscreen.profilechallenge";
@@ -381,7 +377,6 @@ public class LockSettingsService extends ILockSettings.Stub {
*/
private void tieProfileLockIfNecessary(int profileUserId,
LockscreenCredential profileUserPassword) {
- if (DEBUG) Slog.v(TAG, "Check child profile lock for user: " + profileUserId);
// Only for profiles that shares credential with parent
if (!isCredentialSharableWithParent(profileUserId)) {
return;
@@ -399,8 +394,7 @@ public class LockSettingsService extends ILockSettings.Stub {
// as its parent.
final int parentId = mUserManager.getProfileParent(profileUserId).id;
if (!isUserSecure(parentId) && !profileUserPassword.isNone()) {
- if (DEBUG) Slog.v(TAG, "Parent does not have a screen lock but profile has one");
-
+ Slogf.i(TAG, "Clearing password for profile user %d to match parent", profileUserId);
setLockCredentialInternal(LockscreenCredential.createNone(), profileUserPassword,
profileUserId, /* isLockTiedToParent= */ true);
return;
@@ -416,11 +410,10 @@ public class LockSettingsService extends ILockSettings.Stub {
Slog.e(TAG, "Failed to talk to GateKeeper service", e);
return;
}
- if (DEBUG) Slog.v(TAG, "Tie profile to parent now!");
try (LockscreenCredential unifiedProfilePassword = generateRandomProfilePassword()) {
setLockCredentialInternal(unifiedProfilePassword, profileUserPassword, profileUserId,
/* isLockTiedToParent= */ true);
- tieProfileLockToParent(profileUserId, unifiedProfilePassword);
+ tieProfileLockToParent(profileUserId, parentId, unifiedProfilePassword);
mManagedProfilePasswordCache.storePassword(profileUserId, unifiedProfilePassword);
}
}
@@ -690,8 +683,8 @@ public class LockSettingsService extends ILockSettings.Stub {
PendingIntent intent = PendingIntent.getActivity(mContext, 0, unlockIntent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
- Slog.d(TAG, TextUtils.formatSimple("showing encryption notification, user: %d; reason: %s",
- user.getIdentifier(), reason));
+ Slogf.d(TAG, "Showing encryption notification for user %d; reason: %s",
+ user.getIdentifier(), reason);
showEncryptionNotification(user, title, message, detail, intent);
}
@@ -735,7 +728,7 @@ public class LockSettingsService extends ILockSettings.Stub {
}
private void hideEncryptionNotification(UserHandle userHandle) {
- Slog.d(TAG, "hide encryption notification, user: " + userHandle.getIdentifier());
+ Slogf.d(TAG, "Hiding encryption notification for user %d", userHandle.getIdentifier());
mNotificationManager.cancelAsUser(null, SystemMessage.NOTE_FBE_ENCRYPTED_NOTIFICATION,
userHandle);
}
@@ -888,7 +881,6 @@ public class LockSettingsService extends ILockSettings.Stub {
&& !getBoolean("migrated_frp", false, 0)) {
migrateFrpCredential();
setBoolean("migrated_frp", true, 0);
- Slog.i(TAG, "Migrated migrated_frp.");
}
}
@@ -1034,7 +1026,7 @@ public class LockSettingsService extends ILockSettings.Stub {
private void enforceFrpResolved() {
final int mainUserId = mInjector.getUserManagerInternal().getMainUserId();
if (mainUserId < 0) {
- Slog.i(TAG, "No Main user on device; skip enforceFrpResolved");
+ Slog.d(TAG, "No Main user on device; skipping enforceFrpResolved");
return;
}
final ContentResolver cr = mContext.getContentResolver();
@@ -1065,18 +1057,7 @@ public class LockSettingsService extends ILockSettings.Stub {
mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsHave");
}
- private static final String[] UNPROTECTED_SETTINGS = {
- // These three LOCK_PATTERN_* settings have traditionally been readable via the public API
- // android.provider.Settings.{System,Secure}.getString() without any permission.
- Settings.Secure.LOCK_PATTERN_ENABLED,
- Settings.Secure.LOCK_PATTERN_VISIBLE,
- Settings.Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED,
- };
-
private final void checkDatabaseReadPermission(String requestedKey, int userId) {
- if (ArrayUtils.contains(UNPROTECTED_SETTINGS, requestedKey)) {
- return;
- }
if (!hasPermission(PERMISSION)) {
throw new SecurityException("uid=" + getCallingUid() + " needs permission "
+ PERMISSION + " to read " + requestedKey + " for user " + userId);
@@ -1190,9 +1171,6 @@ public class LockSettingsService extends ILockSettings.Stub {
@Override
public boolean getBoolean(String key, boolean defaultValue, int userId) {
checkDatabaseReadPermission(key, userId);
- if (Settings.Secure.LOCK_PATTERN_ENABLED.equals(key)) {
- return getCredentialTypeInternal(userId) == CREDENTIAL_TYPE_PATTERN;
- }
return mStorage.getBoolean(key, defaultValue, userId);
}
@@ -1283,7 +1261,6 @@ public class LockSettingsService extends ILockSettings.Stub {
}
private void unlockKeystore(byte[] password, int userHandle) {
- if (DEBUG) Slog.v(TAG, "Unlock keystore for user: " + userHandle);
Authorization.onLockScreenEvent(false, userHandle, password, null);
}
@@ -1293,7 +1270,7 @@ public class LockSettingsService extends ILockSettings.Stub {
NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException,
CertificateException, IOException {
- if (DEBUG) Slog.v(TAG, "Get child profile decrypted key");
+ Slogf.d(TAG, "Decrypting password for tied profile %d", userId);
byte[] storedData = mStorage.readChildProfileLock(userId);
if (storedData == null) {
throw new FileNotFoundException("Child profile lock file not found");
@@ -1342,7 +1319,6 @@ public class LockSettingsService extends ILockSettings.Stub {
* {@link com.android.server.SystemServiceManager#unlockUser} </em>
*/
private void unlockUser(@UserIdInt int userId) {
- Slogf.i(TAG, "Unlocking user %d", userId);
// TODO: make this method fully async so we can update UI with progress strings
final boolean alreadyUnlocked = mUserManager.isUserUnlockingOrUnlocked(userId);
final CountDownLatch latch = new CountDownLatch(1);
@@ -1652,7 +1628,6 @@ public class LockSettingsService extends ILockSettings.Stub {
LockscreenCredential savedCredential, int userId, boolean isLockTiedToParent) {
Objects.requireNonNull(credential);
Objects.requireNonNull(savedCredential);
- if (DEBUG) Slog.d(TAG, "setLockCredentialInternal: user=" + userId);
synchronized (mSpManager) {
if (savedCredential.isNone() && isProfileWithUnifiedLock(userId)) {
// get credential from keystore when profile has unified lock
@@ -1734,6 +1709,7 @@ public class LockSettingsService extends ILockSettings.Stub {
if (passwordHistoryLength == 0) {
passwordHistory = "";
} else {
+ Slogf.d(TAG, "Adding new password to password history for user %d", userHandle);
final byte[] hashFactor = getHashFactor(password, userHandle);
final byte[] salt = getSalt(userHandle).getBytes();
String hash = password.passwordToHistoryHash(salt, hashFactor);
@@ -1765,7 +1741,6 @@ public class LockSettingsService extends ILockSettings.Stub {
if (salt == 0) {
salt = SecureRandomUtils.randomLong();
setLong(LockPatternUtils.LOCK_PASSWORD_SALT_KEY, salt, userId);
- Slog.v(TAG, "Initialized lock password salt for user: " + userId);
}
return Long.toHexString(salt);
}
@@ -1887,34 +1862,44 @@ public class LockSettingsService extends ILockSettings.Stub {
}
@VisibleForTesting /** Note: this method is overridden in unit tests */
- protected void tieProfileLockToParent(int userId, LockscreenCredential password) {
- if (DEBUG) Slog.v(TAG, "tieProfileLockToParent for user: " + userId);
+ protected void tieProfileLockToParent(int profileUserId, int parentUserId,
+ LockscreenCredential password) {
+ Slogf.i(TAG, "Tying lock for profile user %d to parent user %d", profileUserId,
+ parentUserId);
final byte[] iv;
final byte[] ciphertext;
+ final long parentSid;
+ try {
+ parentSid = getGateKeeperService().getSecureUserId(parentUserId);
+ } catch (RemoteException e) {
+ throw new IllegalStateException("Failed to talk to GateKeeper service", e);
+ }
+
try {
KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES);
keyGenerator.init(new SecureRandom());
SecretKey secretKey = keyGenerator.generateKey();
try {
mJavaKeyStore.setEntry(
- PROFILE_KEY_NAME_ENCRYPT + userId,
+ PROFILE_KEY_NAME_ENCRYPT + profileUserId,
new java.security.KeyStore.SecretKeyEntry(secretKey),
new KeyProtection.Builder(KeyProperties.PURPOSE_ENCRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.build());
mJavaKeyStore.setEntry(
- PROFILE_KEY_NAME_DECRYPT + userId,
+ PROFILE_KEY_NAME_DECRYPT + profileUserId,
new java.security.KeyStore.SecretKeyEntry(secretKey),
new KeyProtection.Builder(KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.setUserAuthenticationRequired(true)
+ .setBoundToSpecificSecureUserId(parentSid)
.setUserAuthenticationValidityDurationSeconds(30)
.build());
// Key imported, obtain a reference to it.
SecretKey keyStoreEncryptionKey = (SecretKey) mJavaKeyStore.getKey(
- PROFILE_KEY_NAME_ENCRYPT + userId, null);
+ PROFILE_KEY_NAME_ENCRYPT + profileUserId, null);
Cipher cipher = Cipher.getInstance(
KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_GCM + "/"
+ KeyProperties.ENCRYPTION_PADDING_NONE);
@@ -1923,7 +1908,7 @@ public class LockSettingsService extends ILockSettings.Stub {
iv = cipher.getIV();
} finally {
// The original key can now be discarded.
- mJavaKeyStore.deleteEntry(PROFILE_KEY_NAME_ENCRYPT + userId);
+ mJavaKeyStore.deleteEntry(PROFILE_KEY_NAME_ENCRYPT + profileUserId);
}
} catch (UnrecoverableKeyException
| BadPaddingException | IllegalBlockSizeException | KeyStoreException
@@ -1933,7 +1918,7 @@ public class LockSettingsService extends ILockSettings.Stub {
if (iv.length != PROFILE_KEY_IV_SIZE) {
throw new IllegalArgumentException("Invalid iv length: " + iv.length);
}
- mStorage.writeChildProfileLock(userId, ArrayUtils.concat(iv, ciphertext));
+ mStorage.writeChildProfileLock(profileUserId, ArrayUtils.concat(iv, ciphertext));
}
private void setUserKeyProtection(@UserIdInt int userId, byte[] secret) {
@@ -2007,7 +1992,7 @@ public class LockSettingsService extends ILockSettings.Stub {
@Override
public void resetKeyStore(int userId) {
checkWritePermission();
- if (DEBUG) Slog.v(TAG, "Reset keystore for user: " + userId);
+ Slogf.d(TAG, "Resetting keystore for user %d", userId);
List<Integer> profileUserIds = new ArrayList<>();
List<LockscreenCredential> profileUserDecryptedPasswords = new ArrayList<>();
final List<UserInfo> profiles = mUserManager.getProfiles(userId);
@@ -2044,8 +2029,7 @@ public class LockSettingsService extends ILockSettings.Stub {
int piUserId = profileUserIds.get(i);
LockscreenCredential piUserDecryptedPassword = profileUserDecryptedPasswords.get(i);
if (piUserId != -1 && piUserDecryptedPassword != null) {
- if (DEBUG) Slog.v(TAG, "Restore tied profile lock");
- tieProfileLockToParent(piUserId, piUserDecryptedPassword);
+ tieProfileLockToParent(piUserId, userId, piUserDecryptedPassword);
}
if (piUserDecryptedPassword != null) {
piUserDecryptedPassword.zeroize();
@@ -2137,7 +2121,7 @@ public class LockSettingsService extends ILockSettings.Stub {
Slog.e(TAG, "FRP credential can only be verified prior to provisioning.");
return VerifyCredentialResponse.ERROR;
}
- Slog.d(TAG, "doVerifyCredential: user=" + userId);
+ Slogf.i(TAG, "Verifying lockscreen credential for user %d", userId);
final AuthenticationResult authResult;
VerifyCredentialResponse response;
@@ -2171,6 +2155,7 @@ public class LockSettingsService extends ILockSettings.Stub {
}
}
if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
+ Slogf.i(TAG, "Successfully verified lockscreen credential for user %d", userId);
onCredentialVerified(authResult.syntheticPassword,
PasswordMetrics.computeForCredential(credential), userId);
if ((flags & VERIFY_FLAG_REQUEST_GK_PW_HANDLE) != 0) {
@@ -2329,13 +2314,18 @@ public class LockSettingsService extends ILockSettings.Stub {
}
private void removeKeystoreProfileKey(int targetUserId) {
- Slog.i(TAG, "Remove keystore profile key for user: " + targetUserId);
+ final String encryptAlias = PROFILE_KEY_NAME_ENCRYPT + targetUserId;
+ final String decryptAlias = PROFILE_KEY_NAME_DECRYPT + targetUserId;
try {
- mJavaKeyStore.deleteEntry(PROFILE_KEY_NAME_ENCRYPT + targetUserId);
- mJavaKeyStore.deleteEntry(PROFILE_KEY_NAME_DECRYPT + targetUserId);
+ if (mJavaKeyStore.containsAlias(encryptAlias) ||
+ mJavaKeyStore.containsAlias(decryptAlias)) {
+ Slogf.i(TAG, "Removing keystore profile key for user %d", targetUserId);
+ mJavaKeyStore.deleteEntry(encryptAlias);
+ mJavaKeyStore.deleteEntry(decryptAlias);
+ }
} catch (KeyStoreException e) {
- // We have tried our best to remove all keys
- Slog.e(TAG, "Unable to remove keystore profile key for user:" + targetUserId, e);
+ // We have tried our best to remove the key.
+ Slogf.e(TAG, e, "Error removing keystore profile key for user %d", targetUserId);
}
}
@@ -2683,7 +2673,7 @@ public class LockSettingsService extends ILockSettings.Stub {
@VisibleForTesting
SyntheticPassword initializeSyntheticPassword(int userId) {
synchronized (mSpManager) {
- Slog.i(TAG, "Initialize SyntheticPassword for user: " + userId);
+ Slogf.i(TAG, "Initializing synthetic password for user %d", userId);
Preconditions.checkState(getCurrentLskfBasedProtectorId(userId) ==
SyntheticPasswordManager.NULL_PROTECTOR_ID,
"Cannot reinitialize SP");
@@ -2694,6 +2684,7 @@ public class LockSettingsService extends ILockSettings.Stub {
setCurrentLskfBasedProtectorId(protectorId, userId);
setUserKeyProtection(userId, sp.deriveFileBasedEncryptionKey());
onSyntheticPasswordCreated(userId, sp);
+ Slogf.i(TAG, "Successfully initialized synthetic password for user %d", userId);
return sp;
}
}
@@ -2730,8 +2721,11 @@ public class LockSettingsService extends ILockSettings.Stub {
final long finalHandle = handle;
mHandler.postDelayed(() -> {
synchronized (mGatekeeperPasswords) {
- Slog.d(TAG, "Removing handle: " + finalHandle);
- mGatekeeperPasswords.remove(finalHandle);
+ if (mGatekeeperPasswords.get(finalHandle) != null) {
+ Slogf.d(TAG, "Cached Gatekeeper password with handle %016x has expired",
+ finalHandle);
+ mGatekeeperPasswords.remove(finalHandle);
+ }
}
}, GK_PW_HANDLE_STORE_DURATION_MS);
@@ -2780,7 +2774,8 @@ public class LockSettingsService extends ILockSettings.Stub {
@GuardedBy("mSpManager")
private long setLockCredentialWithSpLocked(LockscreenCredential credential,
SyntheticPassword sp, int userId) {
- if (DEBUG) Slog.d(TAG, "setLockCredentialWithSpLocked: user=" + userId);
+ Slogf.i(TAG, "Changing lockscreen credential of user %d; newCredentialType=%s\n",
+ userId, LockPatternUtils.credentialTypeToString(credential.getType()));
final int savedCredentialType = getCredentialTypeInternal(userId);
final long oldProtectorId = getCurrentLskfBasedProtectorId(userId);
final long newProtectorId = mSpManager.createLskfBasedProtector(getGateKeeperService(),
@@ -2825,6 +2820,7 @@ public class LockSettingsService extends ILockSettings.Stub {
}
}
mSpManager.destroyLskfBasedProtector(oldProtectorId, userId);
+ Slogf.i(TAG, "Successfully changed lockscreen credential of user %d", userId);
return newProtectorId;
}
@@ -2909,6 +2905,7 @@ public class LockSettingsService extends ILockSettings.Stub {
public byte[] getHashFactor(LockscreenCredential currentCredential, int userId) {
checkPasswordReadPermission();
try {
+ Slogf.d(TAG, "Getting password history hash factor for user %d", userId);
if (isProfileWithUnifiedLock(userId)) {
try {
currentCredential = getDecryptedPasswordForTiedProfile(userId);
@@ -2934,7 +2931,7 @@ public class LockSettingsService extends ILockSettings.Stub {
private long addEscrowToken(@NonNull byte[] token, @TokenType int type, int userId,
@NonNull EscrowTokenStateChangeCallback callback) {
- if (DEBUG) Slog.d(TAG, "addEscrowToken: user=" + userId + ", type=" + type);
+ Slogf.i(TAG, "Adding escrow token for user %d", userId);
synchronized (mSpManager) {
// If the user has no LSKF, then the token can be activated immediately. Otherwise, the
// token can't be activated until the SP is unlocked by another protector (normally the
@@ -2952,18 +2949,20 @@ public class LockSettingsService extends ILockSettings.Stub {
long handle = mSpManager.addPendingToken(token, type, userId, callback);
if (sp != null) {
// Activate the token immediately
+ Slogf.i(TAG, "Immediately activating escrow token %016x", handle);
mSpManager.createTokenBasedProtector(handle, sp, userId);
+ } else {
+ Slogf.i(TAG, "Escrow token %016x will be activated when user is unlocked", handle);
}
return handle;
}
}
private void activateEscrowTokens(SyntheticPassword sp, int userId) {
- if (DEBUG) Slog.d(TAG, "activateEscrowTokens: user=" + userId);
synchronized (mSpManager) {
disableEscrowTokenOnNonManagedDevicesIfNeeded(userId);
for (long handle : mSpManager.getPendingTokensForUser(userId)) {
- Slog.i(TAG, TextUtils.formatSimple("activateEscrowTokens: %x %d ", handle, userId));
+ Slogf.i(TAG, "Activating escrow token %016x for user %d", handle, userId);
mSpManager.createTokenBasedProtector(handle, sp, userId);
}
}
@@ -3034,6 +3033,8 @@ public class LockSettingsService extends ILockSettings.Stub {
@GuardedBy("mSpManager")
private boolean setLockCredentialWithTokenInternalLocked(LockscreenCredential credential,
long tokenHandle, byte[] token, int userId) {
+ Slogf.i(TAG, "Resetting lockscreen credential of user %d using escrow token %016x",
+ userId, tokenHandle);
final AuthenticationResult result;
result = mSpManager.unlockTokenBasedProtector(getGateKeeperService(), tokenHandle, token,
userId);
@@ -3056,8 +3057,9 @@ public class LockSettingsService extends ILockSettings.Stub {
private boolean unlockUserWithToken(long tokenHandle, byte[] token, int userId) {
AuthenticationResult authResult;
synchronized (mSpManager) {
+ Slogf.i(TAG, "Unlocking user %d using escrow token %016x", userId, tokenHandle);
if (!mSpManager.hasEscrowData(userId)) {
- Slog.w(TAG, "Escrow token is disabled on the current user");
+ Slogf.w(TAG, "Escrow token support is disabled on user %d", userId);
return false;
}
authResult = mSpManager.unlockTokenBasedProtector(getGateKeeperService(), tokenHandle,
@@ -3068,6 +3070,7 @@ public class LockSettingsService extends ILockSettings.Stub {
}
}
+ Slogf.i(TAG, "Unlocked synthetic password for user %d using escrow token", userId);
onCredentialVerified(authResult.syntheticPassword,
loadPasswordMetrics(authResult.syntheticPassword, userId), userId);
return true;
@@ -3095,21 +3098,6 @@ public class LockSettingsService extends ILockSettings.Stub {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(timestamp));
}
- private static String credentialTypeToString(int credentialType) {
- switch (credentialType) {
- case CREDENTIAL_TYPE_NONE:
- return "None";
- case CREDENTIAL_TYPE_PATTERN:
- return "Pattern";
- case CREDENTIAL_TYPE_PIN:
- return "Pin";
- case CREDENTIAL_TYPE_PASSWORD:
- return "Password";
- default:
- return "Unknown " + credentialType;
- }
- }
-
@Override
protected void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, TAG, printWriter)) return;
@@ -3126,22 +3114,23 @@ public class LockSettingsService extends ILockSettings.Stub {
pw.println("User " + userId);
pw.increaseIndent();
synchronized (mSpManager) {
- pw.println(TextUtils.formatSimple("LSKF-based SP protector ID: %x",
+ pw.println(TextUtils.formatSimple("LSKF-based SP protector ID: %016x",
getCurrentLskfBasedProtectorId(userId)));
- pw.println(TextUtils.formatSimple("LSKF last changed: %s (previous protector: %x)",
- timestampToString(getLong(LSKF_LAST_CHANGED_TIME_KEY, 0, userId)),
- getLong(PREV_LSKF_BASED_PROTECTOR_ID_KEY, 0, userId)));
+ pw.println(TextUtils.formatSimple(
+ "LSKF last changed: %s (previous protector: %016x)",
+ timestampToString(getLong(LSKF_LAST_CHANGED_TIME_KEY, 0, userId)),
+ getLong(PREV_LSKF_BASED_PROTECTOR_ID_KEY, 0, userId)));
}
try {
- pw.println(TextUtils.formatSimple("SID: %x",
+ pw.println(TextUtils.formatSimple("SID: %016x",
getGateKeeperService().getSecureUserId(userId)));
} catch (RemoteException e) {
// ignore.
}
- // It's OK to dump the password type since anyone with physical access can just
+ // It's OK to dump the credential type since anyone with physical access can just
// observe it from the keyguard directly.
pw.println("Quality: " + getKeyguardStoredQuality(userId));
- pw.println("CredentialType: " + credentialTypeToString(
+ pw.println("CredentialType: " + LockPatternUtils.credentialTypeToString(
getCredentialTypeInternal(userId)));
pw.println("SeparateChallenge: " + getSeparateProfileChallengeEnabledInternal(userId));
pw.println(TextUtils.formatSimple("Metrics: %s",
@@ -3199,6 +3188,11 @@ public class LockSettingsService extends ILockSettings.Stub {
* if we are running an automotive build.
*/
private void disableEscrowTokenOnNonManagedDevicesIfNeeded(int userId) {
+
+ if (!mSpManager.hasAnyEscrowData(userId)) {
+ return;
+ }
+
// TODO(b/258213147): Remove
final long identity = Binder.clearCallingIdentity();
try {
@@ -3243,7 +3237,7 @@ public class LockSettingsService extends ILockSettings.Stub {
}
// Disable escrow token permanently on all other device/user types.
- Slog.i(TAG, "Disabling escrow token on user " + userId);
+ Slogf.i(TAG, "Permanently disabling support for escrow tokens on user %d", userId);
mSpManager.destroyEscrowData(userId);
}
@@ -3475,6 +3469,7 @@ public class LockSettingsService extends ILockSettings.Stub {
synchronized (mSpManager) {
mSpManager.verifyChallenge(getGateKeeperService(), sp, 0L, userId);
}
+ Slogf.i(TAG, "Restored synthetic password for user %d using reboot escrow", userId);
onCredentialVerified(sp, loadPasswordMetrics(sp, userId), userId);
}
}
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
index dee26e382cec..1663b019d769 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
@@ -744,6 +744,11 @@ class SyntheticPasswordManager {
&& hasState(SP_P1_NAME, NULL_PROTECTOR_ID, userId);
}
+ public boolean hasAnyEscrowData(int userId) {
+ return hasState(SP_E0_NAME, NULL_PROTECTOR_ID, userId)
+ || hasState(SP_P1_NAME, NULL_PROTECTOR_ID, userId);
+ }
+
public void destroyEscrowData(int userId) {
destroyState(SP_E0_NAME, NULL_PROTECTOR_ID, userId);
destroyState(SP_P1_NAME, NULL_PROTECTOR_ID, userId);
@@ -780,13 +785,17 @@ class SyntheticPasswordManager {
int slot = loadWeaverSlot(protectorId, userId);
destroyState(WEAVER_SLOT_NAME, protectorId, userId);
if (slot != INVALID_WEAVER_SLOT) {
+ if (!isWeaverAvailable()) {
+ Slog.e(TAG, "Cannot erase Weaver slot because Weaver is unavailable");
+ return;
+ }
Set<Integer> usedSlots = getUsedWeaverSlots();
if (!usedSlots.contains(slot)) {
- Slog.i(TAG, "Destroy weaver slot " + slot + " for user " + userId);
+ Slogf.i(TAG, "Erasing Weaver slot %d", slot);
weaverEnroll(slot, null, null);
mPasswordSlotManager.markSlotDeleted(slot);
} else {
- Slog.w(TAG, "Skip destroying reused weaver slot " + slot + " for user " + userId);
+ Slogf.i(TAG, "Weaver slot %d was already reused; not erasing it", slot);
}
}
}
@@ -854,11 +863,13 @@ class SyntheticPasswordManager {
long sid = GateKeeper.INVALID_SECURE_USER_ID;
final byte[] protectorSecret;
+ Slogf.i(TAG, "Creating LSKF-based protector %016x for user %d", protectorId, userId);
+
if (isWeaverAvailable()) {
// Weaver is available, so make the protector use it to verify the LSKF. Do this even
// if the LSKF is empty, as that gives us support for securely deleting the protector.
int weaverSlot = getNextAvailableWeaverSlot();
- Slog.i(TAG, "Weaver enroll password to slot " + weaverSlot + " for user " + userId);
+ Slogf.i(TAG, "Enrolling LSKF for user %d into Weaver slot %d", userId, weaverSlot);
byte[] weaverSecret = weaverEnroll(weaverSlot, stretchedLskfToWeaverKey(stretchedLskf),
null);
if (weaverSecret == null) {
@@ -888,6 +899,7 @@ class SyntheticPasswordManager {
} catch (RemoteException ignore) {
Slog.w(TAG, "Failed to clear SID from gatekeeper");
}
+ Slogf.i(TAG, "Enrolling LSKF for user %d into Gatekeeper", userId);
GateKeeperResponse response;
try {
response = gatekeeper.enroll(fakeUserId(userId), null, null,
@@ -960,6 +972,7 @@ class SyntheticPasswordManager {
&& LockPatternUtils.userOwnsFrpCredential(mContext, userInfo)
&& getCredentialType(protectorId, userInfo.id) !=
LockPatternUtils.CREDENTIAL_TYPE_NONE) {
+ Slog.i(TAG, "Migrating FRP credential to persistent data block");
PasswordData pwd = PasswordData.fromBytes(loadState(PASSWORD_DATA_NAME, protectorId,
userInfo.id));
int weaverSlot = loadWeaverSlot(protectorId, userInfo.id);
@@ -1088,9 +1101,10 @@ class SyntheticPasswordManager {
Slog.w(TAG, "User is not escrowable");
return false;
}
+ Slogf.i(TAG, "Creating token-based protector %016x for user %d", tokenHandle, userId);
if (isWeaverAvailable()) {
int slot = getNextAvailableWeaverSlot();
- Slog.i(TAG, "Weaver enroll token to slot " + slot + " for user " + userId);
+ Slogf.i(TAG, "Using Weaver slot %d for new token-based protector", slot);
if (weaverEnroll(slot, null, tokenData.weaverSecret) == null) {
Slog.e(TAG, "Failed to enroll weaver secret when activating token");
return false;
@@ -1166,8 +1180,9 @@ class SyntheticPasswordManager {
storedType = pwd.credentialType;
}
if (!credential.checkAgainstStoredType(storedType)) {
- Slog.e(TAG, TextUtils.formatSimple("Credential type mismatch: expected %d actual %d",
- storedType, credential.getType()));
+ Slogf.e(TAG, "Credential type mismatch: stored type is %s but provided type is %s",
+ LockPatternUtils.credentialTypeToString(storedType),
+ LockPatternUtils.credentialTypeToString(credential.getType()));
result.gkResponse = VerifyCredentialResponse.ERROR;
return result;
}
@@ -1245,8 +1260,13 @@ class SyntheticPasswordManager {
}
sid = sidFromPasswordHandle(pwd.passwordHandle);
}
- protectorSecret = transformUnderSecdiscardable(stretchedLskf,
- loadSecdiscardable(protectorId, userId));
+ byte[] secdiscardable = loadSecdiscardable(protectorId, userId);
+ if (secdiscardable == null) {
+ Slog.e(TAG, "secdiscardable file not found");
+ result.gkResponse = VerifyCredentialResponse.ERROR;
+ return result;
+ }
+ protectorSecret = transformUnderSecdiscardable(stretchedLskf, secdiscardable);
}
// Supplied credential passes first stage weaver/gatekeeper check so it should be correct.
// Notify the callback so the keyguard UI can proceed immediately.
@@ -1311,6 +1331,11 @@ class SyntheticPasswordManager {
byte[] token, int userId) {
AuthenticationResult result = new AuthenticationResult();
byte[] secdiscardable = loadSecdiscardable(protectorId, userId);
+ if (secdiscardable == null) {
+ Slog.e(TAG, "secdiscardable file not found");
+ result.gkResponse = VerifyCredentialResponse.ERROR;
+ return result;
+ }
int slotId = loadWeaverSlot(protectorId, userId);
if (slotId != INVALID_WEAVER_SLOT) {
if (!isWeaverAvailable()) {
@@ -1459,6 +1484,7 @@ class SyntheticPasswordManager {
/** Destroy a token-based SP protector. */
public void destroyTokenBasedProtector(long protectorId, int userId) {
+ Slogf.i(TAG, "Destroying token-based protector %016x for user %d", protectorId, userId);
SyntheticPasswordBlob blob = SyntheticPasswordBlob.fromBytes(loadState(SP_BLOB_NAME,
protectorId, userId));
destroyProtectorCommon(protectorId, userId);
@@ -1484,6 +1510,7 @@ class SyntheticPasswordManager {
* Destroy an LSKF-based SP protector. This is used when the user's LSKF is changed.
*/
public void destroyLskfBasedProtector(long protectorId, int userId) {
+ Slogf.i(TAG, "Destroying LSKF-based protector %016x for user %d", protectorId, userId);
destroyProtectorCommon(protectorId, userId);
destroyState(PASSWORD_DATA_NAME, protectorId, userId);
destroyState(PASSWORD_METRICS_NAME, protectorId, userId);
@@ -1644,6 +1671,9 @@ class SyntheticPasswordManager {
}
private String getProtectorKeyAlias(long protectorId) {
+ // Note, this arguably has a bug: %x should be %016x so that the protector ID is left-padded
+ // with zeroes, like how the synthetic password state files are named. It's too late to fix
+ // this, though, and it doesn't actually matter.
return TextUtils.formatSimple("%s%x", PROTECTOR_KEY_ALIAS_PREFIX, protectorId);
}
diff --git a/services/core/java/com/android/server/media/AudioPoliciesBluetoothRouteController.java b/services/core/java/com/android/server/media/AudioPoliciesBluetoothRouteController.java
new file mode 100644
index 000000000000..eb997badca52
--- /dev/null
+++ b/services/core/java/com/android/server/media/AudioPoliciesBluetoothRouteController.java
@@ -0,0 +1,482 @@
+/*
+ * Copyright (C) 2023 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.media;
+
+import static android.bluetooth.BluetoothAdapter.ACTIVE_DEVICE_AUDIO;
+import static android.bluetooth.BluetoothAdapter.STATE_CONNECTED;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothLeAudio;
+import android.bluetooth.BluetoothProfile;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.media.AudioManager;
+import android.media.AudioSystem;
+import android.media.MediaRoute2Info;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.util.Slog;
+import android.util.SparseBooleanArray;
+import android.util.SparseIntArray;
+
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Controls bluetooth routes and provides selected route override.
+ *
+ * <p>The controller offers similar functionality to {@link LegacyBluetoothRouteController} but does
+ * not support routes selection logic. Instead, relies on external clients to make a decision
+ * about currently selected route.
+ *
+ * <p>Selected route override should be used by {@link AudioManager} which is aware of Audio
+ * Policies.
+ */
+/* package */ class AudioPoliciesBluetoothRouteController
+ implements BluetoothRouteController {
+ private static final String TAG = "APBtRouteController";
+
+ private static final String HEARING_AID_ROUTE_ID_PREFIX = "HEARING_AID_";
+ private static final String LE_AUDIO_ROUTE_ID_PREFIX = "LE_AUDIO_";
+
+ @NonNull
+ private final AdapterStateChangedReceiver mAdapterStateChangedReceiver =
+ new AdapterStateChangedReceiver();
+
+ @NonNull
+ private final DeviceStateChangedReceiver mDeviceStateChangedReceiver =
+ new DeviceStateChangedReceiver();
+
+ @NonNull
+ private final Map<String, BluetoothRouteInfo> mBluetoothRoutes = new HashMap<>();
+
+ @NonNull
+ private final SparseIntArray mVolumeMap = new SparseIntArray();
+
+ @NonNull
+ private final Context mContext;
+ @NonNull
+ private final BluetoothAdapter mBluetoothAdapter;
+ @NonNull
+ private final BluetoothRouteController.BluetoothRoutesUpdatedListener mListener;
+ @NonNull
+ private final BluetoothProfileMonitor mBluetoothProfileMonitor;
+ @NonNull
+ private final AudioManager mAudioManager;
+
+ @Nullable
+ private BluetoothRouteInfo mSelectedBluetoothRoute;
+
+ AudioPoliciesBluetoothRouteController(@NonNull Context context,
+ @NonNull BluetoothAdapter bluetoothAdapter,
+ @NonNull BluetoothRouteController.BluetoothRoutesUpdatedListener listener) {
+ this(context, bluetoothAdapter,
+ new BluetoothProfileMonitor(context, bluetoothAdapter), listener);
+ }
+
+ @VisibleForTesting
+ AudioPoliciesBluetoothRouteController(@NonNull Context context,
+ @NonNull BluetoothAdapter bluetoothAdapter,
+ @NonNull BluetoothProfileMonitor bluetoothProfileMonitor,
+ @NonNull BluetoothRouteController.BluetoothRoutesUpdatedListener listener) {
+ Objects.requireNonNull(context);
+ Objects.requireNonNull(bluetoothAdapter);
+ Objects.requireNonNull(bluetoothProfileMonitor);
+ Objects.requireNonNull(listener);
+
+ mContext = context;
+ mBluetoothAdapter = bluetoothAdapter;
+ mBluetoothProfileMonitor = bluetoothProfileMonitor;
+ mAudioManager = mContext.getSystemService(AudioManager.class);
+ mListener = listener;
+
+ updateBluetoothRoutes();
+ }
+
+ @Override
+ public void start(UserHandle user) {
+ mBluetoothProfileMonitor.start();
+
+ IntentFilter adapterStateChangedIntentFilter = new IntentFilter();
+
+ adapterStateChangedIntentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
+ mContext.registerReceiverAsUser(mAdapterStateChangedReceiver, user,
+ adapterStateChangedIntentFilter, null, null);
+
+ IntentFilter deviceStateChangedIntentFilter = new IntentFilter();
+
+ deviceStateChangedIntentFilter.addAction(BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED);
+ deviceStateChangedIntentFilter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
+ deviceStateChangedIntentFilter.addAction(BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED);
+ deviceStateChangedIntentFilter.addAction(
+ BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
+ deviceStateChangedIntentFilter.addAction(
+ BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED);
+ deviceStateChangedIntentFilter.addAction(
+ BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED);
+
+ mContext.registerReceiverAsUser(mDeviceStateChangedReceiver, user,
+ deviceStateChangedIntentFilter, null, null);
+ }
+
+ @Override
+ public void stop() {
+ mContext.unregisterReceiver(mAdapterStateChangedReceiver);
+ mContext.unregisterReceiver(mDeviceStateChangedReceiver);
+ }
+
+ @Override
+ public boolean selectRoute(@Nullable String deviceAddress) {
+ synchronized (this) {
+ // Fetch all available devices in order to avoid race conditions with Bluetooth stack.
+ updateBluetoothRoutes();
+
+ if (deviceAddress == null) {
+ mSelectedBluetoothRoute = null;
+ return true;
+ }
+
+ BluetoothRouteInfo bluetoothRouteInfo = mBluetoothRoutes.get(deviceAddress);
+
+ if (bluetoothRouteInfo == null) {
+ Slog.w(TAG, "Cannot find bluetooth route for " + deviceAddress);
+ return false;
+ }
+
+ mSelectedBluetoothRoute = bluetoothRouteInfo;
+ setRouteConnectionState(mSelectedBluetoothRoute, STATE_CONNECTED);
+
+ updateConnectivityStateForDevicesInTheSameGroup();
+
+ return true;
+ }
+ }
+
+ /**
+ * Updates connectivity state for devices in the same devices group.
+ *
+ * <p>{@link BluetoothProfile#LE_AUDIO} and {@link BluetoothProfile#HEARING_AID} support
+ * grouping devices. Devices that belong to the same group should have the same routeId but
+ * different physical address.
+ *
+ * <p>In case one of the devices from the group is selected then other devices should also
+ * reflect this by changing their connectivity status to
+ * {@link MediaRoute2Info#CONNECTION_STATE_CONNECTED}.
+ */
+ private void updateConnectivityStateForDevicesInTheSameGroup() {
+ synchronized (this) {
+ for (BluetoothRouteInfo btRoute : mBluetoothRoutes.values()) {
+ if (TextUtils.equals(btRoute.mRoute.getId(), mSelectedBluetoothRoute.mRoute.getId())
+ && !TextUtils.equals(btRoute.mBtDevice.getAddress(),
+ mSelectedBluetoothRoute.mBtDevice.getAddress())) {
+ setRouteConnectionState(btRoute, STATE_CONNECTED);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void transferTo(@Nullable String routeId) {
+ if (routeId == null) {
+ mBluetoothAdapter.removeActiveDevice(ACTIVE_DEVICE_AUDIO);
+ return;
+ }
+
+ BluetoothRouteInfo btRouteInfo = findBluetoothRouteWithRouteId(routeId);
+
+ if (btRouteInfo == null) {
+ Slog.w(TAG, "transferTo: Unknown route. ID=" + routeId);
+ return;
+ }
+
+ mBluetoothAdapter.setActiveDevice(btRouteInfo.mBtDevice, ACTIVE_DEVICE_AUDIO);
+ }
+
+ @Nullable
+ private BluetoothRouteInfo findBluetoothRouteWithRouteId(@Nullable String routeId) {
+ if (routeId == null) {
+ return null;
+ }
+ synchronized (this) {
+ for (BluetoothRouteInfo btRouteInfo : mBluetoothRoutes.values()) {
+ if (TextUtils.equals(btRouteInfo.mRoute.getId(), routeId)) {
+ return btRouteInfo;
+ }
+ }
+ }
+ return null;
+ }
+
+ private void updateBluetoothRoutes() {
+ Set<BluetoothDevice> bondedDevices = mBluetoothAdapter.getBondedDevices();
+
+ if (bondedDevices == null) {
+ return;
+ }
+
+ synchronized (this) {
+ mBluetoothRoutes.clear();
+
+ // We need to query all available to BT stack devices in order to avoid inconsistency
+ // between external services, like, AndroidManager, and BT stack.
+ for (BluetoothDevice device : bondedDevices) {
+ if (isDeviceConnected(device)) {
+ BluetoothRouteInfo newBtRoute = createBluetoothRoute(device);
+ if (newBtRoute.mConnectedProfiles.size() > 0) {
+ mBluetoothRoutes.put(device.getAddress(), newBtRoute);
+ }
+ }
+ }
+ }
+ }
+
+ @VisibleForTesting
+ /* package */ boolean isDeviceConnected(@NonNull BluetoothDevice device) {
+ return device.isConnected();
+ }
+
+ @Nullable
+ @Override
+ public MediaRoute2Info getSelectedRoute() {
+ synchronized (this) {
+ if (mSelectedBluetoothRoute == null) {
+ return null;
+ }
+
+ return mSelectedBluetoothRoute.mRoute;
+ }
+ }
+
+ @NonNull
+ @Override
+ public List<MediaRoute2Info> getTransferableRoutes() {
+ List<MediaRoute2Info> routes = getAllBluetoothRoutes();
+ synchronized (this) {
+ if (mSelectedBluetoothRoute != null) {
+ routes.remove(mSelectedBluetoothRoute.mRoute);
+ }
+ }
+ return routes;
+ }
+
+ @NonNull
+ @Override
+ public List<MediaRoute2Info> getAllBluetoothRoutes() {
+ List<MediaRoute2Info> routes = new ArrayList<>();
+ List<String> routeIds = new ArrayList<>();
+
+ MediaRoute2Info selectedRoute = getSelectedRoute();
+ if (selectedRoute != null) {
+ routes.add(selectedRoute);
+ routeIds.add(selectedRoute.getId());
+ }
+
+ synchronized (this) {
+ for (BluetoothRouteInfo btRoute : mBluetoothRoutes.values()) {
+ // A pair of hearing aid devices or having the same hardware address
+ if (routeIds.contains(btRoute.mRoute.getId())) {
+ continue;
+ }
+ routes.add(btRoute.mRoute);
+ routeIds.add(btRoute.mRoute.getId());
+ }
+ }
+ return routes;
+ }
+
+ @Override
+ public boolean updateVolumeForDevices(int devices, int volume) {
+ int routeType;
+ if ((devices & (AudioSystem.DEVICE_OUT_HEARING_AID)) != 0) {
+ routeType = MediaRoute2Info.TYPE_HEARING_AID;
+ } else if ((devices & (AudioManager.DEVICE_OUT_BLUETOOTH_A2DP
+ | AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES
+ | AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)) != 0) {
+ routeType = MediaRoute2Info.TYPE_BLUETOOTH_A2DP;
+ } else if ((devices & (AudioManager.DEVICE_OUT_BLE_HEADSET)) != 0) {
+ routeType = MediaRoute2Info.TYPE_BLE_HEADSET;
+ } else {
+ return false;
+ }
+
+ synchronized (this) {
+ mVolumeMap.put(routeType, volume);
+ if (mSelectedBluetoothRoute == null
+ || mSelectedBluetoothRoute.mRoute.getType() != routeType) {
+ return false;
+ }
+
+ mSelectedBluetoothRoute.mRoute =
+ new MediaRoute2Info.Builder(mSelectedBluetoothRoute.mRoute)
+ .setVolume(volume)
+ .build();
+ }
+
+ notifyBluetoothRoutesUpdated();
+ return true;
+ }
+
+ private void notifyBluetoothRoutesUpdated() {
+ mListener.onBluetoothRoutesUpdated(getAllBluetoothRoutes());
+ }
+
+ private BluetoothRouteInfo createBluetoothRoute(BluetoothDevice device) {
+ BluetoothRouteInfo
+ newBtRoute = new BluetoothRouteInfo();
+ newBtRoute.mBtDevice = device;
+
+ String routeId = device.getAddress();
+ String deviceName = device.getName();
+ if (TextUtils.isEmpty(deviceName)) {
+ deviceName = mContext.getResources().getText(R.string.unknownName).toString();
+ }
+ int type = MediaRoute2Info.TYPE_BLUETOOTH_A2DP;
+ newBtRoute.mConnectedProfiles = new SparseBooleanArray();
+ if (mBluetoothProfileMonitor.isProfileSupported(BluetoothProfile.A2DP, device)) {
+ newBtRoute.mConnectedProfiles.put(BluetoothProfile.A2DP, true);
+ }
+ if (mBluetoothProfileMonitor.isProfileSupported(BluetoothProfile.HEARING_AID, device)) {
+ newBtRoute.mConnectedProfiles.put(BluetoothProfile.HEARING_AID, true);
+ // Intentionally assign the same ID for a pair of devices to publish only one of them.
+ routeId = HEARING_AID_ROUTE_ID_PREFIX
+ + mBluetoothProfileMonitor.getGroupId(BluetoothProfile.HEARING_AID, device);
+ type = MediaRoute2Info.TYPE_HEARING_AID;
+ }
+ if (mBluetoothProfileMonitor.isProfileSupported(BluetoothProfile.LE_AUDIO, device)) {
+ newBtRoute.mConnectedProfiles.put(BluetoothProfile.LE_AUDIO, true);
+ routeId = LE_AUDIO_ROUTE_ID_PREFIX
+ + mBluetoothProfileMonitor.getGroupId(BluetoothProfile.LE_AUDIO, device);
+ type = MediaRoute2Info.TYPE_BLE_HEADSET;
+ }
+
+ // Current volume will be set when connected.
+ newBtRoute.mRoute = new MediaRoute2Info.Builder(routeId, deviceName)
+ .addFeature(MediaRoute2Info.FEATURE_LIVE_AUDIO)
+ .addFeature(MediaRoute2Info.FEATURE_LOCAL_PLAYBACK)
+ .setConnectionState(MediaRoute2Info.CONNECTION_STATE_DISCONNECTED)
+ .setDescription(mContext.getResources().getText(
+ R.string.bluetooth_a2dp_audio_route_name).toString())
+ .setType(type)
+ .setVolumeHandling(MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
+ .setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
+ .setAddress(device.getAddress())
+ .build();
+ return newBtRoute;
+ }
+
+ private void setRouteConnectionState(@NonNull BluetoothRouteInfo btRoute,
+ @MediaRoute2Info.ConnectionState int state) {
+ if (btRoute == null) {
+ Slog.w(TAG, "setRouteConnectionState: route shouldn't be null");
+ return;
+ }
+ if (btRoute.mRoute.getConnectionState() == state) {
+ return;
+ }
+
+ MediaRoute2Info.Builder builder = new MediaRoute2Info.Builder(btRoute.mRoute)
+ .setConnectionState(state);
+ builder.setType(btRoute.getRouteType());
+
+
+
+ if (state == MediaRoute2Info.CONNECTION_STATE_CONNECTED) {
+ int currentVolume;
+ synchronized (this) {
+ currentVolume = mVolumeMap.get(btRoute.getRouteType(), 0);
+ }
+ builder.setVolume(currentVolume);
+ }
+
+ btRoute.mRoute = builder.build();
+ }
+
+ private static class BluetoothRouteInfo {
+ private BluetoothDevice mBtDevice;
+ private MediaRoute2Info mRoute;
+ private SparseBooleanArray mConnectedProfiles;
+
+ @MediaRoute2Info.Type
+ int getRouteType() {
+ // Let hearing aid profile have a priority.
+ if (mConnectedProfiles.get(BluetoothProfile.HEARING_AID, false)) {
+ return MediaRoute2Info.TYPE_HEARING_AID;
+ }
+
+ if (mConnectedProfiles.get(BluetoothProfile.LE_AUDIO, false)) {
+ return MediaRoute2Info.TYPE_BLE_HEADSET;
+ }
+
+ return MediaRoute2Info.TYPE_BLUETOOTH_A2DP;
+ }
+ }
+
+ private class AdapterStateChangedReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
+ if (state == BluetoothAdapter.STATE_OFF
+ || state == BluetoothAdapter.STATE_TURNING_OFF) {
+ synchronized (AudioPoliciesBluetoothRouteController.this) {
+ mBluetoothRoutes.clear();
+ }
+ notifyBluetoothRoutesUpdated();
+ } else if (state == BluetoothAdapter.STATE_ON) {
+ updateBluetoothRoutes();
+
+ boolean shouldCallListener;
+ synchronized (AudioPoliciesBluetoothRouteController.this) {
+ shouldCallListener = !mBluetoothRoutes.isEmpty();
+ }
+
+ if (shouldCallListener) {
+ notifyBluetoothRoutesUpdated();
+ }
+ }
+ }
+ }
+
+ private class DeviceStateChangedReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ switch (intent.getAction()) {
+ case BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED:
+ case BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED:
+ case BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED:
+ case BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED:
+ case BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED:
+ case BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED:
+ updateBluetoothRoutes();
+ notifyBluetoothRoutesUpdated();
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/media/AudioPoliciesDeviceRouteController.java b/services/core/java/com/android/server/media/AudioPoliciesDeviceRouteController.java
new file mode 100644
index 000000000000..961313de0c97
--- /dev/null
+++ b/services/core/java/com/android/server/media/AudioPoliciesDeviceRouteController.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2023 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.media;
+
+import static android.media.MediaRoute2Info.FEATURE_LIVE_AUDIO;
+import static android.media.MediaRoute2Info.FEATURE_LIVE_VIDEO;
+import static android.media.MediaRoute2Info.FEATURE_LOCAL_PLAYBACK;
+import static android.media.MediaRoute2Info.TYPE_BUILTIN_SPEAKER;
+import static android.media.MediaRoute2Info.TYPE_DOCK;
+import static android.media.MediaRoute2Info.TYPE_HDMI;
+import static android.media.MediaRoute2Info.TYPE_USB_DEVICE;
+import static android.media.MediaRoute2Info.TYPE_WIRED_HEADPHONES;
+import static android.media.MediaRoute2Info.TYPE_WIRED_HEADSET;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.media.AudioManager;
+import android.media.AudioRoutesInfo;
+import android.media.IAudioRoutesObserver;
+import android.media.IAudioService;
+import android.media.MediaRoute2Info;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.Objects;
+
+
+/* package */ final class AudioPoliciesDeviceRouteController implements DeviceRouteController {
+
+ private static final String TAG = "APDeviceRoutesController";
+
+ private static final String DEVICE_ROUTE_ID = "DEVICE_ROUTE";
+
+ @NonNull
+ private final Context mContext;
+ @NonNull
+ private final AudioManager mAudioManager;
+ @NonNull
+ private final IAudioService mAudioService;
+
+ @NonNull
+ private final OnDeviceRouteChangedListener mOnDeviceRouteChangedListener;
+ @NonNull
+ private final AudioRoutesObserver mAudioRoutesObserver = new AudioRoutesObserver();
+
+ private int mDeviceVolume;
+ private MediaRoute2Info mDeviceRoute;
+
+ @VisibleForTesting
+ /* package */ AudioPoliciesDeviceRouteController(@NonNull Context context,
+ @NonNull AudioManager audioManager,
+ @NonNull IAudioService audioService,
+ @NonNull OnDeviceRouteChangedListener onDeviceRouteChangedListener) {
+ Objects.requireNonNull(context);
+ Objects.requireNonNull(audioManager);
+ Objects.requireNonNull(audioService);
+ Objects.requireNonNull(onDeviceRouteChangedListener);
+
+ mContext = context;
+ mOnDeviceRouteChangedListener = onDeviceRouteChangedListener;
+
+ mAudioManager = audioManager;
+ mAudioService = audioService;
+
+ AudioRoutesInfo newAudioRoutes = null;
+ try {
+ newAudioRoutes = mAudioService.startWatchingRoutes(mAudioRoutesObserver);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Cannot connect to audio service to start listen to routes", e);
+ }
+
+ mDeviceRoute = createRouteFromAudioInfo(newAudioRoutes);
+ }
+
+ @Override
+ public boolean selectRoute(@Nullable Integer type) {
+ // No-op as the controller does not support selection from the outside of the class.
+ return false;
+ }
+
+ @Override
+ @NonNull
+ public synchronized MediaRoute2Info getDeviceRoute() {
+ return mDeviceRoute;
+ }
+
+ @Override
+ public synchronized boolean updateVolume(int volume) {
+ if (mDeviceVolume == volume) {
+ return false;
+ }
+
+ mDeviceVolume = volume;
+ mDeviceRoute = new MediaRoute2Info.Builder(mDeviceRoute)
+ .setVolume(volume)
+ .build();
+
+ return true;
+ }
+
+ private MediaRoute2Info createRouteFromAudioInfo(@Nullable AudioRoutesInfo newRoutes) {
+ int name = R.string.default_audio_route_name;
+ int type = TYPE_BUILTIN_SPEAKER;
+
+ if (newRoutes != null) {
+ if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADPHONES) != 0) {
+ type = TYPE_WIRED_HEADPHONES;
+ name = R.string.default_audio_route_name_headphones;
+ } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADSET) != 0) {
+ type = TYPE_WIRED_HEADSET;
+ name = R.string.default_audio_route_name_headphones;
+ } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_DOCK_SPEAKERS) != 0) {
+ type = TYPE_DOCK;
+ name = R.string.default_audio_route_name_dock_speakers;
+ } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HDMI) != 0) {
+ type = TYPE_HDMI;
+ name = R.string.default_audio_route_name_external_device;
+ } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_USB) != 0) {
+ type = TYPE_USB_DEVICE;
+ name = R.string.default_audio_route_name_usb;
+ }
+ }
+
+ synchronized (this) {
+ return new MediaRoute2Info.Builder(
+ DEVICE_ROUTE_ID, mContext.getResources().getText(name).toString())
+ .setVolumeHandling(mAudioManager.isVolumeFixed()
+ ? MediaRoute2Info.PLAYBACK_VOLUME_FIXED
+ : MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
+ .setVolume(mDeviceVolume)
+ .setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
+ .setType(type)
+ .addFeature(FEATURE_LIVE_AUDIO)
+ .addFeature(FEATURE_LIVE_VIDEO)
+ .addFeature(FEATURE_LOCAL_PLAYBACK)
+ .setConnectionState(MediaRoute2Info.CONNECTION_STATE_CONNECTED)
+ .build();
+ }
+ }
+
+ private void notifyDeviceRouteUpdate(@NonNull MediaRoute2Info deviceRoute) {
+ mOnDeviceRouteChangedListener.onDeviceRouteChanged(deviceRoute);
+ }
+
+ private class AudioRoutesObserver extends IAudioRoutesObserver.Stub {
+
+ @Override
+ public void dispatchAudioRoutesChanged(AudioRoutesInfo newAudioRoutes) {
+ MediaRoute2Info deviceRoute = createRouteFromAudioInfo(newAudioRoutes);
+ synchronized (AudioPoliciesDeviceRouteController.this) {
+ mDeviceRoute = deviceRoute;
+ }
+ notifyDeviceRouteUpdate(deviceRoute);
+ }
+ }
+
+}
diff --git a/services/core/java/com/android/server/media/BluetoothProfileMonitor.java b/services/core/java/com/android/server/media/BluetoothProfileMonitor.java
new file mode 100644
index 000000000000..b129dd0f74c6
--- /dev/null
+++ b/services/core/java/com/android/server/media/BluetoothProfileMonitor.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2023 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.media;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothLeAudio;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+
+import java.util.Objects;
+
+/* package */ class BluetoothProfileMonitor {
+
+ /* package */ static final long GROUP_ID_NO_GROUP = -1L;
+
+ @NonNull
+ private final ProfileListener mProfileListener = new ProfileListener();
+
+ @NonNull
+ private final Context mContext;
+ @NonNull
+ private final BluetoothAdapter mBluetoothAdapter;
+
+ @Nullable
+ private BluetoothA2dp mA2dpProfile;
+ @Nullable
+ private BluetoothHearingAid mHearingAidProfile;
+ @Nullable
+ private BluetoothLeAudio mLeAudioProfile;
+
+ @Nullable
+ private OnProfileChangedListener mOnProfileChangedListener;
+
+ BluetoothProfileMonitor(@NonNull Context context,
+ @NonNull BluetoothAdapter bluetoothAdapter) {
+ Objects.requireNonNull(context);
+ Objects.requireNonNull(bluetoothAdapter);
+
+ mContext = context;
+ mBluetoothAdapter = bluetoothAdapter;
+ }
+
+ /* package */ synchronized void setOnProfileChangedListener(
+ @NonNull OnProfileChangedListener listener) {
+ mOnProfileChangedListener = listener;
+ }
+
+ /* package */ void start() {
+ mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.A2DP);
+ mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.HEARING_AID);
+ mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.LE_AUDIO);
+ }
+
+ /* package */ boolean isProfileSupported(int profile, @NonNull BluetoothDevice device) {
+ BluetoothProfile bluetoothProfile;
+
+ synchronized (this) {
+ switch (profile) {
+ case BluetoothProfile.A2DP:
+ bluetoothProfile = mA2dpProfile;
+ break;
+ case BluetoothProfile.LE_AUDIO:
+ bluetoothProfile = mLeAudioProfile;
+ break;
+ case BluetoothProfile.HEARING_AID:
+ bluetoothProfile = mHearingAidProfile;
+ break;
+ default:
+ throw new IllegalArgumentException(profile
+ + " is not supported as Bluetooth profile");
+ }
+ }
+
+ if (bluetoothProfile == null) {
+ return false;
+ }
+
+ return bluetoothProfile.getConnectedDevices().contains(device);
+ }
+
+ /* package */ long getGroupId(int profile, @NonNull BluetoothDevice device) {
+ synchronized (this) {
+ switch (profile) {
+ case BluetoothProfile.A2DP:
+ return GROUP_ID_NO_GROUP;
+ case BluetoothProfile.LE_AUDIO:
+ return mLeAudioProfile == null ? GROUP_ID_NO_GROUP : mLeAudioProfile.getGroupId(
+ device);
+ case BluetoothProfile.HEARING_AID:
+ return mHearingAidProfile == null
+ ? GROUP_ID_NO_GROUP : mHearingAidProfile.getHiSyncId(device);
+ default:
+ throw new IllegalArgumentException(profile
+ + " is not supported as Bluetooth profile");
+ }
+ }
+ }
+
+ /* package */ interface OnProfileChangedListener {
+ void onProfileChange(int profile);
+ }
+
+ private final class ProfileListener implements BluetoothProfile.ServiceListener {
+ @Override
+ public void onServiceConnected(int profile, BluetoothProfile proxy) {
+ OnProfileChangedListener listener;
+
+ synchronized (BluetoothProfileMonitor.this) {
+ switch (profile) {
+ case BluetoothProfile.A2DP:
+ mA2dpProfile = (BluetoothA2dp) proxy;
+ break;
+ case BluetoothProfile.HEARING_AID:
+ mHearingAidProfile = (BluetoothHearingAid) proxy;
+ break;
+ case BluetoothProfile.LE_AUDIO:
+ mLeAudioProfile = (BluetoothLeAudio) proxy;
+ break;
+ default:
+ return;
+ }
+
+ listener = mOnProfileChangedListener;
+ }
+
+ if (listener != null) {
+ listener.onProfileChange(profile);
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(int profile) {
+ OnProfileChangedListener listener;
+
+ synchronized (BluetoothProfileMonitor.this) {
+ switch (profile) {
+ case BluetoothProfile.A2DP:
+ mA2dpProfile = null;
+ break;
+ case BluetoothProfile.HEARING_AID:
+ mHearingAidProfile = null;
+ break;
+ case BluetoothProfile.LE_AUDIO:
+ mLeAudioProfile = null;
+ break;
+ default:
+ return;
+ }
+
+ listener = mOnProfileChangedListener;
+ }
+
+ if (listener != null) {
+ listener.onProfileChange(profile);
+ }
+ }
+ }
+
+}
diff --git a/services/core/java/com/android/server/media/BluetoothRouteController.java b/services/core/java/com/android/server/media/BluetoothRouteController.java
index 08691d035f29..d4a118458952 100644
--- a/services/core/java/com/android/server/media/BluetoothRouteController.java
+++ b/services/core/java/com/android/server/media/BluetoothRouteController.java
@@ -68,6 +68,17 @@ import java.util.Objects;
*/
void stop();
+
+ /**
+ * Selects the route with the given {@code deviceAddress}.
+ *
+ * @param deviceAddress The physical address of the device to select. May be null to unselect
+ * the currently selected device.
+ * @return Whether the selection succeeds. If the selection fails, the state of the instance
+ * remains unaltered.
+ */
+ boolean selectRoute(@Nullable String deviceAddress);
+
/**
* Transfers Bluetooth output to the given route.
*
@@ -145,6 +156,12 @@ import java.util.Objects;
}
@Override
+ public boolean selectRoute(String deviceAddress) {
+ // no op
+ return false;
+ }
+
+ @Override
public void transferTo(String routeId) {
// no op
}
diff --git a/services/core/java/com/android/server/media/DeviceRouteController.java b/services/core/java/com/android/server/media/DeviceRouteController.java
new file mode 100644
index 000000000000..d7893eed800b
--- /dev/null
+++ b/services/core/java/com/android/server/media/DeviceRouteController.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2023 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.media;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.media.AudioManager;
+import android.media.IAudioRoutesObserver;
+import android.media.IAudioService;
+import android.media.MediaRoute2Info;
+import android.os.ServiceManager;
+
+/**
+ * Controls device routes.
+ *
+ * <p>A device route is a system wired route, for example, built-in speaker, wired
+ * headsets and headphones, dock, hdmi, or usb devices.
+ *
+ * @see SystemMediaRoute2Provider
+ */
+/* package */ interface DeviceRouteController {
+
+ /**
+ * Returns a new instance of {@link DeviceRouteController}.
+ */
+ /* package */ static DeviceRouteController createInstance(@NonNull Context context,
+ @NonNull OnDeviceRouteChangedListener onDeviceRouteChangedListener) {
+ AudioManager audioManager = context.getSystemService(AudioManager.class);
+ IAudioService audioService = IAudioService.Stub.asInterface(
+ ServiceManager.getService(Context.AUDIO_SERVICE));
+
+ return new LegacyDeviceRouteController(context,
+ audioManager,
+ audioService,
+ onDeviceRouteChangedListener);
+ }
+
+ /**
+ * Select the route with the given built-in or wired {@link MediaRoute2Info.Type}.
+ *
+ * <p>If the type is {@code null} then unselects the route and falls back to the default device
+ * route observed from
+ * {@link com.android.server.audio.AudioService#startWatchingRoutes(IAudioRoutesObserver)}.
+ *
+ * @param type device type. May be {@code null} to unselect currently selected route.
+ * @return whether the selection succeeds. If the selection fails the state of the controller
+ * remains intact.
+ */
+ boolean selectRoute(@Nullable @MediaRoute2Info.Type Integer type);
+
+ /**
+ * Returns currently selected device (built-in or wired) route.
+ *
+ * @return non-null device route.
+ */
+ @NonNull
+ MediaRoute2Info getDeviceRoute();
+
+ /**
+ * Updates device route volume.
+ *
+ * @param volume specifies a volume for the device route or 0 for unknown.
+ * @return {@code true} if updated successfully and {@code false} otherwise.
+ */
+ boolean updateVolume(int volume);
+
+ /**
+ * Interface for receiving events when device route has changed.
+ */
+ interface OnDeviceRouteChangedListener {
+
+ /**
+ * Called when device route has changed.
+ *
+ * @param deviceRoute non-null device route.
+ */
+ void onDeviceRouteChanged(@NonNull MediaRoute2Info deviceRoute);
+ }
+
+}
diff --git a/services/core/java/com/android/server/media/LegacyBluetoothRouteController.java b/services/core/java/com/android/server/media/LegacyBluetoothRouteController.java
index 7979d2a3fb3b..e31a7fc5d5ff 100644
--- a/services/core/java/com/android/server/media/LegacyBluetoothRouteController.java
+++ b/services/core/java/com/android/server/media/LegacyBluetoothRouteController.java
@@ -52,7 +52,7 @@ import java.util.Map;
import java.util.Set;
class LegacyBluetoothRouteController implements BluetoothRouteController {
- private static final String TAG = "BTRouteProvider";
+ private static final String TAG = "LBtRouteProvider";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final String HEARING_AID_ROUTE_ID_PREFIX = "HEARING_AID_";
@@ -132,6 +132,12 @@ class LegacyBluetoothRouteController implements BluetoothRouteController {
mContext.unregisterReceiver(mDeviceStateChangedReceiver);
}
+ @Override
+ public boolean selectRoute(String deviceAddress) {
+ // No-op as the class decides if a route is selected based on Bluetooth events.
+ return false;
+ }
+
/**
* Transfers to a given bluetooth route.
* The dedicated BT device with the route would be activated.
diff --git a/services/core/java/com/android/server/media/LegacyDeviceRouteController.java b/services/core/java/com/android/server/media/LegacyDeviceRouteController.java
new file mode 100644
index 000000000000..971d11f24b9c
--- /dev/null
+++ b/services/core/java/com/android/server/media/LegacyDeviceRouteController.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2023 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.media;
+
+import static android.media.MediaRoute2Info.FEATURE_LIVE_AUDIO;
+import static android.media.MediaRoute2Info.FEATURE_LIVE_VIDEO;
+import static android.media.MediaRoute2Info.FEATURE_LOCAL_PLAYBACK;
+import static android.media.MediaRoute2Info.TYPE_BUILTIN_SPEAKER;
+import static android.media.MediaRoute2Info.TYPE_DOCK;
+import static android.media.MediaRoute2Info.TYPE_HDMI;
+import static android.media.MediaRoute2Info.TYPE_USB_DEVICE;
+import static android.media.MediaRoute2Info.TYPE_WIRED_HEADPHONES;
+import static android.media.MediaRoute2Info.TYPE_WIRED_HEADSET;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.media.AudioManager;
+import android.media.AudioRoutesInfo;
+import android.media.IAudioRoutesObserver;
+import android.media.IAudioService;
+import android.media.MediaRoute2Info;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.Objects;
+
+/**
+ * Controls device routes.
+ *
+ * <p>A device route is a system wired route, for example, built-in speaker, wired
+ * headsets and headphones, dock, hdmi, or usb devices.
+ *
+ * <p>Thread safe.
+ *
+ * @see SystemMediaRoute2Provider
+ */
+/* package */ final class LegacyDeviceRouteController implements DeviceRouteController {
+
+ private static final String TAG = "LDeviceRouteController";
+
+ private static final String DEVICE_ROUTE_ID = "DEVICE_ROUTE";
+
+ @NonNull
+ private final Context mContext;
+ @NonNull
+ private final AudioManager mAudioManager;
+ @NonNull
+ private final IAudioService mAudioService;
+
+ @NonNull
+ private final OnDeviceRouteChangedListener mOnDeviceRouteChangedListener;
+ @NonNull
+ private final AudioRoutesObserver mAudioRoutesObserver = new AudioRoutesObserver();
+
+ private int mDeviceVolume;
+ private MediaRoute2Info mDeviceRoute;
+
+ @VisibleForTesting
+ /* package */ LegacyDeviceRouteController(@NonNull Context context,
+ @NonNull AudioManager audioManager,
+ @NonNull IAudioService audioService,
+ @NonNull OnDeviceRouteChangedListener onDeviceRouteChangedListener) {
+ Objects.requireNonNull(context);
+ Objects.requireNonNull(audioManager);
+ Objects.requireNonNull(audioService);
+ Objects.requireNonNull(onDeviceRouteChangedListener);
+
+ mContext = context;
+ mOnDeviceRouteChangedListener = onDeviceRouteChangedListener;
+
+ mAudioManager = audioManager;
+ mAudioService = audioService;
+
+ AudioRoutesInfo newAudioRoutes = null;
+ try {
+ newAudioRoutes = mAudioService.startWatchingRoutes(mAudioRoutesObserver);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Cannot connect to audio service to start listen to routes", e);
+ }
+
+ mDeviceRoute = createRouteFromAudioInfo(newAudioRoutes);
+ }
+
+ @Override
+ public boolean selectRoute(@Nullable Integer type) {
+ // No-op as the controller does not support selection from the outside of the class.
+ return false;
+ }
+
+ @Override
+ @NonNull
+ public synchronized MediaRoute2Info getDeviceRoute() {
+ return mDeviceRoute;
+ }
+
+ @Override
+ public synchronized boolean updateVolume(int volume) {
+ if (mDeviceVolume == volume) {
+ return false;
+ }
+
+ mDeviceVolume = volume;
+ mDeviceRoute = new MediaRoute2Info.Builder(mDeviceRoute)
+ .setVolume(volume)
+ .build();
+
+ return true;
+ }
+
+ private MediaRoute2Info createRouteFromAudioInfo(@Nullable AudioRoutesInfo newRoutes) {
+ int name = R.string.default_audio_route_name;
+ int type = TYPE_BUILTIN_SPEAKER;
+
+ if (newRoutes != null) {
+ if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADPHONES) != 0) {
+ type = TYPE_WIRED_HEADPHONES;
+ name = com.android.internal.R.string.default_audio_route_name_headphones;
+ } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADSET) != 0) {
+ type = TYPE_WIRED_HEADSET;
+ name = com.android.internal.R.string.default_audio_route_name_headphones;
+ } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_DOCK_SPEAKERS) != 0) {
+ type = TYPE_DOCK;
+ name = com.android.internal.R.string.default_audio_route_name_dock_speakers;
+ } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HDMI) != 0) {
+ type = TYPE_HDMI;
+ name = com.android.internal.R.string.default_audio_route_name_external_device;
+ } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_USB) != 0) {
+ type = TYPE_USB_DEVICE;
+ name = com.android.internal.R.string.default_audio_route_name_usb;
+ }
+ }
+
+ synchronized (this) {
+ return new MediaRoute2Info.Builder(
+ DEVICE_ROUTE_ID, mContext.getResources().getText(name).toString())
+ .setVolumeHandling(mAudioManager.isVolumeFixed()
+ ? MediaRoute2Info.PLAYBACK_VOLUME_FIXED
+ : MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
+ .setVolume(mDeviceVolume)
+ .setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
+ .setType(type)
+ .addFeature(FEATURE_LIVE_AUDIO)
+ .addFeature(FEATURE_LIVE_VIDEO)
+ .addFeature(FEATURE_LOCAL_PLAYBACK)
+ .setConnectionState(MediaRoute2Info.CONNECTION_STATE_CONNECTED)
+ .build();
+ }
+ }
+
+ private void notifyDeviceRouteUpdate(@NonNull MediaRoute2Info deviceRoute) {
+ mOnDeviceRouteChangedListener.onDeviceRouteChanged(deviceRoute);
+ }
+
+ private class AudioRoutesObserver extends IAudioRoutesObserver.Stub {
+
+ @Override
+ public void dispatchAudioRoutesChanged(AudioRoutesInfo newAudioRoutes) {
+ MediaRoute2Info deviceRoute = createRouteFromAudioInfo(newAudioRoutes);
+ synchronized (LegacyDeviceRouteController.this) {
+ mDeviceRoute = deviceRoute;
+ }
+ notifyDeviceRouteUpdate(deviceRoute);
+ }
+ }
+
+}
diff --git a/services/core/java/com/android/server/media/MediaFeatureFlagManager.java b/services/core/java/com/android/server/media/MediaFeatureFlagManager.java
new file mode 100644
index 000000000000..723cda056694
--- /dev/null
+++ b/services/core/java/com/android/server/media/MediaFeatureFlagManager.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2023 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.media;
+
+import android.annotation.StringDef;
+import android.provider.DeviceConfig;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/* package */ class MediaFeatureFlagManager {
+
+ /**
+ * Namespace for media better together features.
+ */
+ private static final String NAMESPACE_MEDIA_BETTER_TOGETHER = "media_better_together";
+
+ @StringDef(prefix = "FEATURE_", value = {
+ FEATURE_IS_USING_LEGACY_BLUETOOTH_CONTROLLER
+ })
+ @Target({ ElementType.TYPE_USE, ElementType.TYPE_PARAMETER })
+ @Retention(RetentionPolicy.SOURCE)
+ /* package */ @interface MediaFeatureFlag {}
+
+ /**
+ * Whether to use old legacy implementation of BluetoothRouteController or new
+ * 'Audio Strategies'-aware controller.
+ */
+ /* package */ static final @MediaFeatureFlag String
+ FEATURE_IS_USING_LEGACY_BLUETOOTH_CONTROLLER =
+ "BluetoothRouteController__enable_legacy_bluetooth_routes_controller";
+
+ private static final MediaFeatureFlagManager sInstance = new MediaFeatureFlagManager();
+
+ private MediaFeatureFlagManager() {
+ // Empty to prevent instantiation.
+ }
+
+ /* package */ MediaFeatureFlagManager getInstance() {
+ return sInstance;
+ }
+
+ /**
+ * Returns a boolean value from {@link DeviceConfig} from the system_time namespace, or
+ * {@code defaultValue} if there is no explicit value set.
+ */
+ public boolean getBoolean(@MediaFeatureFlag String key, boolean defaultValue) {
+ return DeviceConfig.getBoolean(NAMESPACE_MEDIA_BETTER_TOGETHER, key, defaultValue);
+ }
+}
diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
index 76ff19fcb322..6619e6c3d26f 100644
--- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
@@ -16,25 +16,12 @@
package com.android.server.media;
-import static android.media.MediaRoute2Info.FEATURE_LIVE_AUDIO;
-import static android.media.MediaRoute2Info.FEATURE_LIVE_VIDEO;
-import static android.media.MediaRoute2Info.FEATURE_LOCAL_PLAYBACK;
-import static android.media.MediaRoute2Info.TYPE_BUILTIN_SPEAKER;
-import static android.media.MediaRoute2Info.TYPE_DOCK;
-import static android.media.MediaRoute2Info.TYPE_HDMI;
-import static android.media.MediaRoute2Info.TYPE_USB_DEVICE;
-import static android.media.MediaRoute2Info.TYPE_WIRED_HEADPHONES;
-import static android.media.MediaRoute2Info.TYPE_WIRED_HEADSET;
-
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
-import android.media.AudioRoutesInfo;
-import android.media.IAudioRoutesObserver;
-import android.media.IAudioService;
import android.media.MediaRoute2Info;
import android.media.MediaRoute2ProviderInfo;
import android.media.MediaRoute2ProviderService;
@@ -43,14 +30,11 @@ import android.media.RoutingSessionInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
-import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;
-import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import java.util.Objects;
@@ -68,23 +52,21 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
SystemMediaRoute2Provider.class.getName());
static final String DEFAULT_ROUTE_ID = "DEFAULT_ROUTE";
- static final String DEVICE_ROUTE_ID = "DEVICE_ROUTE";
static final String SYSTEM_SESSION_ID = "SYSTEM_SESSION";
private final AudioManager mAudioManager;
- private final IAudioService mAudioService;
private final Handler mHandler;
private final Context mContext;
private final UserHandle mUser;
- private final BluetoothRouteController mBtRouteProvider;
+
+ private final DeviceRouteController mDeviceRouteController;
+ private final BluetoothRouteController mBluetoothRouteController;
private String mSelectedRouteId;
// For apps without MODIFYING_AUDIO_ROUTING permission.
// This should be the currently selected route.
MediaRoute2Info mDefaultRoute;
- MediaRoute2Info mDeviceRoute;
RoutingSessionInfo mDefaultSessionInfo;
- int mDeviceVolume;
private final AudioManagerBroadcastReceiver mAudioReceiver =
new AudioManagerBroadcastReceiver();
@@ -93,19 +75,6 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
@GuardedBy("mRequestLock")
private volatile SessionCreationRequest mPendingSessionCreationRequest;
- final IAudioRoutesObserver.Stub mAudioRoutesObserver = new IAudioRoutesObserver.Stub() {
- @Override
- public void dispatchAudioRoutesChanged(final AudioRoutesInfo newRoutes) {
- mHandler.post(() -> {
- updateDeviceRoute(newRoutes);
- notifyProviderState();
- if (updateSessionInfosIfNeeded()) {
- notifySessionInfoUpdated();
- }
- });
- }
- };
-
SystemMediaRoute2Provider(Context context, UserHandle user) {
super(COMPONENT_NAME);
mIsSystemRouteProvider = true;
@@ -114,25 +83,26 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
mHandler = new Handler(Looper.getMainLooper());
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
- mAudioService = IAudioService.Stub.asInterface(
- ServiceManager.getService(Context.AUDIO_SERVICE));
- mBtRouteProvider = BluetoothRouteController.createInstance(context, (routes) -> {
+ mBluetoothRouteController = BluetoothRouteController.createInstance(context, (routes) -> {
publishProviderState();
if (updateSessionInfosIfNeeded()) {
notifySessionInfoUpdated();
}
});
- AudioRoutesInfo newAudioRoutes = null;
- try {
- newAudioRoutes = mAudioService.startWatchingRoutes(mAudioRoutesObserver);
- } catch (RemoteException e) {
- }
+ mDeviceRouteController = DeviceRouteController.createInstance(context, (deviceRoute) -> {
+ mHandler.post(() -> {
+ publishProviderState();
+ if (updateSessionInfosIfNeeded()) {
+ notifySessionInfoUpdated();
+ }
+ });
+ });
- // The methods below should be called after all fields are initialized, as they
+ // These methods below should be called after all fields are initialized, as they
// access the fields inside.
- updateDeviceRoute(newAudioRoutes);
+ updateProviderState();
updateSessionInfosIfNeeded();
}
@@ -143,7 +113,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
intentFilter, null, null);
mHandler.post(() -> {
- mBtRouteProvider.start(mUser);
+ mBluetoothRouteController.start(mUser);
notifyProviderState();
});
updateVolume();
@@ -152,7 +122,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
public void stop() {
mContext.unregisterReceiver(mAudioReceiver);
mHandler.post(() -> {
- mBtRouteProvider.stop();
+ mBluetoothRouteController.stop();
notifyProviderState();
});
}
@@ -216,10 +186,12 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
// The currently selected route is the default route.
return;
}
- if (TextUtils.equals(routeId, mDeviceRoute.getId())) {
- mBtRouteProvider.transferTo(null);
+
+ MediaRoute2Info deviceRoute = mDeviceRouteController.getDeviceRoute();
+ if (TextUtils.equals(routeId, deviceRoute.getId())) {
+ mBluetoothRouteController.transferTo(null);
} else {
- mBtRouteProvider.transferTo(routeId);
+ mBluetoothRouteController.transferTo(routeId);
}
}
@@ -254,58 +226,26 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
if (mSessionInfos.isEmpty()) {
return null;
}
+
+ MediaRoute2Info deviceRoute = mDeviceRouteController.getDeviceRoute();
+
RoutingSessionInfo.Builder builder = new RoutingSessionInfo.Builder(
SYSTEM_SESSION_ID, packageName).setSystemSession(true);
- builder.addSelectedRoute(mDeviceRoute.getId());
- for (MediaRoute2Info route : mBtRouteProvider.getAllBluetoothRoutes()) {
+ builder.addSelectedRoute(deviceRoute.getId());
+ for (MediaRoute2Info route : mBluetoothRouteController.getAllBluetoothRoutes()) {
builder.addTransferableRoute(route.getId());
}
return builder.setProviderId(mUniqueId).build();
}
}
- private void updateDeviceRoute(AudioRoutesInfo newRoutes) {
- int name = R.string.default_audio_route_name;
- int type = TYPE_BUILTIN_SPEAKER;
- if (newRoutes != null) {
- if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADPHONES) != 0) {
- type = TYPE_WIRED_HEADPHONES;
- name = com.android.internal.R.string.default_audio_route_name_headphones;
- } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADSET) != 0) {
- type = TYPE_WIRED_HEADSET;
- name = com.android.internal.R.string.default_audio_route_name_headphones;
- } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_DOCK_SPEAKERS) != 0) {
- type = TYPE_DOCK;
- name = com.android.internal.R.string.default_audio_route_name_dock_speakers;
- } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HDMI) != 0) {
- type = TYPE_HDMI;
- name = com.android.internal.R.string.default_audio_route_name_external_device;
- } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_USB) != 0) {
- type = TYPE_USB_DEVICE;
- name = com.android.internal.R.string.default_audio_route_name_usb;
- }
- }
-
- mDeviceRoute = new MediaRoute2Info.Builder(
- DEVICE_ROUTE_ID, mContext.getResources().getText(name).toString())
- .setVolumeHandling(mAudioManager.isVolumeFixed()
- ? MediaRoute2Info.PLAYBACK_VOLUME_FIXED
- : MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
- .setVolume(mDeviceVolume)
- .setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
- .setType(type)
- .addFeature(FEATURE_LIVE_AUDIO)
- .addFeature(FEATURE_LIVE_VIDEO)
- .addFeature(FEATURE_LOCAL_PLAYBACK)
- .setConnectionState(MediaRoute2Info.CONNECTION_STATE_CONNECTED)
- .build();
- updateProviderState();
- }
-
private void updateProviderState() {
MediaRoute2ProviderInfo.Builder builder = new MediaRoute2ProviderInfo.Builder();
- builder.addRoute(mDeviceRoute);
- for (MediaRoute2Info route : mBtRouteProvider.getAllBluetoothRoutes()) {
+
+ // We must have a device route in the provider info.
+ builder.addRoute(mDeviceRouteController.getDeviceRoute());
+
+ for (MediaRoute2Info route : mBluetoothRouteController.getAllBluetoothRoutes()) {
builder.addRoute(route);
}
MediaRoute2ProviderInfo providerInfo = builder.build();
@@ -327,11 +267,12 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
SYSTEM_SESSION_ID, "" /* clientPackageName */)
.setSystemSession(true);
- MediaRoute2Info selectedRoute = mDeviceRoute;
- MediaRoute2Info selectedBtRoute = mBtRouteProvider.getSelectedRoute();
+ MediaRoute2Info deviceRoute = mDeviceRouteController.getDeviceRoute();
+ MediaRoute2Info selectedRoute = deviceRoute;
+ MediaRoute2Info selectedBtRoute = mBluetoothRouteController.getSelectedRoute();
if (selectedBtRoute != null) {
selectedRoute = selectedBtRoute;
- builder.addTransferableRoute(mDeviceRoute.getId());
+ builder.addTransferableRoute(deviceRoute.getId());
}
mSelectedRouteId = selectedRoute.getId();
mDefaultRoute = new MediaRoute2Info.Builder(DEFAULT_ROUTE_ID, selectedRoute)
@@ -340,7 +281,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
.build();
builder.addSelectedRoute(mSelectedRouteId);
- for (MediaRoute2Info route : mBtRouteProvider.getTransferableRoutes()) {
+ for (MediaRoute2Info route : mBluetoothRouteController.getTransferableRoutes()) {
builder.addTransferableRoute(route.getId());
}
@@ -420,15 +361,12 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
.build();
}
- if (mBtRouteProvider.updateVolumeForDevices(devices, volume)) {
+ if (mBluetoothRouteController.updateVolumeForDevices(devices, volume)) {
return;
}
- if (mDeviceVolume != volume) {
- mDeviceVolume = volume;
- mDeviceRoute = new MediaRoute2Info.Builder(mDeviceRoute)
- .setVolume(volume)
- .build();
- }
+
+ mDeviceRouteController.updateVolume(volume);
+
publishProviderState();
}
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 53e841d50b33..73440b7f2eec 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -892,6 +892,7 @@ abstract public class ManagedServices {
return allowedComponents;
}
+ @NonNull
protected List<String> getAllowedPackages(int userId) {
final List<String> allowedPackages = new ArrayList<>();
synchronized (mApproved) {
@@ -1181,25 +1182,6 @@ abstract public class ManagedServices {
return installed;
}
- protected Set<String> getAllowedPackages() {
- final Set<String> allowedPackages = new ArraySet<>();
- synchronized (mApproved) {
- for (int k = 0; k < mApproved.size(); k++) {
- ArrayMap<Boolean, ArraySet<String>> allowedByType = mApproved.valueAt(k);
- for (int i = 0; i < allowedByType.size(); i++) {
- final ArraySet<String> allowed = allowedByType.valueAt(i);
- for (int j = 0; j < allowed.size(); j++) {
- String pkgName = getPackageName(allowed.valueAt(j));
- if (!TextUtils.isEmpty(pkgName)) {
- allowedPackages.add(pkgName);
- }
- }
- }
- }
- }
- return allowedPackages;
- }
-
private void trimApprovedListsAccordingToInstalledServices(int userId) {
synchronized (mApproved) {
final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(userId);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 38cddc4c0127..53b03d58beae 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -229,7 +229,6 @@ import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.VibrationEffect;
-import android.permission.PermissionCheckerManager;
import android.permission.PermissionManager;
import android.provider.DeviceConfig;
import android.provider.Settings;
@@ -2710,16 +2709,18 @@ public class NotificationManagerService extends SystemService {
}
private void sendRegisteredOnlyBroadcast(String action) {
- Intent intent = new Intent(action);
- getContext().sendBroadcastAsUser(intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY),
- UserHandle.ALL, null);
+ int[] userIds = mUmInternal.getProfileIds(mAmi.getCurrentUserId(), true);
+ Intent intent = new Intent(action).addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ for (int userId : userIds) {
+ getContext().sendBroadcastAsUser(intent, UserHandle.of(userId), null);
+ }
// explicitly send the broadcast to all DND packages, even if they aren't currently running
- intent.setFlags(0);
- final Set<String> dndApprovedPackages = mConditionProviders.getAllowedPackages();
- for (String pkg : dndApprovedPackages) {
- intent.setPackage(pkg);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
+ for (int userId : userIds) {
+ for (String pkg : mConditionProviders.getAllowedPackages(userId)) {
+ Intent pkgIntent = new Intent(action).setPackage(pkg).setFlags(
+ Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ getContext().sendBroadcastAsUser(pkgIntent, UserHandle.of(userId));
+ }
}
}
@@ -6774,7 +6775,7 @@ public class NotificationManagerService extends SystemService {
final int permissionResult = mPermissionManager.checkPermissionForDataDelivery(
Manifest.permission.USE_FULL_SCREEN_INTENT, source, /* message= */ null);
- if (permissionResult != PermissionCheckerManager.PERMISSION_GRANTED) {
+ if (permissionResult != PermissionManager.PERMISSION_GRANTED) {
makeStickyHun(notification);
}
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 69ea55969b03..59af58fb0dfb 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -22,6 +22,7 @@ import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_NONE;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_MAX;
import static android.app.NotificationManager.IMPORTANCE_NONE;
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
import static android.util.StatsLog.ANNOTATION_ID_IS_UID;
@@ -861,11 +862,11 @@ public class PreferencesHelper implements RankingConfig {
if (r == null) {
throw new IllegalArgumentException("Invalid package");
}
+ if (r.groups.size() >= NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT) {
+ throw new IllegalStateException("Limit exceed; cannot create more groups");
+ }
if (fromTargetApp) {
group.setBlocked(false);
- if (r.groups.size() >= NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT) {
- throw new IllegalStateException("Limit exceed; cannot create more groups");
- }
}
final NotificationChannelGroup oldGroup = r.groups.get(group.getId());
if (oldGroup != null) {
@@ -905,6 +906,9 @@ public class PreferencesHelper implements RankingConfig {
Objects.requireNonNull(channel);
Objects.requireNonNull(channel.getId());
Preconditions.checkArgument(!TextUtils.isEmpty(channel.getName()));
+ Preconditions.checkArgument(channel.getImportance() >= IMPORTANCE_NONE
+ && channel.getImportance() <= IMPORTANCE_MAX, "Invalid importance level");
+
boolean needsPolicyFileChange = false, wasUndeleted = false, needsDndChange = false;
synchronized (mPackagePreferences) {
PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid);
@@ -993,11 +997,6 @@ public class PreferencesHelper implements RankingConfig {
needsPolicyFileChange = true;
- if (channel.getImportance() < IMPORTANCE_NONE
- || channel.getImportance() > NotificationManager.IMPORTANCE_MAX) {
- throw new IllegalArgumentException("Invalid importance level");
- }
-
// Reset fields that apps aren't allowed to set.
if (fromTargetApp && !hasDndAccess) {
channel.setBypassDnd(r.priority == Notification.PRIORITY_MAX);
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 4b2c88c2bf06..27744626385e 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -20,7 +20,7 @@ import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_DISABLED;
import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_ENABLED;
import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_REMOVED;
import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_ANY;
-import static android.service.notification.DNDModeProto.ROOT_CONFIG;
+import static android.service.notification.NotificationServiceProto.ROOT_CONFIG;
import static android.util.StatsLog.ANNOTATION_ID_IS_UID;
import static com.android.internal.util.FrameworkStatsLog.DND_MODE_RULE;
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index faa06f70d411..9bca9f0192b2 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -404,7 +404,7 @@ public final class BackgroundDexOptService {
"BackgroundDexOptService_" + (isPostBootUpdateJob ? "PostBoot" : "Idle"),
() -> {
TimingsTraceAndSlog tr =
- new TimingsTraceAndSlog(TAG, Trace.TRACE_TAG_PACKAGE_MANAGER);
+ new TimingsTraceAndSlog(TAG, Trace.TRACE_TAG_DALVIK);
tr.traceBegin("jobExecution");
boolean completed = false;
boolean fatalError = false;
@@ -494,6 +494,8 @@ public final class BackgroundDexOptService {
@GuardedBy("mLock")
private void waitForDexOptThreadToFinishLocked() {
TimingsTraceAndSlog tr = new TimingsTraceAndSlog(TAG, Trace.TRACE_TAG_PACKAGE_MANAGER);
+ // This tracing section doesn't have any correspondence in ART Service - it never waits for
+ // cancellation to finish.
tr.traceBegin("waitForDexOptThreadToFinishLocked");
try {
// Wait but check in regular internal to see if the thread is still alive.
diff --git a/services/core/java/com/android/server/pm/DexOptHelper.java b/services/core/java/com/android/server/pm/DexOptHelper.java
index 1bd5b9962436..a9d4115b4b79 100644
--- a/services/core/java/com/android/server/pm/DexOptHelper.java
+++ b/services/core/java/com/android/server/pm/DexOptHelper.java
@@ -16,7 +16,7 @@
package com.android.server.pm;
-import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
+import static android.os.Trace.TRACE_TAG_DALVIK;
import static com.android.server.LocalManagerRegistry.ManagerNotFoundException;
import static com.android.server.pm.ApexManager.ActiveApexInfo;
@@ -40,6 +40,7 @@ import static dalvik.system.DexFile.isProfileGuidedCompilerFilter;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppGlobals;
+import android.app.role.RoleManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -272,7 +273,6 @@ public final class DexOptHelper {
* compiles it if needed.
*/
private void checkAndDexOptSystemUi(int reason) throws LegacyDexoptDisabledException {
- Installer.checkLegacyDexoptDisabled();
Computer snapshot = mPm.snapshotComputer();
String sysUiPackageName =
mPm.mContext.getString(com.android.internal.R.string.config_systemUi);
@@ -288,7 +288,7 @@ public final class DexOptHelper {
String compilerFilter;
if (isProfileGuidedCompilerFilter(targetCompilerFilter)) {
- compilerFilter = defaultCompilerFilter;
+ compilerFilter = "verify";
File profileFile = new File(getPrebuildProfilePath(pkg));
// Copy the profile to the reference profile path if it exists. Installd can only use a
@@ -312,7 +312,26 @@ public final class DexOptHelper {
compilerFilter = targetCompilerFilter;
}
- // We don't expect updates in current profiles to be significant here, but
+ performDexoptPackage(sysUiPackageName, reason, compilerFilter);
+ }
+
+ private void dexoptLauncher(int reason) throws LegacyDexoptDisabledException {
+ Computer snapshot = mPm.snapshotComputer();
+ RoleManager roleManager = mPm.mContext.getSystemService(RoleManager.class);
+ for (var packageName : roleManager.getRoleHolders(RoleManager.ROLE_HOME)) {
+ AndroidPackage pkg = snapshot.getPackage(packageName);
+ if (pkg == null) {
+ Log.w(TAG, "Launcher package " + packageName + " is not found for dexopting");
+ } else {
+ performDexoptPackage(packageName, reason, "speed-profile");
+ }
+ }
+ }
+
+ private void performDexoptPackage(@NonNull String packageName, int reason,
+ @NonNull String compilerFilter) throws LegacyDexoptDisabledException {
+ Installer.checkLegacyDexoptDisabled();
+
// DEXOPT_CHECK_FOR_PROFILES_UPDATES is set to replicate behaviour that will be
// unconditionally enabled for profile guided filters when ART Service is called instead of
// the legacy PackageDexOptimizer implementation.
@@ -320,8 +339,8 @@ public final class DexOptHelper {
? DexoptOptions.DEXOPT_CHECK_FOR_PROFILES_UPDATES
: 0;
- performDexOptTraced(new DexoptOptions(pkg.getPackageName(), REASON_BOOT_AFTER_OTA,
- compilerFilter, null /* splitName */, dexoptFlags));
+ performDexOptTraced(new DexoptOptions(
+ packageName, reason, compilerFilter, null /* splitName */, dexoptFlags));
}
/**
@@ -343,6 +362,10 @@ public final class DexOptHelper {
return;
}
+ Log.i(TAG,
+ "Starting boot dexopt for reason "
+ + DexoptOptions.convertToArtServiceDexoptReason(reason));
+
final long startTime = System.nanoTime();
if (useArtService()) {
@@ -351,9 +374,10 @@ public final class DexOptHelper {
null /* progressCallbackExecutor */, null /* progressCallback */);
} else {
try {
- // System UI is important to user experience, so we check it after a mainline update
- // or an OTA. It may need to be re-compiled in these cases.
+ // System UI and the launcher are important to user experience, so we check them
+ // after a mainline update or OTA. They may need to be re-compiled in these cases.
checkAndDexOptSystemUi(reason);
+ dexoptLauncher(reason);
if (reason != REASON_BOOT_AFTER_OTA && reason != REASON_FIRST_BOOT) {
return;
@@ -446,11 +470,11 @@ public final class DexOptHelper {
@DexOptResult
private int performDexOptTraced(DexoptOptions options) {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
+ Trace.traceBegin(TRACE_TAG_DALVIK, "dexopt");
try {
return performDexOptInternal(options);
} finally {
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ Trace.traceEnd(TRACE_TAG_DALVIK);
}
}
@@ -581,7 +605,7 @@ public final class DexOptHelper {
throw new IllegalArgumentException("Can't dexopt APEX package: " + packageName);
}
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
+ Trace.traceBegin(TRACE_TAG_DALVIK, "dexopt");
// Whoever is calling forceDexOpt wants a compiled package.
// Don't use profiles since that may cause compilation to be skipped.
@@ -591,7 +615,7 @@ public final class DexOptHelper {
@DexOptResult int res = performDexOptInternalWithDependenciesLI(pkg, packageState, options);
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ Trace.traceEnd(TRACE_TAG_DALVIK);
if (res != PackageDexOptimizer.DEX_OPT_PERFORMED) {
throw new IllegalStateException("Failed to dexopt: " + res);
}
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index a868470b0042..7fe6c7d5aa93 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -164,6 +164,7 @@ import com.android.internal.util.FrameworkStatsLog;
import com.android.server.EventLogTags;
import com.android.server.LocalManagerRegistry;
import com.android.server.art.model.DexoptParams;
+import com.android.server.art.model.DexoptResult;
import com.android.server.pm.Installer.LegacyDexoptDisabledException;
import com.android.server.pm.dex.ArtManagerService;
import com.android.server.pm.dex.DexManager;
@@ -2534,8 +2535,9 @@ final class InstallPackageHelper {
packageManagerLocal.withFilteredSnapshot()) {
DexoptParams params =
dexoptOptions.convertToDexoptParams(0 /* extraFlags */);
- DexOptHelper.getArtManagerLocal().dexoptPackage(
+ DexoptResult dexOptResult = DexOptHelper.getArtManagerLocal().dexoptPackage(
snapshot, packageName, params);
+ installRequest.onDexoptFinished(dexOptResult);
}
} else {
try {
diff --git a/services/core/java/com/android/server/pm/InstallRequest.java b/services/core/java/com/android/server/pm/InstallRequest.java
index 46ea010d9aaa..95e790450724 100644
--- a/services/core/java/com/android/server/pm/InstallRequest.java
+++ b/services/core/java/com/android/server/pm/InstallRequest.java
@@ -43,6 +43,7 @@ import android.util.ArrayMap;
import android.util.ExceptionUtils;
import android.util.Slog;
+import com.android.server.art.model.DexoptResult;
import com.android.server.pm.parsing.pkg.ParsedPackage;
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageState;
@@ -127,6 +128,8 @@ final class InstallRequest {
private final int mSessionId;
private final int mRequireUserAction;
+ private int mDexoptStatus;
+
// New install
InstallRequest(InstallingSession params) {
mUserId = params.getUser().getIdentifier();
@@ -609,6 +612,10 @@ final class InstallRequest {
return mRequireUserAction;
}
+ public int getDexoptStatus() {
+ return mDexoptStatus;
+ }
+
public void setScanFlags(int scanFlags) {
mScanFlags = scanFlags;
}
@@ -799,6 +806,25 @@ final class InstallRequest {
}
}
+ public void onDexoptFinished(DexoptResult dexoptResult) {
+ if (mPackageMetrics == null) {
+ return;
+ }
+ mDexoptStatus = dexoptResult.getFinalStatus();
+ if (mDexoptStatus != DexoptResult.DEXOPT_PERFORMED) {
+ return;
+ }
+ long durationMillis = 0;
+ for (DexoptResult.PackageDexoptResult packageResult :
+ dexoptResult.getPackageDexoptResults()) {
+ for (DexoptResult.DexContainerFileDexoptResult fileResult :
+ packageResult.getDexContainerFileDexoptResults()) {
+ durationMillis += fileResult.getDex2oatWallTimeMillis();
+ }
+ }
+ mPackageMetrics.onStepFinished(PackageMetrics.STEP_DEXOPT, durationMillis);
+ }
+
public void onInstallCompleted() {
if (getReturnCode() == INSTALL_SUCCEEDED) {
if (mPackageMetrics != null) {
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index f33813759e4f..0a90e7a30db6 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -386,7 +386,7 @@ public class PackageDexOptimizer {
options.getCompilationReason());
// OTAPreopt doesn't have stats so don't report in that case.
if (packageStats != null) {
- Trace.traceBegin(Trace.TRACE_TAG_PACKAGE_MANAGER, "dex2oat-metrics");
+ Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "dex2oat-metrics");
try {
long sessionId = sRandom.nextLong();
ArtStatsLogUtils.writeStatsLog(
@@ -403,7 +403,7 @@ public class PackageDexOptimizer {
dexCodeIsa,
path);
} finally {
- Trace.traceEnd(Trace.TRACE_TAG_PACKAGE_MANAGER);
+ Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index a42e78b69709..de5f0c4d523f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -6675,24 +6675,16 @@ public class PackageManagerService implements PackageSender, TestUtilityService
@Deprecated
public void legacyDumpProfiles(String packageName, boolean dumpClassesAndMethods)
throws LegacyDexoptDisabledException {
- /* Only the shell, root, or the app user should be able to dump profiles. */
- final int callingUid = Binder.getCallingUid();
final Computer snapshot = snapshotComputer();
- final String[] callerPackageNames = snapshot.getPackagesForUid(callingUid);
- if (!PackageManagerServiceUtils.isRootOrShell(callingUid)
- && !ArrayUtils.contains(callerPackageNames, packageName)) {
- throw new SecurityException("dumpProfiles");
- }
-
AndroidPackage pkg = snapshot.getPackage(packageName);
if (pkg == null) {
throw new IllegalArgumentException("Unknown package: " + packageName);
}
synchronized (mInstallLock) {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dump profiles");
+ Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "dump profiles");
mArtManagerService.dumpProfiles(pkg, dumpClassesAndMethods);
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 93b0dcba0afe..586e1123fdc4 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -391,6 +391,11 @@ class PackageManagerShellCommand extends ShellCommand {
private int runLegacyDexoptCommand(@NonNull String cmd)
throws RemoteException, LegacyDexoptDisabledException {
Installer.checkLegacyDexoptDisabled();
+
+ if (!PackageManagerServiceUtils.isRootOrShell(Binder.getCallingUid())) {
+ throw new SecurityException("Dexopt shell commands need root or shell access");
+ }
+
switch (cmd) {
case "compile":
return runCompile();
@@ -4410,10 +4415,9 @@ class PackageManagerShellCommand extends ShellCommand {
pw.println(" " + PackageManagerServiceCompilerMapping.REASON_STRINGS[i]);
}
pw.println(" --reset: restore package to its post-install state");
- pw.println(" --check-prof (true | false): look at profiles when doing dexopt?");
+ pw.println(" --check-prof (true | false): ignored - this is always true");
pw.println(" --secondary-dex: compile app secondary dex files");
pw.println(" --split SPLIT: compile only the given split name");
- pw.println(" --compile-layouts: compile layout resources for faster inflation");
pw.println("");
pw.println(" force-dex-opt PACKAGE");
pw.println(" Force immediate execution of dex opt for the given PACKAGE.");
diff --git a/services/core/java/com/android/server/pm/PackageMetrics.java b/services/core/java/com/android/server/pm/PackageMetrics.java
index fe014a499073..80d6ebbd90b3 100644
--- a/services/core/java/com/android/server/pm/PackageMetrics.java
+++ b/services/core/java/com/android/server/pm/PackageMetrics.java
@@ -48,12 +48,14 @@ final class PackageMetrics {
public static final int STEP_SCAN = 2;
public static final int STEP_RECONCILE = 3;
public static final int STEP_COMMIT = 4;
+ public static final int STEP_DEXOPT = 5;
@IntDef(prefix = {"STEP_"}, value = {
STEP_PREPARE,
STEP_SCAN,
STEP_RECONCILE,
STEP_COMMIT,
+ STEP_DEXOPT
})
@Retention(RetentionPolicy.SOURCE)
public @interface StepInt {
@@ -175,6 +177,10 @@ final class PackageMetrics {
}
}
+ public void onStepFinished(@StepInt int step, long durationMillis) {
+ mInstallSteps.put(step, new InstallStep(durationMillis));
+ }
+
// List of steps (e.g., 1, 2, 3) and corresponding list of durations (e.g., 200ms, 100ms, 150ms)
private Pair<int[], long[]> getInstallStepDurations() {
ArrayList<Integer> steps = new ArrayList<>();
@@ -203,6 +209,11 @@ final class PackageMetrics {
mStartTimestampMillis = System.currentTimeMillis();
}
+ InstallStep(long durationMillis) {
+ mStartTimestampMillis = -1;
+ mDurationMillis = durationMillis;
+ }
+
void finish() {
mDurationMillis = System.currentTimeMillis() - mStartTimestampMillis;
}
diff --git a/services/core/java/com/android/server/pm/ResilientAtomicFile.java b/services/core/java/com/android/server/pm/ResilientAtomicFile.java
new file mode 100644
index 000000000000..19aa4f8e8d0b
--- /dev/null
+++ b/services/core/java/com/android/server/pm/ResilientAtomicFile.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2023 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.pm;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.FileUtils;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+import android.util.Slog;
+
+import com.android.server.security.FileIntegrity;
+
+import libcore.io.IoUtils;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+final class ResilientAtomicFile implements Closeable {
+ private static final String LOG_TAG = "ResilientAtomicFile";
+
+ private final File mFile;
+
+ private final File mTemporaryBackup;
+
+ private final File mReserveCopy;
+
+ private final int mFileMode;
+
+ private final String mDebugName;
+
+ private final ReadEventLogger mReadEventLogger;
+
+ // Write state.
+ private FileOutputStream mMainOutStream = null;
+ private FileInputStream mMainInStream = null;
+ private FileOutputStream mReserveOutStream = null;
+ private FileInputStream mReserveInStream = null;
+
+ // Read state.
+ private File mCurrentFile = null;
+ private FileInputStream mCurrentInStream = null;
+
+ private void finalizeOutStream(FileOutputStream str) throws IOException {
+ // Flash/sync + set permissions.
+ str.flush();
+ FileUtils.sync(str);
+ FileUtils.setPermissions(str.getFD(), mFileMode, -1, -1);
+ }
+
+ ResilientAtomicFile(@NonNull File file, @NonNull File temporaryBackup,
+ @NonNull File reserveCopy, int fileMode, String debugName,
+ @Nullable ReadEventLogger readEventLogger) {
+ mFile = file;
+ mTemporaryBackup = temporaryBackup;
+ mReserveCopy = reserveCopy;
+ mFileMode = fileMode;
+ mDebugName = debugName;
+ mReadEventLogger = readEventLogger;
+ }
+
+ public File getBaseFile() {
+ return mFile;
+ }
+
+ public FileOutputStream startWrite() throws IOException {
+ if (mMainOutStream != null) {
+ throw new IllegalStateException("Duplicate startWrite call?");
+ }
+
+ new File(mFile.getParent()).mkdirs();
+
+ if (mFile.exists()) {
+ // Presence of backup settings file indicates that we failed
+ // to persist packages earlier. So preserve the older
+ // backup for future reference since the current packages
+ // might have been corrupted.
+ if (!mTemporaryBackup.exists()) {
+ if (!mFile.renameTo(mTemporaryBackup)) {
+ throw new IOException("Unable to backup " + mDebugName
+ + " file, current changes will be lost at reboot");
+ }
+ } else {
+ mFile.delete();
+ Slog.w(LOG_TAG, "Preserving older " + mDebugName + " backup");
+ }
+ }
+ // Reserve copy is not valid anymore.
+ mReserveCopy.delete();
+
+ // In case of MT access, it's possible the files get overwritten during write.
+ // Let's open all FDs we need now.
+ mMainOutStream = new FileOutputStream(mFile);
+ mMainInStream = new FileInputStream(mFile);
+ mReserveOutStream = new FileOutputStream(mReserveCopy);
+ mReserveInStream = new FileInputStream(mReserveCopy);
+
+ return mMainOutStream;
+ }
+
+ public void finishWrite(FileOutputStream str) throws IOException {
+ if (mMainOutStream != str) {
+ throw new IllegalStateException("Invalid incoming stream.");
+ }
+
+ // Flush and set permissions.
+ try (FileOutputStream mainOutStream = mMainOutStream) {
+ mMainOutStream = null;
+ finalizeOutStream(mainOutStream);
+ }
+ // New file successfully written, old one are no longer needed.
+ mTemporaryBackup.delete();
+
+ try (FileInputStream mainInStream = mMainInStream;
+ FileInputStream reserveInStream = mReserveInStream) {
+ mMainInStream = null;
+ mReserveInStream = null;
+
+ // Copy main file to reserve.
+ try (FileOutputStream reserveOutStream = mReserveOutStream) {
+ mReserveOutStream = null;
+ FileUtils.copy(mainInStream, reserveOutStream);
+ finalizeOutStream(reserveOutStream);
+ }
+
+ // Protect both main and reserve using fs-verity.
+ try (ParcelFileDescriptor mainPfd = ParcelFileDescriptor.dup(mainInStream.getFD());
+ ParcelFileDescriptor copyPfd = ParcelFileDescriptor.dup(reserveInStream.getFD())) {
+ FileIntegrity.setUpFsVerity(mainPfd);
+ FileIntegrity.setUpFsVerity(copyPfd);
+ } catch (IOException e) {
+ Slog.e(LOG_TAG, "Failed to verity-protect " + mDebugName, e);
+ }
+ } catch (IOException e) {
+ Slog.e(LOG_TAG, "Failed to write reserve copy " + mDebugName + ": " + mReserveCopy, e);
+ }
+ }
+
+ public void failWrite(FileOutputStream str) {
+ if (mMainOutStream != str) {
+ throw new IllegalStateException("Invalid incoming stream.");
+ }
+
+ // Close all FDs.
+ close();
+
+ // Clean up partially written files
+ if (mFile.exists()) {
+ if (!mFile.delete()) {
+ Slog.i(LOG_TAG, "Failed to clean up mangled file: " + mFile);
+ }
+ }
+ }
+
+ public FileInputStream openRead() throws IOException {
+ if (mTemporaryBackup.exists()) {
+ try {
+ mCurrentFile = mTemporaryBackup;
+ mCurrentInStream = new FileInputStream(mCurrentFile);
+ if (mReadEventLogger != null) {
+ mReadEventLogger.logEvent(Log.INFO,
+ "Need to read from backup " + mDebugName + " file");
+ }
+ if (mFile.exists()) {
+ // If both the backup and normal file exist, we
+ // ignore the normal one since it might have been
+ // corrupted.
+ Slog.w(LOG_TAG, "Cleaning up " + mDebugName + " file " + mFile);
+ mFile.delete();
+ }
+ // Ignore reserve copy as well.
+ mReserveCopy.delete();
+ } catch (java.io.IOException e) {
+ // We'll try for the normal settings file.
+ }
+ }
+
+ if (mCurrentInStream != null) {
+ return mCurrentInStream;
+ }
+
+ if (mFile.exists()) {
+ mCurrentFile = mFile;
+ mCurrentInStream = new FileInputStream(mCurrentFile);
+ } else if (mReserveCopy.exists()) {
+ mCurrentFile = mReserveCopy;
+ mCurrentInStream = new FileInputStream(mCurrentFile);
+ if (mReadEventLogger != null) {
+ mReadEventLogger.logEvent(Log.INFO,
+ "Need to read from reserve copy " + mDebugName + " file");
+ }
+ }
+
+ if (mCurrentInStream == null) {
+ if (mReadEventLogger != null) {
+ mReadEventLogger.logEvent(Log.INFO, "No " + mDebugName + " file");
+ }
+ }
+
+ return mCurrentInStream;
+ }
+
+ public void failRead(FileInputStream str, Exception e) {
+ if (mCurrentInStream != str) {
+ throw new IllegalStateException("Invalid incoming stream.");
+ }
+ mCurrentInStream = null;
+ IoUtils.closeQuietly(str);
+
+ if (mReadEventLogger != null) {
+ mReadEventLogger.logEvent(Log.ERROR,
+ "Error reading " + mDebugName + ", removing " + mCurrentFile + '\n'
+ + Log.getStackTraceString(e));
+ }
+
+ mCurrentFile.delete();
+ mCurrentFile = null;
+ }
+
+ public void delete() {
+ mFile.delete();
+ mTemporaryBackup.delete();
+ mReserveCopy.delete();
+ }
+
+ @Override
+ public void close() {
+ IoUtils.closeQuietly(mMainOutStream);
+ IoUtils.closeQuietly(mMainInStream);
+ IoUtils.closeQuietly(mReserveOutStream);
+ IoUtils.closeQuietly(mReserveInStream);
+ IoUtils.closeQuietly(mCurrentInStream);
+ mMainOutStream = null;
+ mMainInStream = null;
+ mReserveOutStream = null;
+ mReserveInStream = null;
+ mCurrentInStream = null;
+ mCurrentFile = null;
+ }
+
+ public String toString() {
+ return mFile.getPath();
+ }
+
+ interface ReadEventLogger {
+ void logEvent(int priority, String msg);
+ }
+}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index f1998f764e7c..b6557d000463 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -119,7 +119,6 @@ import com.android.server.pm.resolution.ComponentResolver;
import com.android.server.pm.verify.domain.DomainVerificationLegacySettings;
import com.android.server.pm.verify.domain.DomainVerificationManagerInternal;
import com.android.server.pm.verify.domain.DomainVerificationPersistence;
-import com.android.server.security.FileIntegrity;
import com.android.server.utils.Slogf;
import com.android.server.utils.Snappable;
import com.android.server.utils.SnapshotCache;
@@ -172,7 +171,7 @@ import java.util.function.Consumer;
/**
* Holds information about dynamic settings.
*/
-public final class Settings implements Watchable, Snappable {
+public final class Settings implements Watchable, Snappable, ResilientAtomicFile.ReadEventLogger {
private static final String TAG = "PackageSettings";
/**
@@ -344,7 +343,7 @@ public final class Settings implements Watchable, Snappable {
private static final String ATTR_BLOCK_UNINSTALL = "blockUninstall";
private static final String ATTR_ENABLED = "enabled";
private static final String ATTR_ENABLED_CALLER = "enabledCaller";
- private static final String ATTR_DOMAIN_VERIFICATON_STATE = "domainVerificationStatus";
+ private static final String ATTR_DOMAIN_VERIFICATION_STATE = "domainVerificationStatus";
private static final String ATTR_APP_LINK_GENERATION = "app-link-generation";
private static final String ATTR_INSTALL_REASON = "install-reason";
private static final String ATTR_UNINSTALL_REASON = "uninstall-reason";
@@ -1511,16 +1510,22 @@ public final class Settings implements Watchable, Snappable {
return new File(new File(mSystemDir, "users"), Integer.toString(userId));
}
- // The method itself does not have to be guarded, but the file does.
- @GuardedBy("mPackageRestrictionsLock")
- private File getUserPackagesStateFile(int userId) {
- return new File(getUserSystemDirectory(userId), "package-restrictions.xml");
+ private ResilientAtomicFile getUserPackagesStateFile(int userId) {
+ File mainFile = new File(getUserSystemDirectory(userId), "package-restrictions.xml");
+ File temporaryBackup = new File(getUserSystemDirectory(userId),
+ "package-restrictions-backup.xml");
+ File reserveCopy = new File(getUserSystemDirectory(userId),
+ "package-restrictions.xml.reservecopy");
+ return new ResilientAtomicFile(mainFile, temporaryBackup, reserveCopy,
+ FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IRGRP | FileUtils.S_IWGRP,
+ "package restrictions", this);
}
- // The method itself does not have to be guarded, but the file does.
- @GuardedBy("mPackageRestrictionsLock")
- private File getUserPackagesStateBackupFile(int userId) {
- return new File(getUserSystemDirectory(userId), "package-restrictions-backup.xml");
+ private ResilientAtomicFile getSettingsFile() {
+ return new ResilientAtomicFile(mSettingsFilename, mPreviousSettingsFilename,
+ mSettingsReserveCopyFilename,
+ FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IRGRP | FileUtils.S_IWGRP,
+ "package manager settings", this);
}
private File getUserRuntimePermissionsFile(int userId) {
@@ -1730,272 +1735,243 @@ public final class Settings implements Watchable, Snappable {
}
}
+ @Override
+ public void logEvent(int priority, String msg) {
+ mReadMessages.append(msg + "\n");
+ PackageManagerService.reportSettingsProblem(priority, msg);
+ }
+
+
void readPackageRestrictionsLPr(int userId,
@NonNull ArrayMap<String, Long> origFirstInstallTimes) {
if (DEBUG_MU) {
Log.i(TAG, "Reading package restrictions for user=" + userId);
}
- FileInputStream str = null;
- synchronized (mPackageRestrictionsLock) {
- File userPackagesStateFile = getUserPackagesStateFile(userId);
- File backupFile = getUserPackagesStateBackupFile(userId);
- if (backupFile.exists()) {
- try {
- str = new FileInputStream(backupFile);
- mReadMessages.append("Reading from backup stopped packages file\n");
- PackageManagerService.reportSettingsProblem(Log.INFO,
- "Need to read from backup stopped packages file");
- if (userPackagesStateFile.exists()) {
- // If both the backup and normal file exist, we
- // ignore the normal one since it might have been
- // corrupted.
- Slog.w(PackageManagerService.TAG, "Cleaning up stopped packages file "
- + userPackagesStateFile);
- userPackagesStateFile.delete();
+ try (ResilientAtomicFile atomicFile = getUserPackagesStateFile(userId)) {
+ FileInputStream str = null;
+ try {
+ synchronized (mPackageRestrictionsLock) {
+ str = atomicFile.openRead();
+ if (str == null) {
+ // At first boot, make sure no packages are stopped.
+ // We usually want to have third party apps initialize
+ // in the stopped state, but not at first boot. Also
+ // consider all applications to be installed.
+ for (PackageSetting pkg : mPackages.values()) {
+ pkg.setUserState(userId, 0, COMPONENT_ENABLED_STATE_DEFAULT,
+ true /*installed*/,
+ false /*stopped*/,
+ false /*notLaunched*/,
+ false /*hidden*/,
+ 0 /*distractionFlags*/,
+ null /*suspendParams*/,
+ false /*instantApp*/,
+ false /*virtualPreload*/,
+ null /*lastDisableAppCaller*/,
+ null /*enabledComponents*/,
+ null /*disabledComponents*/,
+ PackageManager.INSTALL_REASON_UNKNOWN,
+ PackageManager.UNINSTALL_REASON_UNKNOWN,
+ null /*harmfulAppWarning*/,
+ null /* splashScreenTheme*/,
+ 0 /*firstInstallTime*/
+ );
+ }
+ return;
}
- } catch (java.io.IOException e) {
- // We'll try for the normal settings file.
}
- }
-
- if (str == null && userPackagesStateFile.exists()) {
- try {
- str = new FileInputStream(userPackagesStateFile);
- if (DEBUG_MU) Log.i(TAG, "Reading " + userPackagesStateFile);
- } catch (java.io.IOException e) {
- mReadMessages.append("Error reading: " + e.toString());
- PackageManagerService.reportSettingsProblem(Log.ERROR,
- "Error reading settings: " + e);
- Slog.wtf(TAG, "Error reading package manager stopped packages", e);
- }
- }
- }
-
- if (str == null) {
- mReadMessages.append("No stopped packages file found\n");
- PackageManagerService.reportSettingsProblem(Log.INFO,
- "No stopped packages file; "
- + "assuming all started");
- // At first boot, make sure no packages are stopped.
- // We usually want to have third party apps initialize
- // in the stopped state, but not at first boot. Also
- // consider all applications to be installed.
- for (PackageSetting pkg : mPackages.values()) {
- pkg.setUserState(userId, 0, COMPONENT_ENABLED_STATE_DEFAULT,
- true /*installed*/,
- false /*stopped*/,
- false /*notLaunched*/,
- false /*hidden*/,
- 0 /*distractionFlags*/,
- null /*suspendParams*/,
- false /*instantApp*/,
- false /*virtualPreload*/,
- null /*lastDisableAppCaller*/,
- null /*enabledComponents*/,
- null /*disabledComponents*/,
- PackageManager.INSTALL_REASON_UNKNOWN,
- PackageManager.UNINSTALL_REASON_UNKNOWN,
- null /*harmfulAppWarning*/,
- null /* splashScreenTheme*/,
- 0 /*firstInstallTime*/
- );
- }
- return;
- }
- try {
- final TypedXmlPullParser parser = Xml.resolvePullParser(str);
-
- int type;
- while ((type=parser.next()) != XmlPullParser.START_TAG
- && type != XmlPullParser.END_DOCUMENT) {
- ;
- }
+ final TypedXmlPullParser parser = Xml.resolvePullParser(str);
- if (type != XmlPullParser.START_TAG) {
- mReadMessages.append("No start tag found in package restrictions file\n");
- PackageManagerService.reportSettingsProblem(Log.WARN,
- "No start tag found in package manager stopped packages");
- return;
- }
+ int type;
+ while ((type = parser.next()) != XmlPullParser.START_TAG
+ && type != XmlPullParser.END_DOCUMENT) {
+ // nothing
+ }
- int outerDepth = parser.getDepth();
- PackageSetting ps = null;
- while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG
- || parser.getDepth() > outerDepth)) {
- if (type == XmlPullParser.END_TAG
- || type == XmlPullParser.TEXT) {
- continue;
+ if (type != XmlPullParser.START_TAG) {
+ mReadMessages.append("No start tag found in package restrictions file\n");
+ PackageManagerService.reportSettingsProblem(Log.WARN,
+ "No start tag found in package manager package restrictions file");
+ return;
}
- String tagName = parser.getName();
- if (tagName.equals(TAG_PACKAGE)) {
- String name = parser.getAttributeValue(null, ATTR_NAME);
- ps = mPackages.get(name);
- if (ps == null) {
- Slog.w(PackageManagerService.TAG, "No package known for stopped package "
- + name);
- XmlUtils.skipCurrentTag(parser);
+ int outerDepth = parser.getDepth();
+ PackageSetting ps = null;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG
+ || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG
+ || type == XmlPullParser.TEXT) {
continue;
}
- final long ceDataInode =
- parser.getAttributeLong(null, ATTR_CE_DATA_INODE, 0);
- final boolean installed =
- parser.getAttributeBoolean(null, ATTR_INSTALLED, true);
- final boolean stopped =
- parser.getAttributeBoolean(null, ATTR_STOPPED, false);
- final boolean notLaunched =
- parser.getAttributeBoolean(null, ATTR_NOT_LAUNCHED, false);
-
- // For backwards compatibility with the previous name of "blocked", which
- // now means hidden, read the old attribute as well.
- boolean hidden = parser.getAttributeBoolean(null, ATTR_HIDDEN, false);
- if (!hidden) {
- hidden = parser.getAttributeBoolean(null, ATTR_BLOCKED, false);
- }
+ String tagName = parser.getName();
+ if (tagName.equals(TAG_PACKAGE)) {
+ String name = parser.getAttributeValue(null, ATTR_NAME);
+ ps = mPackages.get(name);
+ if (ps == null) {
+ Slog.w(PackageManagerService.TAG,
+ "No package known for package restrictions " + name);
+ XmlUtils.skipCurrentTag(parser);
+ continue;
+ }
- final int distractionFlags = parser.getAttributeInt(null, ATTR_DISTRACTION_FLAGS, 0);
- final boolean suspended = parser.getAttributeBoolean(null, ATTR_SUSPENDED, false);
- String oldSuspendingPackage = parser.getAttributeValue(null,
- ATTR_SUSPENDING_PACKAGE);
- final String dialogMessage = parser.getAttributeValue(null,
- ATTR_SUSPEND_DIALOG_MESSAGE);
- if (suspended && oldSuspendingPackage == null) {
- oldSuspendingPackage = PLATFORM_PACKAGE_NAME;
- }
+ final long ceDataInode =
+ parser.getAttributeLong(null, ATTR_CE_DATA_INODE, 0);
+ final boolean installed =
+ parser.getAttributeBoolean(null, ATTR_INSTALLED, true);
+ final boolean stopped =
+ parser.getAttributeBoolean(null, ATTR_STOPPED, false);
+ final boolean notLaunched =
+ parser.getAttributeBoolean(null, ATTR_NOT_LAUNCHED, false);
+
+ // For backwards compatibility with the previous name of "blocked", which
+ // now means hidden, read the old attribute as well.
+ boolean hidden = parser.getAttributeBoolean(null, ATTR_HIDDEN, false);
+ if (!hidden) {
+ hidden = parser.getAttributeBoolean(null, ATTR_BLOCKED, false);
+ }
- final boolean blockUninstall =
- parser.getAttributeBoolean(null, ATTR_BLOCK_UNINSTALL, false);
- final boolean instantApp =
- parser.getAttributeBoolean(null, ATTR_INSTANT_APP, false);
- final boolean virtualPreload =
- parser.getAttributeBoolean(null, ATTR_VIRTUAL_PRELOAD, false);
- final int enabled = parser.getAttributeInt(null, ATTR_ENABLED,
- COMPONENT_ENABLED_STATE_DEFAULT);
- final String enabledCaller = parser.getAttributeValue(null,
- ATTR_ENABLED_CALLER);
- final String harmfulAppWarning =
- parser.getAttributeValue(null, ATTR_HARMFUL_APP_WARNING);
- final int verifState = parser.getAttributeInt(null,
- ATTR_DOMAIN_VERIFICATON_STATE,
- PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED);
- final int installReason = parser.getAttributeInt(null, ATTR_INSTALL_REASON,
- PackageManager.INSTALL_REASON_UNKNOWN);
- final int uninstallReason = parser.getAttributeInt(null, ATTR_UNINSTALL_REASON,
- PackageManager.UNINSTALL_REASON_UNKNOWN);
- final String splashScreenTheme = parser.getAttributeValue(null,
- ATTR_SPLASH_SCREEN_THEME);
- final long firstInstallTime = parser.getAttributeLongHex(null,
- ATTR_FIRST_INSTALL_TIME, 0);
-
- ArraySet<String> enabledComponents = null;
- ArraySet<String> disabledComponents = null;
- PersistableBundle suspendedAppExtras = null;
- PersistableBundle suspendedLauncherExtras = null;
- SuspendDialogInfo oldSuspendDialogInfo = null;
-
- int packageDepth = parser.getDepth();
- ArrayMap<String, SuspendParams> suspendParamsMap = null;
- while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG
- || parser.getDepth() > packageDepth)) {
- if (type == XmlPullParser.END_TAG
- || type == XmlPullParser.TEXT) {
- continue;
+ final int distractionFlags = parser.getAttributeInt(null,
+ ATTR_DISTRACTION_FLAGS, 0);
+ final boolean suspended = parser.getAttributeBoolean(null, ATTR_SUSPENDED,
+ false);
+ String oldSuspendingPackage = parser.getAttributeValue(null,
+ ATTR_SUSPENDING_PACKAGE);
+ final String dialogMessage = parser.getAttributeValue(null,
+ ATTR_SUSPEND_DIALOG_MESSAGE);
+ if (suspended && oldSuspendingPackage == null) {
+ oldSuspendingPackage = PLATFORM_PACKAGE_NAME;
}
- switch (parser.getName()) {
- case TAG_ENABLED_COMPONENTS:
- enabledComponents = readComponentsLPr(parser);
- break;
- case TAG_DISABLED_COMPONENTS:
- disabledComponents = readComponentsLPr(parser);
- break;
- case TAG_SUSPENDED_APP_EXTRAS:
- suspendedAppExtras = PersistableBundle.restoreFromXml(parser);
- break;
- case TAG_SUSPENDED_LAUNCHER_EXTRAS:
- suspendedLauncherExtras = PersistableBundle.restoreFromXml(parser);
- break;
- case TAG_SUSPENDED_DIALOG_INFO:
- oldSuspendDialogInfo = SuspendDialogInfo.restoreFromXml(parser);
- break;
- case TAG_SUSPEND_PARAMS:
- final String suspendingPackage = parser.getAttributeValue(null,
- ATTR_SUSPENDING_PACKAGE);
- if (suspendingPackage == null) {
- Slog.wtf(TAG, "No suspendingPackage found inside tag "
- + TAG_SUSPEND_PARAMS);
- continue;
- }
- if (suspendParamsMap == null) {
- suspendParamsMap = new ArrayMap<>();
- }
- suspendParamsMap.put(suspendingPackage,
- SuspendParams.restoreFromXml(parser));
- break;
- default:
- Slog.wtf(TAG, "Unknown tag " + parser.getName() + " under tag "
- + TAG_PACKAGE);
+
+ final boolean blockUninstall =
+ parser.getAttributeBoolean(null, ATTR_BLOCK_UNINSTALL, false);
+ final boolean instantApp =
+ parser.getAttributeBoolean(null, ATTR_INSTANT_APP, false);
+ final boolean virtualPreload =
+ parser.getAttributeBoolean(null, ATTR_VIRTUAL_PRELOAD, false);
+ final int enabled = parser.getAttributeInt(null, ATTR_ENABLED,
+ COMPONENT_ENABLED_STATE_DEFAULT);
+ final String enabledCaller = parser.getAttributeValue(null,
+ ATTR_ENABLED_CALLER);
+ final String harmfulAppWarning =
+ parser.getAttributeValue(null, ATTR_HARMFUL_APP_WARNING);
+ final int verifState = parser.getAttributeInt(null,
+ ATTR_DOMAIN_VERIFICATION_STATE,
+ PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED);
+ final int installReason = parser.getAttributeInt(null, ATTR_INSTALL_REASON,
+ PackageManager.INSTALL_REASON_UNKNOWN);
+ final int uninstallReason = parser.getAttributeInt(null,
+ ATTR_UNINSTALL_REASON,
+ PackageManager.UNINSTALL_REASON_UNKNOWN);
+ final String splashScreenTheme = parser.getAttributeValue(null,
+ ATTR_SPLASH_SCREEN_THEME);
+ final long firstInstallTime = parser.getAttributeLongHex(null,
+ ATTR_FIRST_INSTALL_TIME, 0);
+
+ ArraySet<String> enabledComponents = null;
+ ArraySet<String> disabledComponents = null;
+ PersistableBundle suspendedAppExtras = null;
+ PersistableBundle suspendedLauncherExtras = null;
+ SuspendDialogInfo oldSuspendDialogInfo = null;
+
+ int packageDepth = parser.getDepth();
+ ArrayMap<String, SuspendParams> suspendParamsMap = null;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG
+ || parser.getDepth() > packageDepth)) {
+ if (type == XmlPullParser.END_TAG
+ || type == XmlPullParser.TEXT) {
+ continue;
+ }
+ switch (parser.getName()) {
+ case TAG_ENABLED_COMPONENTS:
+ enabledComponents = readComponentsLPr(parser);
+ break;
+ case TAG_DISABLED_COMPONENTS:
+ disabledComponents = readComponentsLPr(parser);
+ break;
+ case TAG_SUSPENDED_APP_EXTRAS:
+ suspendedAppExtras = PersistableBundle.restoreFromXml(parser);
+ break;
+ case TAG_SUSPENDED_LAUNCHER_EXTRAS:
+ suspendedLauncherExtras = PersistableBundle.restoreFromXml(
+ parser);
+ break;
+ case TAG_SUSPENDED_DIALOG_INFO:
+ oldSuspendDialogInfo = SuspendDialogInfo.restoreFromXml(parser);
+ break;
+ case TAG_SUSPEND_PARAMS:
+ final String suspendingPackage = parser.getAttributeValue(null,
+ ATTR_SUSPENDING_PACKAGE);
+ if (suspendingPackage == null) {
+ Slog.wtf(TAG, "No suspendingPackage found inside tag "
+ + TAG_SUSPEND_PARAMS);
+ continue;
+ }
+ if (suspendParamsMap == null) {
+ suspendParamsMap = new ArrayMap<>();
+ }
+ suspendParamsMap.put(suspendingPackage,
+ SuspendParams.restoreFromXml(parser));
+ break;
+ default:
+ Slog.wtf(TAG, "Unknown tag " + parser.getName() + " under tag "
+ + TAG_PACKAGE);
+ }
+ }
+ if (oldSuspendDialogInfo == null && !TextUtils.isEmpty(dialogMessage)) {
+ oldSuspendDialogInfo = new SuspendDialogInfo.Builder()
+ .setMessage(dialogMessage)
+ .build();
+ }
+ if (suspended && suspendParamsMap == null) {
+ final SuspendParams suspendParams = new SuspendParams(
+ oldSuspendDialogInfo,
+ suspendedAppExtras,
+ suspendedLauncherExtras);
+ suspendParamsMap = new ArrayMap<>();
+ suspendParamsMap.put(oldSuspendingPackage, suspendParams);
}
- }
- if (oldSuspendDialogInfo == null && !TextUtils.isEmpty(dialogMessage)) {
- oldSuspendDialogInfo = new SuspendDialogInfo.Builder()
- .setMessage(dialogMessage)
- .build();
- }
- if (suspended && suspendParamsMap == null) {
- final SuspendParams suspendParams = new SuspendParams(
- oldSuspendDialogInfo,
- suspendedAppExtras,
- suspendedLauncherExtras);
- suspendParamsMap = new ArrayMap<>();
- suspendParamsMap.put(oldSuspendingPackage, suspendParams);
- }
- if (blockUninstall) {
- setBlockUninstallLPw(userId, name, true);
+ if (blockUninstall) {
+ setBlockUninstallLPw(userId, name, true);
+ }
+ ps.setUserState(userId, ceDataInode, enabled, installed, stopped,
+ notLaunched,
+ hidden, distractionFlags, suspendParamsMap, instantApp,
+ virtualPreload,
+ enabledCaller, enabledComponents, disabledComponents, installReason,
+ uninstallReason, harmfulAppWarning, splashScreenTheme,
+ firstInstallTime != 0 ? firstInstallTime :
+ origFirstInstallTimes.getOrDefault(name, 0L));
+
+ mDomainVerificationManager.setLegacyUserState(name, userId, verifState);
+ } else if (tagName.equals("preferred-activities")) {
+ readPreferredActivitiesLPw(parser, userId);
+ } else if (tagName.equals(TAG_PERSISTENT_PREFERRED_ACTIVITIES)) {
+ readPersistentPreferredActivitiesLPw(parser, userId);
+ } else if (tagName.equals(TAG_CROSS_PROFILE_INTENT_FILTERS)) {
+ readCrossProfileIntentFiltersLPw(parser, userId);
+ } else if (tagName.equals(TAG_DEFAULT_APPS)) {
+ readDefaultAppsLPw(parser, userId);
+ } else if (tagName.equals(TAG_BLOCK_UNINSTALL_PACKAGES)) {
+ readBlockUninstallPackagesLPw(parser, userId);
+ } else {
+ Slog.w(PackageManagerService.TAG,
+ "Unknown element under <stopped-packages>: "
+ + parser.getName());
+ XmlUtils.skipCurrentTag(parser);
}
- ps.setUserState(userId, ceDataInode, enabled, installed, stopped, notLaunched,
- hidden, distractionFlags, suspendParamsMap, instantApp, virtualPreload,
- enabledCaller, enabledComponents, disabledComponents, installReason,
- uninstallReason, harmfulAppWarning, splashScreenTheme,
- firstInstallTime != 0 ? firstInstallTime :
- origFirstInstallTimes.getOrDefault(name, 0L));
-
- mDomainVerificationManager.setLegacyUserState(name, userId, verifState);
- } else if (tagName.equals("preferred-activities")) {
- readPreferredActivitiesLPw(parser, userId);
- } else if (tagName.equals(TAG_PERSISTENT_PREFERRED_ACTIVITIES)) {
- readPersistentPreferredActivitiesLPw(parser, userId);
- } else if (tagName.equals(TAG_CROSS_PROFILE_INTENT_FILTERS)) {
- readCrossProfileIntentFiltersLPw(parser, userId);
- } else if (tagName.equals(TAG_DEFAULT_APPS)) {
- readDefaultAppsLPw(parser, userId);
- } else if (tagName.equals(TAG_BLOCK_UNINSTALL_PACKAGES)) {
- readBlockUninstallPackagesLPw(parser, userId);
- } else {
- Slog.w(PackageManagerService.TAG, "Unknown element under <stopped-packages>: "
- + parser.getName());
- XmlUtils.skipCurrentTag(parser);
}
- }
-
- str.close();
- } catch (XmlPullParserException e) {
- mReadMessages.append("Error reading: " + e.toString());
- PackageManagerService.reportSettingsProblem(Log.ERROR,
- "Error reading stopped packages: " + e);
- Slog.wtf(PackageManagerService.TAG, "Error reading package manager stopped packages",
- e);
+ } catch (IOException | XmlPullParserException e) {
+ // Remove corrupted file and retry.
+ atomicFile.failRead(str, e);
- } catch (java.io.IOException e) {
- mReadMessages.append("Error reading: " + e.toString());
- PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
- Slog.wtf(PackageManagerService.TAG, "Error reading package manager stopped packages",
- e);
+ readPackageRestrictionsLPr(userId, origFirstInstallTimes);
+ }
}
}
@@ -2165,219 +2141,176 @@ public final class Settings implements Watchable, Snappable {
Log.i(TAG, "Writing package restrictions for user=" + userId);
}
- final File userPackagesStateFile;
- final File backupFile;
- final FileOutputStream fstr;
-
- synchronized (mPackageRestrictionsLock) {
- if (!sync) {
- int pending = mPendingAsyncPackageRestrictionsWrites.get(userId, 0) - 1;
- if (pending < 0) {
- Log.i(TAG, "Cancel writing package restrictions for user=" + userId);
- return;
- }
- mPendingAsyncPackageRestrictionsWrites.put(userId, pending);
- }
+ FileOutputStream str = null;
+ try (ResilientAtomicFile atomicFile = getUserPackagesStateFile(userId)) {
+ try {
+ synchronized (mPackageRestrictionsLock) {
+ if (!sync) {
+ int pending = mPendingAsyncPackageRestrictionsWrites.get(userId, 0) - 1;
+ if (pending < 0) {
+ Log.i(TAG, "Cancel writing package restrictions for user=" + userId);
+ return;
+ }
+ mPendingAsyncPackageRestrictionsWrites.put(userId, pending);
+ }
- // Keep the old stopped packages around until we know the new ones have
- // been successfully written.
- userPackagesStateFile = getUserPackagesStateFile(userId);
- backupFile = getUserPackagesStateBackupFile(userId);
- new File(userPackagesStateFile.getParent()).mkdirs();
- if (userPackagesStateFile.exists()) {
- // Presence of backup settings file indicates that we failed
- // to persist packages earlier. So preserve the older
- // backup for future reference since the current packages
- // might have been corrupted.
- if (!backupFile.exists()) {
- if (!userPackagesStateFile.renameTo(backupFile)) {
+ try {
+ str = atomicFile.startWrite();
+ } catch (java.io.IOException e) {
Slog.wtf(PackageManagerService.TAG,
- "Unable to backup user packages state file, "
- + "current changes will be lost at reboot");
+ "Unable to write package manager package restrictions, "
+ + " current changes will be lost at reboot", e);
return;
}
- } else {
- userPackagesStateFile.delete();
- Slog.w(PackageManagerService.TAG, "Preserving older stopped packages backup");
}
- }
-
- try {
- fstr = new FileOutputStream(userPackagesStateFile);
- // File is created, set permissions.
- FileUtils.setPermissions(userPackagesStateFile.toString(),
- FileUtils.S_IRUSR | FileUtils.S_IWUSR
- | FileUtils.S_IRGRP | FileUtils.S_IWGRP,
- -1, -1);
- } catch (java.io.IOException e) {
- Slog.wtf(PackageManagerService.TAG,
- "Unable to write package manager user packages state, "
- + " current changes will be lost at reboot", e);
- return;
- }
- }
- try {
- synchronized (mLock) {
- final TypedXmlSerializer serializer = Xml.resolveSerializer(fstr);
- serializer.startDocument(null, true);
- serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output",
- true);
+ synchronized (mLock) {
+ final TypedXmlSerializer serializer = Xml.resolveSerializer(str);
+ serializer.startDocument(null, true);
+ serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output",
+ true);
- serializer.startTag(null, TAG_PACKAGE_RESTRICTIONS);
+ serializer.startTag(null, TAG_PACKAGE_RESTRICTIONS);
- if (DEBUG_MU) {
- Slogf.i(TAG, "Writing %s (%d packages)", userPackagesStateFile,
- mPackages.values().size());
- }
- for (final PackageSetting pkg : mPackages.values()) {
- final PackageUserStateInternal ustate = pkg.readUserState(userId);
if (DEBUG_MU) {
- Log.v(TAG, " pkg=" + pkg.getPackageName()
- + ", installed=" + ustate.isInstalled()
- + ", state=" + ustate.getEnabledState());
+ Slogf.i(TAG, "Writing %s (%d packages)", atomicFile,
+ mPackages.values().size());
}
+ for (final PackageSetting pkg : mPackages.values()) {
+ final PackageUserStateInternal ustate = pkg.readUserState(userId);
+ if (DEBUG_MU) {
+ Log.v(TAG, " pkg=" + pkg.getPackageName()
+ + ", installed=" + ustate.isInstalled()
+ + ", state=" + ustate.getEnabledState());
+ }
- serializer.startTag(null, TAG_PACKAGE);
- serializer.attribute(null, ATTR_NAME, pkg.getPackageName());
- if (ustate.getCeDataInode() != 0) {
- serializer.attributeLong(null, ATTR_CE_DATA_INODE, ustate.getCeDataInode());
- }
- if (!ustate.isInstalled()) {
- serializer.attributeBoolean(null, ATTR_INSTALLED, false);
- }
- if (ustate.isStopped()) {
- serializer.attributeBoolean(null, ATTR_STOPPED, true);
- }
- if (ustate.isNotLaunched()) {
- serializer.attributeBoolean(null, ATTR_NOT_LAUNCHED, true);
- }
- if (ustate.isHidden()) {
- serializer.attributeBoolean(null, ATTR_HIDDEN, true);
- }
- if (ustate.getDistractionFlags() != 0) {
- serializer.attributeInt(null, ATTR_DISTRACTION_FLAGS,
- ustate.getDistractionFlags());
- }
- if (ustate.isSuspended()) {
- serializer.attributeBoolean(null, ATTR_SUSPENDED, true);
- }
- if (ustate.isInstantApp()) {
- serializer.attributeBoolean(null, ATTR_INSTANT_APP, true);
- }
- if (ustate.isVirtualPreload()) {
- serializer.attributeBoolean(null, ATTR_VIRTUAL_PRELOAD, true);
- }
- if (ustate.getEnabledState() != COMPONENT_ENABLED_STATE_DEFAULT) {
- serializer.attributeInt(null, ATTR_ENABLED, ustate.getEnabledState());
- if (ustate.getLastDisableAppCaller() != null) {
- serializer.attribute(null, ATTR_ENABLED_CALLER,
- ustate.getLastDisableAppCaller());
+ serializer.startTag(null, TAG_PACKAGE);
+ serializer.attribute(null, ATTR_NAME, pkg.getPackageName());
+ if (ustate.getCeDataInode() != 0) {
+ serializer.attributeLong(null, ATTR_CE_DATA_INODE,
+ ustate.getCeDataInode());
}
- }
- if (ustate.getInstallReason() != PackageManager.INSTALL_REASON_UNKNOWN) {
- serializer.attributeInt(null, ATTR_INSTALL_REASON,
- ustate.getInstallReason());
- }
- serializer.attributeLongHex(null, ATTR_FIRST_INSTALL_TIME,
- ustate.getFirstInstallTimeMillis());
- if (ustate.getUninstallReason() != PackageManager.UNINSTALL_REASON_UNKNOWN) {
- serializer.attributeInt(null, ATTR_UNINSTALL_REASON,
- ustate.getUninstallReason());
- }
- if (ustate.getHarmfulAppWarning() != null) {
- serializer.attribute(null, ATTR_HARMFUL_APP_WARNING,
- ustate.getHarmfulAppWarning());
- }
- if (ustate.getSplashScreenTheme() != null) {
- serializer.attribute(null, ATTR_SPLASH_SCREEN_THEME,
- ustate.getSplashScreenTheme());
- }
- if (ustate.isSuspended()) {
- for (int i = 0; i < ustate.getSuspendParams().size(); i++) {
- final String suspendingPackage = ustate.getSuspendParams().keyAt(i);
- serializer.startTag(null, TAG_SUSPEND_PARAMS);
- serializer.attribute(null, ATTR_SUSPENDING_PACKAGE, suspendingPackage);
- final SuspendParams params =
- ustate.getSuspendParams().valueAt(i);
- if (params != null) {
- params.saveToXml(serializer);
+ if (!ustate.isInstalled()) {
+ serializer.attributeBoolean(null, ATTR_INSTALLED, false);
+ }
+ if (ustate.isStopped()) {
+ serializer.attributeBoolean(null, ATTR_STOPPED, true);
+ }
+ if (ustate.isNotLaunched()) {
+ serializer.attributeBoolean(null, ATTR_NOT_LAUNCHED, true);
+ }
+ if (ustate.isHidden()) {
+ serializer.attributeBoolean(null, ATTR_HIDDEN, true);
+ }
+ if (ustate.getDistractionFlags() != 0) {
+ serializer.attributeInt(null, ATTR_DISTRACTION_FLAGS,
+ ustate.getDistractionFlags());
+ }
+ if (ustate.isSuspended()) {
+ serializer.attributeBoolean(null, ATTR_SUSPENDED, true);
+ }
+ if (ustate.isInstantApp()) {
+ serializer.attributeBoolean(null, ATTR_INSTANT_APP, true);
+ }
+ if (ustate.isVirtualPreload()) {
+ serializer.attributeBoolean(null, ATTR_VIRTUAL_PRELOAD, true);
+ }
+ if (ustate.getEnabledState() != COMPONENT_ENABLED_STATE_DEFAULT) {
+ serializer.attributeInt(null, ATTR_ENABLED, ustate.getEnabledState());
+ if (ustate.getLastDisableAppCaller() != null) {
+ serializer.attribute(null, ATTR_ENABLED_CALLER,
+ ustate.getLastDisableAppCaller());
}
- serializer.endTag(null, TAG_SUSPEND_PARAMS);
}
- }
- final ArraySet<String> enabledComponents = ustate.getEnabledComponents();
- if (enabledComponents != null && enabledComponents.size() > 0) {
- serializer.startTag(null, TAG_ENABLED_COMPONENTS);
- for (int i = 0; i < enabledComponents.size(); i++) {
- serializer.startTag(null, TAG_ITEM);
- serializer.attribute(null, ATTR_NAME,
- enabledComponents.valueAt(i));
- serializer.endTag(null, TAG_ITEM);
+ if (ustate.getInstallReason() != PackageManager.INSTALL_REASON_UNKNOWN) {
+ serializer.attributeInt(null, ATTR_INSTALL_REASON,
+ ustate.getInstallReason());
}
- serializer.endTag(null, TAG_ENABLED_COMPONENTS);
- }
- final ArraySet<String> disabledComponents = ustate.getDisabledComponents();
- if (disabledComponents != null && disabledComponents.size() > 0) {
- serializer.startTag(null, TAG_DISABLED_COMPONENTS);
- for (int i = 0; i < disabledComponents.size(); i++) {
- serializer.startTag(null, TAG_ITEM);
- serializer.attribute(null, ATTR_NAME,
- disabledComponents.valueAt(i));
- serializer.endTag(null, TAG_ITEM);
+ serializer.attributeLongHex(null, ATTR_FIRST_INSTALL_TIME,
+ ustate.getFirstInstallTimeMillis());
+ if (ustate.getUninstallReason()
+ != PackageManager.UNINSTALL_REASON_UNKNOWN) {
+ serializer.attributeInt(null, ATTR_UNINSTALL_REASON,
+ ustate.getUninstallReason());
+ }
+ if (ustate.getHarmfulAppWarning() != null) {
+ serializer.attribute(null, ATTR_HARMFUL_APP_WARNING,
+ ustate.getHarmfulAppWarning());
+ }
+ if (ustate.getSplashScreenTheme() != null) {
+ serializer.attribute(null, ATTR_SPLASH_SCREEN_THEME,
+ ustate.getSplashScreenTheme());
+ }
+ if (ustate.isSuspended()) {
+ for (int i = 0; i < ustate.getSuspendParams().size(); i++) {
+ final String suspendingPackage = ustate.getSuspendParams().keyAt(i);
+ serializer.startTag(null, TAG_SUSPEND_PARAMS);
+ serializer.attribute(null, ATTR_SUSPENDING_PACKAGE,
+ suspendingPackage);
+ final SuspendParams params =
+ ustate.getSuspendParams().valueAt(i);
+ if (params != null) {
+ params.saveToXml(serializer);
+ }
+ serializer.endTag(null, TAG_SUSPEND_PARAMS);
+ }
+ }
+ final ArraySet<String> enabledComponents = ustate.getEnabledComponents();
+ if (enabledComponents != null && enabledComponents.size() > 0) {
+ serializer.startTag(null, TAG_ENABLED_COMPONENTS);
+ for (int i = 0; i < enabledComponents.size(); i++) {
+ serializer.startTag(null, TAG_ITEM);
+ serializer.attribute(null, ATTR_NAME,
+ enabledComponents.valueAt(i));
+ serializer.endTag(null, TAG_ITEM);
+ }
+ serializer.endTag(null, TAG_ENABLED_COMPONENTS);
+ }
+ final ArraySet<String> disabledComponents = ustate.getDisabledComponents();
+ if (disabledComponents != null && disabledComponents.size() > 0) {
+ serializer.startTag(null, TAG_DISABLED_COMPONENTS);
+ for (int i = 0; i < disabledComponents.size(); i++) {
+ serializer.startTag(null, TAG_ITEM);
+ serializer.attribute(null, ATTR_NAME,
+ disabledComponents.valueAt(i));
+ serializer.endTag(null, TAG_ITEM);
+ }
+ serializer.endTag(null, TAG_DISABLED_COMPONENTS);
}
- serializer.endTag(null, TAG_DISABLED_COMPONENTS);
- }
-
- serializer.endTag(null, TAG_PACKAGE);
- }
- writePreferredActivitiesLPr(serializer, userId, true);
- writePersistentPreferredActivitiesLPr(serializer, userId);
- writeCrossProfileIntentFiltersLPr(serializer, userId);
- writeDefaultAppsLPr(serializer, userId);
- writeBlockUninstallPackagesLPr(serializer, userId);
+ serializer.endTag(null, TAG_PACKAGE);
+ }
- serializer.endTag(null, TAG_PACKAGE_RESTRICTIONS);
+ writePreferredActivitiesLPr(serializer, userId, true);
+ writePersistentPreferredActivitiesLPr(serializer, userId);
+ writeCrossProfileIntentFiltersLPr(serializer, userId);
+ writeDefaultAppsLPr(serializer, userId);
+ writeBlockUninstallPackagesLPr(serializer, userId);
- serializer.endDocument();
- }
+ serializer.endTag(null, TAG_PACKAGE_RESTRICTIONS);
- fstr.flush();
- FileUtils.sync(fstr);
- IoUtils.closeQuietly(fstr);
+ serializer.endDocument();
+ }
- synchronized (mPackageRestrictionsLock) {
- // File is created, set permissions.
- FileUtils.setPermissions(userPackagesStateFile.toString(),
- FileUtils.S_IRUSR | FileUtils.S_IWUSR
- | FileUtils.S_IRGRP | FileUtils.S_IWGRP,
- -1, -1);
- // New settings successfully written, old ones are no longer needed.
- backupFile.delete();
- }
+ atomicFile.finishWrite(str);
- if (DEBUG_MU) {
- Log.i(TAG, "New settings successfully written for user=" + userId + ": "
- + userPackagesStateFile);
- }
+ if (DEBUG_MU) {
+ Log.i(TAG, "New package restrictions successfully written for user=" + userId
+ + ": " + atomicFile);
+ }
- com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
- "package-user-" + userId, SystemClock.uptimeMillis() - startTime);
+ com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
+ "package-user-" + userId, SystemClock.uptimeMillis() - startTime);
- // Done, all is good!
- return;
- } catch (java.io.IOException e) {
- Slog.wtf(PackageManagerService.TAG,
- "Unable to write package manager user packages state, "
- + " current changes will be lost at reboot", e);
- }
-
- // Clean up partially written files
- if (userPackagesStateFile.exists()) {
- if (!userPackagesStateFile.delete()) {
- Log.i(PackageManagerService.TAG, "Failed to clean up mangled file: "
- + mStoppedPackagesFilename);
+ // Done, all is good!
+ return;
+ } catch (java.io.IOException e) {
+ Slog.wtf(PackageManagerService.TAG,
+ "Unable to write package manager package restrictions, "
+ + " current changes will be lost at reboot", e);
+ if (str != null) {
+ atomicFile.failWrite(str);
+ }
}
}
}
@@ -2589,153 +2522,108 @@ public final class Settings implements Watchable, Snappable {
// right time.
invalidatePackageCache();
- // Keep the old settings around until we know the new ones have
- // been successfully written.
- if (mSettingsFilename.exists()) {
- // Presence of backup settings file indicates that we failed
- // to persist settings earlier. So preserve the older
- // backup for future reference since the current settings
- // might have been corrupted.
- if (!mPreviousSettingsFilename.exists()) {
- if (!mSettingsFilename.renameTo(mPreviousSettingsFilename)) {
- Slog.wtf(PackageManagerService.TAG,
- "Unable to store older package manager settings, "
- + " current changes will be lost at reboot");
- return;
- }
- } else {
- mSettingsFilename.delete();
- Slog.w(PackageManagerService.TAG, "Preserving older settings backup");
- }
- }
-
mPastSignatures.clear();
- try {
- final FileOutputStream fstr = new FileOutputStream(mSettingsFilename);
- final TypedXmlSerializer serializer = Xml.resolveSerializer(fstr);
- serializer.startDocument(null, true);
- serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
-
- serializer.startTag(null, "packages");
-
- for (int i = 0; i < mVersion.size(); i++) {
- final String volumeUuid = mVersion.keyAt(i);
- final VersionInfo ver = mVersion.valueAt(i);
-
- serializer.startTag(null, TAG_VERSION);
- XmlUtils.writeStringAttribute(serializer, ATTR_VOLUME_UUID, volumeUuid);
- serializer.attributeInt(null, ATTR_SDK_VERSION, ver.sdkVersion);
- serializer.attributeInt(null, ATTR_DATABASE_VERSION, ver.databaseVersion);
- XmlUtils.writeStringAttribute(serializer, ATTR_BUILD_FINGERPRINT,
- ver.buildFingerprint);
- XmlUtils.writeStringAttribute(serializer, ATTR_FINGERPRINT, ver.fingerprint);
- serializer.endTag(null, TAG_VERSION);
- }
+ try (ResilientAtomicFile atomicFile = getSettingsFile()) {
+ FileOutputStream str = null;
+ try {
+ str = atomicFile.startWrite();
- if (mVerifierDeviceIdentity != null) {
- serializer.startTag(null, "verifier");
- serializer.attribute(null, "device", mVerifierDeviceIdentity.toString());
- serializer.endTag(null, "verifier");
- }
+ final TypedXmlSerializer serializer = Xml.resolveSerializer(str);
+ serializer.startDocument(null, true);
+ serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output",
+ true);
- serializer.startTag(null, "permission-trees");
- mPermissions.writePermissionTrees(serializer);
- serializer.endTag(null, "permission-trees");
+ serializer.startTag(null, "packages");
- serializer.startTag(null, "permissions");
- mPermissions.writePermissions(serializer);
- serializer.endTag(null, "permissions");
+ for (int i = 0; i < mVersion.size(); i++) {
+ final String volumeUuid = mVersion.keyAt(i);
+ final VersionInfo ver = mVersion.valueAt(i);
- for (final PackageSetting pkg : mPackages.values()) {
- if (pkg.getPkg() != null && pkg.getPkg().isApex()) {
- // Don't persist APEX which doesn't have a valid app id and will fail to load
- continue;
+ serializer.startTag(null, TAG_VERSION);
+ XmlUtils.writeStringAttribute(serializer, ATTR_VOLUME_UUID, volumeUuid);
+ serializer.attributeInt(null, ATTR_SDK_VERSION, ver.sdkVersion);
+ serializer.attributeInt(null, ATTR_DATABASE_VERSION, ver.databaseVersion);
+ XmlUtils.writeStringAttribute(serializer, ATTR_BUILD_FINGERPRINT,
+ ver.buildFingerprint);
+ XmlUtils.writeStringAttribute(serializer, ATTR_FINGERPRINT, ver.fingerprint);
+ serializer.endTag(null, TAG_VERSION);
}
- writePackageLPr(serializer, pkg);
- }
- for (final PackageSetting pkg : mDisabledSysPackages.values()) {
- if (pkg.getPkg() != null && pkg.getPkg().isApex()) {
- // Don't persist APEX which doesn't have a valid app id and will fail to load
- continue;
+ if (mVerifierDeviceIdentity != null) {
+ serializer.startTag(null, "verifier");
+ serializer.attribute(null, "device", mVerifierDeviceIdentity.toString());
+ serializer.endTag(null, "verifier");
}
- writeDisabledSysPackageLPr(serializer, pkg);
- }
- for (final SharedUserSetting usr : mSharedUsers.values()) {
- serializer.startTag(null, "shared-user");
- serializer.attribute(null, ATTR_NAME, usr.name);
- serializer.attributeInt(null, "userId", usr.mAppId);
- usr.signatures.writeXml(serializer, "sigs", mPastSignatures.untrackedStorage());
- serializer.endTag(null, "shared-user");
- }
+ serializer.startTag(null, "permission-trees");
+ mPermissions.writePermissionTrees(serializer);
+ serializer.endTag(null, "permission-trees");
- if (mRenamedPackages.size() > 0) {
- for (Map.Entry<String, String> e : mRenamedPackages.entrySet()) {
- serializer.startTag(null, "renamed-package");
- serializer.attribute(null, "new", e.getKey());
- serializer.attribute(null, "old", e.getValue());
- serializer.endTag(null, "renamed-package");
+ serializer.startTag(null, "permissions");
+ mPermissions.writePermissions(serializer);
+ serializer.endTag(null, "permissions");
+
+ for (final PackageSetting pkg : mPackages.values()) {
+ if (pkg.getPkg() != null && pkg.getPkg().isApex()) {
+ // Don't persist APEX which doesn't have a valid app id and will fail to
+ // load
+ continue;
+ }
+ writePackageLPr(serializer, pkg);
}
- }
- mDomainVerificationManager.writeSettings(computer, serializer,
- false /* includeSignatures */, UserHandle.USER_ALL);
+ for (final PackageSetting pkg : mDisabledSysPackages.values()) {
+ if (pkg.getPkg() != null && pkg.getPkg().isApex()) {
+ // Don't persist APEX which doesn't have a valid app id and will fail to
+ // load
+ continue;
+ }
+ writeDisabledSysPackageLPr(serializer, pkg);
+ }
- mKeySetManagerService.writeKeySetManagerServiceLPr(serializer);
+ for (final SharedUserSetting usr : mSharedUsers.values()) {
+ serializer.startTag(null, "shared-user");
+ serializer.attribute(null, ATTR_NAME, usr.name);
+ serializer.attributeInt(null, "userId", usr.mAppId);
+ usr.signatures.writeXml(serializer, "sigs", mPastSignatures.untrackedStorage());
+ serializer.endTag(null, "shared-user");
+ }
- serializer.endTag(null, "packages");
+ if (mRenamedPackages.size() > 0) {
+ for (Map.Entry<String, String> e : mRenamedPackages.entrySet()) {
+ serializer.startTag(null, "renamed-package");
+ serializer.attribute(null, "new", e.getKey());
+ serializer.attribute(null, "old", e.getValue());
+ serializer.endTag(null, "renamed-package");
+ }
+ }
- serializer.endDocument();
+ mDomainVerificationManager.writeSettings(computer, serializer,
+ false /* includeSignatures */, UserHandle.USER_ALL);
- fstr.flush();
- FileUtils.sync(fstr);
- fstr.close();
+ mKeySetManagerService.writeKeySetManagerServiceLPr(serializer);
- // New settings successfully written, old ones are no longer needed.
- mPreviousSettingsFilename.delete();
- mSettingsReserveCopyFilename.delete();
+ serializer.endTag(null, "packages");
- FileUtils.setPermissions(mSettingsFilename.toString(),
- FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IRGRP | FileUtils.S_IWGRP,
- -1, -1);
+ serializer.endDocument();
- try (FileInputStream in = new FileInputStream(mSettingsFilename);
- FileOutputStream out = new FileOutputStream(mSettingsReserveCopyFilename)) {
- FileUtils.copy(in, out);
- out.flush();
- FileUtils.sync(out);
- } catch (IOException e) {
- Slog.e(TAG,
- "Failed to write reserve copy of settings: " + mSettingsReserveCopyFilename,
- e);
- }
+ atomicFile.finishWrite(str);
- try {
- FileIntegrity.setUpFsVerity(mSettingsFilename);
- FileIntegrity.setUpFsVerity(mSettingsReserveCopyFilename);
- } catch (IOException e) {
- Slog.e(TAG, "Failed to verity-protect settings", e);
- }
-
- writeKernelMappingLPr();
- writePackageListLPr();
- writeAllUsersPackageRestrictionsLPr(sync);
- writeAllRuntimePermissionsLPr();
- com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
- "package", SystemClock.uptimeMillis() - startTime);
- return;
+ writeKernelMappingLPr();
+ writePackageListLPr();
+ writeAllUsersPackageRestrictionsLPr(sync);
+ writeAllRuntimePermissionsLPr();
+ com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
+ "package", SystemClock.uptimeMillis() - startTime);
+ return;
- } catch(java.io.IOException e) {
- Slog.wtf(PackageManagerService.TAG, "Unable to write package manager settings, "
- + "current changes will be lost at reboot", e);
- }
- // Clean up partially written files
- if (mSettingsFilename.exists()) {
- if (!mSettingsFilename.delete()) {
- Slog.wtf(PackageManagerService.TAG, "Failed to clean up mangled file: "
- + mSettingsFilename);
+ } catch (java.io.IOException e) {
+ Slog.wtf(PackageManagerService.TAG, "Unable to write package manager settings, "
+ + "current changes will be lost at reboot", e);
+ if (str != null) {
+ atomicFile.failWrite(str);
+ }
}
}
//Debug.stopMethodTracing();
@@ -3160,183 +3048,140 @@ public final class Settings implements Watchable, Snappable {
mInstallerPackages.clear();
originalFirstInstallTimes.clear();
- File file = null;
- FileInputStream str = null;
-
- try {
- // Check if the previous write was incomplete.
- if (mPreviousSettingsFilename.exists()) {
- try {
- file = mPreviousSettingsFilename;
- str = new FileInputStream(file);
- mReadMessages.append("Reading from backup settings file\n");
- PackageManagerService.reportSettingsProblem(Log.INFO,
- "Need to read from backup settings file");
- if (mSettingsFilename.exists()) {
- // If both the previous and current settings files exist,
- // we ignore the current since it might have been corrupted.
- Slog.w(PackageManagerService.TAG, "Cleaning up settings file "
- + mSettingsFilename);
- mSettingsFilename.delete();
- }
- // Ignore reserve copy as well.
- mSettingsReserveCopyFilename.delete();
- } catch (java.io.IOException e) {
- // We'll try for the normal settings file.
- }
- }
- if (str == null) {
- if (mSettingsFilename.exists()) {
- // Using packages.xml.
- file = mSettingsFilename;
- str = new FileInputStream(file);
- } else if (mSettingsReserveCopyFilename.exists()) {
- // Using reserve copy.
- file = mSettingsReserveCopyFilename;
- str = new FileInputStream(file);
- mReadMessages.append("Reading from reserve copy settings file\n");
- PackageManagerService.reportSettingsProblem(Log.INFO,
- "Need to read from reserve copy settings file");
+ try (ResilientAtomicFile atomicFile = getSettingsFile()) {
+ FileInputStream str = null;
+ try {
+ str = atomicFile.openRead();
+ if (str == null) {
+ // Not necessary, but will avoid wtf-s in the "finally" section.
+ findOrCreateVersion(StorageManager.UUID_PRIVATE_INTERNAL).forceCurrent();
+ findOrCreateVersion(StorageManager.UUID_PRIMARY_PHYSICAL).forceCurrent();
+ return false;
}
- }
- if (str == null) {
- // No available data sources.
- mReadMessages.append("No settings file found\n");
- PackageManagerService.reportSettingsProblem(Log.INFO,
- "No settings file; creating initial state");
- // Not necessary, but will avoid wtf-s in the "finally" section.
- findOrCreateVersion(StorageManager.UUID_PRIVATE_INTERNAL).forceCurrent();
- findOrCreateVersion(StorageManager.UUID_PRIMARY_PHYSICAL).forceCurrent();
- return false;
- }
- final TypedXmlPullParser parser = Xml.resolvePullParser(str);
+ final TypedXmlPullParser parser = Xml.resolvePullParser(str);
- int type;
- while ((type = parser.next()) != XmlPullParser.START_TAG
- && type != XmlPullParser.END_DOCUMENT) {
- ;
- }
-
- if (type != XmlPullParser.START_TAG) {
- mReadMessages.append("No start tag found in settings file\n");
- PackageManagerService.reportSettingsProblem(Log.WARN,
- "No start tag found in package manager settings");
- Slog.wtf(PackageManagerService.TAG,
- "No start tag found in package manager settings");
- return false;
- }
+ int type;
+ while ((type = parser.next()) != XmlPullParser.START_TAG
+ && type != XmlPullParser.END_DOCUMENT) {
+ // nothing
+ }
- int outerDepth = parser.getDepth();
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
- if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
- continue;
+ if (type != XmlPullParser.START_TAG) {
+ mReadMessages.append("No start tag found in settings file\n");
+ PackageManagerService.reportSettingsProblem(Log.WARN,
+ "No start tag found in package manager settings");
+ Slog.wtf(PackageManagerService.TAG,
+ "No start tag found in package manager settings");
+ return false;
}
- String tagName = parser.getName();
- if (tagName.equals("package")) {
- readPackageLPw(parser, users, originalFirstInstallTimes);
- } else if (tagName.equals("permissions")) {
- mPermissions.readPermissions(parser);
- } else if (tagName.equals("permission-trees")) {
- mPermissions.readPermissionTrees(parser);
- } else if (tagName.equals("shared-user")) {
- readSharedUserLPw(parser, users);
- } else if (tagName.equals("preferred-packages")) {
- // no longer used.
- } else if (tagName.equals("preferred-activities")) {
- // Upgrading from old single-user implementation;
- // these are the preferred activities for user 0.
- readPreferredActivitiesLPw(parser, 0);
- } else if (tagName.equals(TAG_PERSISTENT_PREFERRED_ACTIVITIES)) {
- // TODO: check whether this is okay! as it is very
- // similar to how preferred-activities are treated
- readPersistentPreferredActivitiesLPw(parser, 0);
- } else if (tagName.equals(TAG_CROSS_PROFILE_INTENT_FILTERS)) {
- // TODO: check whether this is okay! as it is very
- // similar to how preferred-activities are treated
- readCrossProfileIntentFiltersLPw(parser, 0);
- } else if (tagName.equals(TAG_DEFAULT_BROWSER)) {
- readDefaultAppsLPw(parser, 0);
- } else if (tagName.equals("updated-package")) {
- readDisabledSysPackageLPw(parser, users);
- } else if (tagName.equals("renamed-package")) {
- String nname = parser.getAttributeValue(null, "new");
- String oname = parser.getAttributeValue(null, "old");
- if (nname != null && oname != null) {
- mRenamedPackages.put(nname, oname);
+ int outerDepth = parser.getDepth();
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+ continue;
}
- } else if (tagName.equals("last-platform-version")) {
- // Upgrade from older XML schema
- final VersionInfo internal = findOrCreateVersion(
- StorageManager.UUID_PRIVATE_INTERNAL);
- final VersionInfo external = findOrCreateVersion(
- StorageManager.UUID_PRIMARY_PHYSICAL);
-
- internal.sdkVersion = parser.getAttributeInt(null, "internal", 0);
- external.sdkVersion = parser.getAttributeInt(null, "external", 0);
- internal.buildFingerprint = external.buildFingerprint =
- XmlUtils.readStringAttribute(parser, "buildFingerprint");
- internal.fingerprint = external.fingerprint =
- XmlUtils.readStringAttribute(parser, "fingerprint");
-
- } else if (tagName.equals("database-version")) {
- // Upgrade from older XML schema
- final VersionInfo internal = findOrCreateVersion(
- StorageManager.UUID_PRIVATE_INTERNAL);
- final VersionInfo external = findOrCreateVersion(
- StorageManager.UUID_PRIMARY_PHYSICAL);
-
- internal.databaseVersion = parser.getAttributeInt(null, "internal", 0);
- external.databaseVersion = parser.getAttributeInt(null, "external", 0);
-
- } else if (tagName.equals("verifier")) {
- final String deviceIdentity = parser.getAttributeValue(null, "device");
- try {
- mVerifierDeviceIdentity = VerifierDeviceIdentity.parse(deviceIdentity);
- } catch (IllegalArgumentException e) {
- Slog.w(PackageManagerService.TAG, "Discard invalid verifier device id: "
- + e.getMessage());
+
+ String tagName = parser.getName();
+ if (tagName.equals("package")) {
+ readPackageLPw(parser, users, originalFirstInstallTimes);
+ } else if (tagName.equals("permissions")) {
+ mPermissions.readPermissions(parser);
+ } else if (tagName.equals("permission-trees")) {
+ mPermissions.readPermissionTrees(parser);
+ } else if (tagName.equals("shared-user")) {
+ readSharedUserLPw(parser, users);
+ } else if (tagName.equals("preferred-packages")) {
+ // no longer used.
+ } else if (tagName.equals("preferred-activities")) {
+ // Upgrading from old single-user implementation;
+ // these are the preferred activities for user 0.
+ readPreferredActivitiesLPw(parser, 0);
+ } else if (tagName.equals(TAG_PERSISTENT_PREFERRED_ACTIVITIES)) {
+ // TODO: check whether this is okay! as it is very
+ // similar to how preferred-activities are treated
+ readPersistentPreferredActivitiesLPw(parser, 0);
+ } else if (tagName.equals(TAG_CROSS_PROFILE_INTENT_FILTERS)) {
+ // TODO: check whether this is okay! as it is very
+ // similar to how preferred-activities are treated
+ readCrossProfileIntentFiltersLPw(parser, 0);
+ } else if (tagName.equals(TAG_DEFAULT_BROWSER)) {
+ readDefaultAppsLPw(parser, 0);
+ } else if (tagName.equals("updated-package")) {
+ readDisabledSysPackageLPw(parser, users);
+ } else if (tagName.equals("renamed-package")) {
+ String nname = parser.getAttributeValue(null, "new");
+ String oname = parser.getAttributeValue(null, "old");
+ if (nname != null && oname != null) {
+ mRenamedPackages.put(nname, oname);
+ }
+ } else if (tagName.equals("last-platform-version")) {
+ // Upgrade from older XML schema
+ final VersionInfo internal = findOrCreateVersion(
+ StorageManager.UUID_PRIVATE_INTERNAL);
+ final VersionInfo external = findOrCreateVersion(
+ StorageManager.UUID_PRIMARY_PHYSICAL);
+
+ internal.sdkVersion = parser.getAttributeInt(null, "internal", 0);
+ external.sdkVersion = parser.getAttributeInt(null, "external", 0);
+ internal.buildFingerprint = external.buildFingerprint =
+ XmlUtils.readStringAttribute(parser, "buildFingerprint");
+ internal.fingerprint = external.fingerprint =
+ XmlUtils.readStringAttribute(parser, "fingerprint");
+
+ } else if (tagName.equals("database-version")) {
+ // Upgrade from older XML schema
+ final VersionInfo internal = findOrCreateVersion(
+ StorageManager.UUID_PRIVATE_INTERNAL);
+ final VersionInfo external = findOrCreateVersion(
+ StorageManager.UUID_PRIMARY_PHYSICAL);
+
+ internal.databaseVersion = parser.getAttributeInt(null, "internal", 0);
+ external.databaseVersion = parser.getAttributeInt(null, "external", 0);
+
+ } else if (tagName.equals("verifier")) {
+ final String deviceIdentity = parser.getAttributeValue(null, "device");
+ try {
+ mVerifierDeviceIdentity = VerifierDeviceIdentity.parse(deviceIdentity);
+ } catch (IllegalArgumentException e) {
+ Slog.w(PackageManagerService.TAG, "Discard invalid verifier device id: "
+ + e.getMessage());
+ }
+ } else if (TAG_READ_EXTERNAL_STORAGE.equals(tagName)) {
+ // No longer used.
+ } else if (tagName.equals("keyset-settings")) {
+ mKeySetManagerService.readKeySetsLPw(parser,
+ mKeySetRefs.untrackedStorage());
+ } else if (TAG_VERSION.equals(tagName)) {
+ final String volumeUuid = XmlUtils.readStringAttribute(parser,
+ ATTR_VOLUME_UUID);
+ final VersionInfo ver = findOrCreateVersion(volumeUuid);
+ ver.sdkVersion = parser.getAttributeInt(null, ATTR_SDK_VERSION);
+ ver.databaseVersion = parser.getAttributeInt(null, ATTR_DATABASE_VERSION);
+ ver.buildFingerprint = XmlUtils.readStringAttribute(parser,
+ ATTR_BUILD_FINGERPRINT);
+ ver.fingerprint = XmlUtils.readStringAttribute(parser, ATTR_FINGERPRINT);
+ } else if (tagName.equals(
+ DomainVerificationPersistence.TAG_DOMAIN_VERIFICATIONS)) {
+ mDomainVerificationManager.readSettings(computer, parser);
+ } else if (tagName.equals(
+ DomainVerificationLegacySettings.TAG_DOMAIN_VERIFICATIONS_LEGACY)) {
+ mDomainVerificationManager.readLegacySettings(parser);
+ } else {
+ Slog.w(PackageManagerService.TAG, "Unknown element under <packages>: "
+ + parser.getName());
+ XmlUtils.skipCurrentTag(parser);
}
- } else if (TAG_READ_EXTERNAL_STORAGE.equals(tagName)) {
- // No longer used.
- } else if (tagName.equals("keyset-settings")) {
- mKeySetManagerService.readKeySetsLPw(parser, mKeySetRefs.untrackedStorage());
- } else if (TAG_VERSION.equals(tagName)) {
- final String volumeUuid = XmlUtils.readStringAttribute(parser,
- ATTR_VOLUME_UUID);
- final VersionInfo ver = findOrCreateVersion(volumeUuid);
- ver.sdkVersion = parser.getAttributeInt(null, ATTR_SDK_VERSION);
- ver.databaseVersion = parser.getAttributeInt(null, ATTR_DATABASE_VERSION);
- ver.buildFingerprint = XmlUtils.readStringAttribute(parser,
- ATTR_BUILD_FINGERPRINT);
- ver.fingerprint = XmlUtils.readStringAttribute(parser, ATTR_FINGERPRINT);
- } else if (tagName.equals(DomainVerificationPersistence.TAG_DOMAIN_VERIFICATIONS)) {
- mDomainVerificationManager.readSettings(computer, parser);
- } else if (tagName.equals(
- DomainVerificationLegacySettings.TAG_DOMAIN_VERIFICATIONS_LEGACY)) {
- mDomainVerificationManager.readLegacySettings(parser);
- } else {
- Slog.w(PackageManagerService.TAG, "Unknown element under <packages>: "
- + parser.getName());
- XmlUtils.skipCurrentTag(parser);
}
- }
- str.close();
- } catch (IOException | XmlPullParserException e) {
- mReadMessages.append("Error reading: " + e.toString());
- PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
- Slog.wtf(PackageManagerService.TAG, "Error reading package manager settings", e);
+ str.close();
+ } catch (IOException | XmlPullParserException e) {
+ // Remove corrupted file and retry.
+ atomicFile.failRead(str, e);
- // Remove corrupted file and retry.
- Slog.e(TAG,
- "Error reading package manager settings, removing " + file + " and retrying.",
- e);
- file.delete();
-
- // Ignore the result to not mark this as a "first boot".
- readSettingsLPw(computer, users, originalFirstInstallTimes);
+ // Ignore the result to not mark this as a "first boot".
+ readSettingsLPw(computer, users, originalFirstInstallTimes);
+ }
}
return true;
@@ -4488,10 +4333,7 @@ public final class Settings implements Watchable, Snappable {
mPreferredActivities.remove(userId);
synchronized (mPackageRestrictionsLock) {
- File file = getUserPackagesStateFile(userId);
- file.delete();
- file = getUserPackagesStateBackupFile(userId);
- file.delete();
+ getUserPackagesStateFile(userId).delete();
mPendingAsyncPackageRestrictionsWrites.delete(userId);
}
@@ -5034,19 +4876,20 @@ public final class Settings implements Watchable, Snappable {
}
}
pw.print(prefix); pw.print(" timeStamp=");
- date.setTime(ps.getLastModifiedTime());
- pw.println(sdf.format(date));
+ date.setTime(ps.getLastModifiedTime());
+ pw.println(sdf.format(date));
pw.print(prefix); pw.print(" lastUpdateTime=");
- date.setTime(ps.getLastUpdateTime());
- pw.println(sdf.format(date));
- if (ps.getInstallSource().mInstallerPackageName != null) {
- pw.print(prefix); pw.print(" installerPackageName=");
- pw.println(ps.getInstallSource().mInstallerPackageName);
- }
- if (ps.getInstallSource().mInstallerPackageUid != INVALID_UID) {
- pw.print(prefix); pw.print(" installerPackageUid=");
- pw.println(ps.getInstallSource().mInstallerPackageUid);
- }
+ date.setTime(ps.getLastUpdateTime());
+ pw.println(sdf.format(date));
+ pw.print(prefix); pw.print(" installerPackageName=");
+ pw.println(ps.getInstallSource().mInstallerPackageName);
+ pw.print(prefix); pw.print(" installerPackageUid=");
+ pw.println(ps.getInstallSource().mInstallerPackageUid);
+ pw.print(prefix); pw.print(" initiatingPackageName=");
+ pw.println(ps.getInstallSource().mInitiatingPackageName);
+ pw.print(prefix); pw.print(" originatingPackageName=");
+ pw.println(ps.getInstallSource().mOriginatingPackageName);
+
if (ps.getInstallSource().mUpdateOwnerPackageName != null) {
pw.print(prefix); pw.print(" updateOwnerPackageName=");
pw.println(ps.getInstallSource().mUpdateOwnerPackageName);
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 6d5e2b00aa78..28cb7f0b03a6 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -430,6 +430,7 @@ class ShortcutPackage extends ShortcutPackageItem {
@NonNull List<ShortcutInfo> changedShortcuts) {
Preconditions.checkArgument(newShortcut.isEnabled(),
"pushDynamicShortcuts() cannot publish disabled shortcuts");
+ ensureShortcutCountBeforePush();
newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
@@ -437,7 +438,7 @@ class ShortcutPackage extends ShortcutPackageItem {
final ShortcutInfo oldShortcut = findShortcutById(newShortcut.getId());
boolean deleted = false;
- if (oldShortcut == null) {
+ if (oldShortcut == null || !oldShortcut.isDynamic()) {
final ShortcutService service = mShortcutUser.mService;
final int maxShortcuts = service.getMaxActivityShortcuts();
@@ -446,18 +447,12 @@ class ShortcutPackage extends ShortcutPackageItem {
final ArrayList<ShortcutInfo> activityShortcuts = all.get(newShortcut.getActivity());
if (activityShortcuts != null && activityShortcuts.size() > maxShortcuts) {
- Slog.e(TAG, "Error pushing shortcut. There are already "
- + activityShortcuts.size() + " shortcuts, exceeding the " + maxShortcuts
- + " shortcuts limit when pushing the new shortcut " + newShortcut
- + ". Id of shortcuts currently available in system memory are "
- + activityShortcuts.stream().map(ShortcutInfo::getId)
- .collect(Collectors.joining(",", "[", "]")));
- // TODO: This should not have happened. If it does, identify the root cause where
- // possible, otherwise bail-out early to prevent memory issue.
+ // Root cause was discovered in b/233155034, so this should not be happening.
+ service.wtf("Error pushing shortcut. There are already "
+ + activityShortcuts.size() + " shortcuts.");
}
if (activityShortcuts != null && activityShortcuts.size() == maxShortcuts) {
// Max has reached. Delete the shortcut with lowest rank.
-
// Sort by isManifestShortcut() and getRank().
Collections.sort(activityShortcuts, mShortcutTypeAndRankComparator);
@@ -473,7 +468,8 @@ class ShortcutPackage extends ShortcutPackageItem {
deleted = deleteDynamicWithId(shortcut.getId(), /* ignoreInvisible =*/ true,
/*ignorePersistedShortcuts=*/ true) != null;
}
- } else {
+ }
+ if (oldShortcut != null) {
// It's an update case.
// Make sure the target is updatable. (i.e. should be mutable.)
oldShortcut.ensureUpdatableWith(newShortcut, /*isUpdating=*/ false);
@@ -505,6 +501,32 @@ class ShortcutPackage extends ShortcutPackageItem {
return deleted;
}
+ private void ensureShortcutCountBeforePush() {
+ final ShortcutService service = mShortcutUser.mService;
+ // Ensure the total number of shortcuts doesn't exceed the hard limit per app.
+ final int maxShortcutPerApp = service.getMaxAppShortcuts();
+ synchronized (mLock) {
+ final List<ShortcutInfo> appShortcuts = mShortcuts.values().stream().filter(si ->
+ !si.isPinned()).collect(Collectors.toList());
+ if (appShortcuts.size() >= maxShortcutPerApp) {
+ // Max has reached. Removes shortcuts until they fall within the hard cap.
+ // Sort by isManifestShortcut(), isDynamic() and getLastChangedTimestamp().
+ Collections.sort(appShortcuts, mShortcutTypeRankAndTimeComparator);
+
+ while (appShortcuts.size() >= maxShortcutPerApp) {
+ final ShortcutInfo shortcut = appShortcuts.remove(appShortcuts.size() - 1);
+ if (shortcut.isDeclaredInManifest()) {
+ // All shortcuts are manifest shortcuts and cannot be removed.
+ throw new IllegalArgumentException(getPackageName() + " has published "
+ + appShortcuts.size() + " manifest shortcuts across different"
+ + " activities.");
+ }
+ forceDeleteShortcutInner(shortcut.getId());
+ }
+ }
+ }
+ }
+
/**
* Remove all shortcuts that aren't pinned, cached nor dynamic.
*
@@ -1371,6 +1393,61 @@ class ShortcutPackage extends ShortcutPackageItem {
};
/**
+ * To sort by isManifestShortcut(), isDynamic(), getRank() and
+ * getLastChangedTimestamp(). i.e. manifest shortcuts come before non-manifest shortcuts,
+ * dynamic shortcuts come before floating shortcuts, then sort by last changed timestamp.
+ *
+ * This is used to decide which shortcuts to remove when the total number of shortcuts retained
+ * for the app exceeds the limit defined in {@link ShortcutService#getMaxAppShortcuts()}.
+ *
+ * (Note the number of manifest shortcuts is always <= the max number, because if there are
+ * more, ShortcutParser would ignore the rest.)
+ */
+ final Comparator<ShortcutInfo> mShortcutTypeRankAndTimeComparator = (ShortcutInfo a,
+ ShortcutInfo b) -> {
+ if (a.isDeclaredInManifest() && !b.isDeclaredInManifest()) {
+ return -1;
+ }
+ if (!a.isDeclaredInManifest() && b.isDeclaredInManifest()) {
+ return 1;
+ }
+ if (a.isDynamic() && b.isDynamic()) {
+ return Integer.compare(a.getRank(), b.getRank());
+ }
+ if (a.isDynamic()) {
+ return -1;
+ }
+ if (b.isDynamic()) {
+ return 1;
+ }
+ if (a.isCached() && b.isCached()) {
+ // if both shortcuts are cached, prioritize shortcuts cached by people tile,
+ if (a.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)
+ && !b.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)) {
+ return -1;
+ } else if (!a.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)
+ && b.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)) {
+ return 1;
+ }
+ // followed by bubbles.
+ if (a.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)
+ && !b.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)) {
+ return -1;
+ } else if (!a.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)
+ && b.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)) {
+ return 1;
+ }
+ }
+ if (a.isCached()) {
+ return -1;
+ }
+ if (b.isCached()) {
+ return 1;
+ }
+ return Long.compare(b.getLastChangedTimestamp(), a.getLastChangedTimestamp());
+ };
+
+ /**
* Build a list of shortcuts for each target activity and return as a map. The result won't
* contain "floating" shortcuts because they don't belong on any activities.
*/
@@ -1971,6 +2048,9 @@ class ShortcutPackage extends ShortcutPackageItem {
shortcutUser.getUserId(), fromBackup);
// Don't use addShortcut(), we don't need to save the icon.
ret.mShortcuts.put(si.getId(), si);
+ } catch (IOException e) {
+ // Don't ignore IO exceptions.
+ throw e;
} catch (Exception e) {
// b/246540168 malformed shortcuts should be ignored
Slog.e(TAG, "Failed parsing shortcut.", e);
diff --git a/services/core/java/com/android/server/pm/ShortcutPackageItem.java b/services/core/java/com/android/server/pm/ShortcutPackageItem.java
index e20330d562f6..8b118da1cdbe 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackageItem.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackageItem.java
@@ -27,6 +27,7 @@ import android.util.Xml;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
import com.android.modules.utils.TypedXmlSerializer;
+import com.android.server.security.FileIntegrity;
import org.json.JSONException;
import org.json.JSONObject;
@@ -180,6 +181,12 @@ abstract class ShortcutPackageItem {
os.flush();
file.finishWrite(os);
+
+ try {
+ FileIntegrity.setUpFsVerity(path);
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to verity-protect " + path, e);
+ }
} catch (XmlPullParserException | IOException e) {
Slog.e(TAG, "Failed to write to file " + file.getBaseFile(), e);
file.failWrite(os);
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 1cd9ec6d8d10..20cb485434b0 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -121,8 +121,6 @@ import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.uri.UriGrantsManagerInternal;
-import libcore.io.IoUtils;
-
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -181,6 +179,9 @@ public class ShortcutService extends IShortcutService.Stub {
static final int DEFAULT_MAX_SHORTCUTS_PER_ACTIVITY = 15;
@VisibleForTesting
+ static final int DEFAULT_MAX_SHORTCUTS_PER_APP = 100;
+
+ @VisibleForTesting
static final int DEFAULT_MAX_ICON_DIMENSION_DP = 96;
@VisibleForTesting
@@ -207,6 +208,10 @@ public class ShortcutService extends IShortcutService.Stub {
@VisibleForTesting
static final String FILENAME_USER_PACKAGES = "shortcuts.xml";
+ @VisibleForTesting
+ static final String FILENAME_USER_PACKAGES_RESERVE_COPY =
+ FILENAME_USER_PACKAGES + ".reservecopy";
+
static final String DIRECTORY_BITMAPS = "bitmaps";
private static final String TAG_ROOT = "root";
@@ -257,6 +262,11 @@ public class ShortcutService extends IShortcutService.Stub {
String KEY_MAX_SHORTCUTS = "max_shortcuts";
/**
+ * Key name for the max shortcuts can be retained in system ram per app. (int)
+ */
+ String KEY_MAX_SHORTCUTS_PER_APP = "max_shortcuts_per_app";
+
+ /**
* Key name for icon compression quality, 0-100.
*/
String KEY_ICON_QUALITY = "icon_quality";
@@ -329,11 +339,16 @@ public class ShortcutService extends IShortcutService.Stub {
new SparseArray<>();
/**
- * Max number of dynamic + manifest shortcuts that each application can have at a time.
+ * Max number of dynamic + manifest shortcuts that each activity can have at a time.
*/
private int mMaxShortcuts;
/**
+ * Max number of shortcuts that can exists in system ram for each application.
+ */
+ private int mMaxShortcutsPerApp;
+
+ /**
* Max number of updating API calls that each application can make during the interval.
*/
int mMaxUpdatesPerInterval;
@@ -807,6 +822,9 @@ public class ShortcutService extends IShortcutService.Stub {
mMaxShortcuts = Math.max(0, (int) parser.getLong(
ConfigConstants.KEY_MAX_SHORTCUTS, DEFAULT_MAX_SHORTCUTS_PER_ACTIVITY));
+ mMaxShortcutsPerApp = Math.max(0, (int) parser.getLong(
+ ConfigConstants.KEY_MAX_SHORTCUTS_PER_APP, DEFAULT_MAX_SHORTCUTS_PER_APP));
+
final int iconDimensionDp = Math.max(1, injectIsLowRamDevice()
? (int) parser.getLong(
ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM,
@@ -1051,32 +1069,38 @@ public class ShortcutService extends IShortcutService.Stub {
}
@VisibleForTesting
- final File getUserFile(@UserIdInt int userId) {
- return new File(injectUserDataPath(userId), FILENAME_USER_PACKAGES);
+ final ResilientAtomicFile getUserFile(@UserIdInt int userId) {
+ File mainFile = new File(injectUserDataPath(userId), FILENAME_USER_PACKAGES);
+ File temporaryBackup = new File(injectUserDataPath(userId),
+ FILENAME_USER_PACKAGES + ".backup");
+ File reserveCopy = new File(injectUserDataPath(userId),
+ FILENAME_USER_PACKAGES_RESERVE_COPY);
+ int fileMode = FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IXOTH;
+ return new ResilientAtomicFile(mainFile, temporaryBackup, reserveCopy, fileMode,
+ "user shortcut", null);
}
@GuardedBy("mLock")
private void saveUserLocked(@UserIdInt int userId) {
- final File path = getUserFile(userId);
- if (DEBUG || DEBUG_REBOOT) {
- Slog.d(TAG, "Saving to " + path);
- }
+ try (ResilientAtomicFile file = getUserFile(userId)) {
+ FileOutputStream os = null;
+ try {
+ if (DEBUG || DEBUG_REBOOT) {
+ Slog.d(TAG, "Saving to " + file);
+ }
- path.getParentFile().mkdirs();
- final AtomicFile file = new AtomicFile(path);
- FileOutputStream os = null;
- try {
- os = file.startWrite();
+ os = file.startWrite();
- saveUserInternalLocked(userId, os, /* forBackup= */ false);
+ saveUserInternalLocked(userId, os, /* forBackup= */ false);
- file.finishWrite(os);
+ file.finishWrite(os);
- // Remove all dangling bitmap files.
- cleanupDanglingBitmapDirectoriesLocked(userId);
- } catch (XmlPullParserException | IOException e) {
- Slog.e(TAG, "Failed to write to file " + file.getBaseFile(), e);
- file.failWrite(os);
+ // Remove all dangling bitmap files.
+ cleanupDanglingBitmapDirectoriesLocked(userId);
+ } catch (XmlPullParserException | IOException e) {
+ Slog.e(TAG, "Failed to write to file " + file, e);
+ file.failWrite(os);
+ }
}
getUserShortcutsLocked(userId).logSharingShortcutStats(mMetricsLogger);
@@ -1113,29 +1137,25 @@ public class ShortcutService extends IShortcutService.Stub {
@Nullable
private ShortcutUser loadUserLocked(@UserIdInt int userId) {
- final File path = getUserFile(userId);
- if (DEBUG || DEBUG_REBOOT) {
- Slog.d(TAG, "Loading from " + path);
- }
- final AtomicFile file = new AtomicFile(path);
-
- final FileInputStream in;
- try {
- in = file.openRead();
- } catch (FileNotFoundException e) {
- if (DEBUG || DEBUG_REBOOT) {
- Slog.d(TAG, "Not found " + path);
+ try (ResilientAtomicFile file = getUserFile(userId)) {
+ FileInputStream in = null;
+ try {
+ if (DEBUG || DEBUG_REBOOT) {
+ Slog.d(TAG, "Loading from " + file);
+ }
+ in = file.openRead();
+ if (in == null) {
+ if (DEBUG || DEBUG_REBOOT) {
+ Slog.d(TAG, "Not found " + file);
+ }
+ return null;
+ }
+ return loadUserInternal(userId, in, /* forBackup= */ false);
+ } catch (Exception e) {
+ // Remove corrupted file and retry.
+ file.failRead(in, e);
+ return loadUserLocked(userId);
}
- return null;
- }
- try {
- final ShortcutUser ret = loadUserInternal(userId, in, /* forBackup= */ false);
- return ret;
- } catch (IOException | XmlPullParserException | InvalidFileFormatException e) {
- Slog.e(TAG, "Failed to read file " + file.getBaseFile(), e);
- return null;
- } finally {
- IoUtils.closeQuietly(in);
}
}
@@ -1759,6 +1779,13 @@ public class ShortcutService extends IShortcutService.Stub {
}
/**
+ * Return the max number of shortcuts can be retaiend in system ram for each application.
+ */
+ int getMaxAppShortcuts() {
+ return mMaxShortcutsPerApp;
+ }
+
+ /**
* - Sends a notification to LauncherApps
* - Write to file
*/
diff --git a/services/core/java/com/android/server/pm/SuspendPackageHelper.java b/services/core/java/com/android/server/pm/SuspendPackageHelper.java
index 07d36b311aac..18eebe45a759 100644
--- a/services/core/java/com/android/server/pm/SuspendPackageHelper.java
+++ b/services/core/java/com/android/server/pm/SuspendPackageHelper.java
@@ -27,6 +27,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
+import android.app.AppOpsManager;
import android.app.IActivityManager;
import android.app.admin.DevicePolicyManagerInternal;
import android.content.Intent;
@@ -39,6 +40,7 @@ import android.os.PersistableBundle;
import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.DeviceConfig;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.IntArray;
@@ -63,6 +65,9 @@ import java.util.Set;
import java.util.function.Predicate;
public final class SuspendPackageHelper {
+
+ private static final String SYSTEM_EXEMPT_FROM_SUSPENSION = "system_exempt_from_suspension";
+
// TODO(b/198166813): remove PMS dependency
private final PackageManagerService mPm;
private final PackageManagerServiceInjector mInjector;
@@ -502,6 +507,10 @@ public final class SuspendPackageHelper {
final String requiredPermissionControllerPackage =
getKnownPackageName(snapshot, KnownPackages.PACKAGE_PERMISSION_CONTROLLER,
userId);
+ final AppOpsManager appOpsManager = mInjector.getSystemService(AppOpsManager.class);
+ final boolean isSystemExemptFlagEnabled = DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
+ SYSTEM_EXEMPT_FROM_SUSPENSION, /* defaultValue= */ true);
for (int i = 0; i < packageNames.length; i++) {
canSuspend[i] = false;
final String packageName = packageNames[i];
@@ -558,6 +567,7 @@ public final class SuspendPackageHelper {
PackageStateInternal packageState = snapshot.getPackageStateInternal(packageName);
AndroidPackage pkg = packageState == null ? null : packageState.getPkg();
if (pkg != null) {
+ final int uid = UserHandle.getUid(userId, packageState.getAppId());
// Cannot suspend SDK libs as they are controlled by SDK manager.
if (pkg.isSdkLibrary()) {
Slog.w(TAG, "Cannot suspend package: " + packageName
@@ -574,6 +584,13 @@ public final class SuspendPackageHelper {
+ pkg.getStaticSharedLibraryName());
continue;
}
+ if (isSystemExemptFlagEnabled && appOpsManager.checkOpNoThrow(
+ AppOpsManager.OP_SYSTEM_EXEMPT_FROM_SUSPENSION, uid, packageName)
+ == AppOpsManager.MODE_ALLOWED) {
+ Slog.w(TAG, "Cannot suspend package \"" + packageName
+ + "\": has OP_SYSTEM_EXEMPT_FROM_SUSPENSION set");
+ continue;
+ }
}
if (PLATFORM_PACKAGE_NAME.equals(packageName)) {
Slog.w(TAG, "Cannot suspend the platform package: " + packageName);
diff --git a/services/core/java/com/android/server/pm/UserManagerInternal.java b/services/core/java/com/android/server/pm/UserManagerInternal.java
index 9ef1bba16351..b4d467f96091 100644
--- a/services/core/java/com/android/server/pm/UserManagerInternal.java
+++ b/services/core/java/com/android/server/pm/UserManagerInternal.java
@@ -64,12 +64,11 @@ public abstract class UserManagerInternal {
})
public @interface UserAssignmentResult {}
- // TODO(b/248408342): Move keep annotation to the method referencing these fields reflectively.
- @Keep public static final int USER_START_MODE_FOREGROUND = 1;
- @Keep public static final int USER_START_MODE_BACKGROUND = 2;
- @Keep public static final int USER_START_MODE_BACKGROUND_VISIBLE = 3;
-
private static final String PREFIX_USER_START_MODE = "USER_START_MODE_";
+
+ /**
+ * Type used to indicate how a user started.
+ */
@IntDef(flag = false, prefix = {PREFIX_USER_START_MODE}, value = {
USER_START_MODE_FOREGROUND,
USER_START_MODE_BACKGROUND,
@@ -77,6 +76,32 @@ public abstract class UserManagerInternal {
})
public @interface UserStartMode {}
+ // TODO(b/248408342): Move keep annotations below to the method referencing these fields
+ // reflectively.
+
+ /** (Full) user started on foreground (a.k.a. "current user"). */
+ @Keep public static final int USER_START_MODE_FOREGROUND = 1;
+
+ /**
+ * User (full or profile) started on background and is
+ * {@link UserManager#isUserVisible() invisible}.
+ *
+ * <p>This is the "traditional" way of starting a background user, and can be used to start
+ * profiles as well, although starting an invisible profile is not common from the System UI
+ * (it could be done through APIs or adb, though).
+ */
+ @Keep public static final int USER_START_MODE_BACKGROUND = 2;
+
+ /**
+ * User (full or profile) started on background and is
+ * {@link UserManager#isUserVisible() visible}.
+ *
+ * <p>This is the "traditional" way of starting a profile (i.e., when the profile of the current
+ * user is the current foreground user), but it can also be used to start a full user associated
+ * with a display (which is the case on automotives with passenger displays).
+ */
+ @Keep public static final int USER_START_MODE_BACKGROUND_VISIBLE = 3;
+
public interface UserRestrictionsListener {
/**
* Called when a user restriction changes.
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index dd014ee637c7..2f98d3485d90 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -114,6 +114,7 @@ import android.util.TimeUtils;
import android.util.TypedValue;
import android.util.Xml;
+import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IAppOpsService;
@@ -2048,6 +2049,27 @@ public class UserManagerService extends IUserManager.Stub {
+ "permission to: check " + name);
}
+ /**
+ * Enforces that the calling user is in the same profile group as {@code userId} or that only
+ * the system UID or root's UID or apps that have the
+ * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} or
+ * {@link android.Manifest.permission#CREATE_USERS CREATE_USERS} or
+ * {@link android.Manifest.permission#QUERY_USERS QUERY_USERS}
+ * can make certain calls to the UserManager.
+ *
+ * @param userId the user's id
+ * @param name used as message if SecurityException is thrown
+ * @throws SecurityException if the caller lacks the required permissions.
+ */
+ private void checkQueryOrCreateUsersPermissionIfCallerInOtherProfileGroup(
+ @UserIdInt int userId, String name) {
+ final int callingUserId = UserHandle.getCallingUserId();
+ if (callingUserId == userId || isSameProfileGroupNoChecks(callingUserId, userId)) {
+ return;
+ }
+ checkQueryOrCreateUsersPermission(name);
+ }
+
@Override
public boolean isDemoUser(@UserIdInt int userId) {
final int callingUserId = UserHandle.getCallingUserId();
@@ -2062,6 +2084,15 @@ public class UserManagerService extends IUserManager.Stub {
}
@Override
+ public boolean isAdminUser(@UserIdInt int userId) {
+ checkQueryOrCreateUsersPermissionIfCallerInOtherProfileGroup(userId, "isAdminUser");
+ synchronized (mUsersLock) {
+ final UserInfo userInfo = getUserInfoLU(userId);
+ return userInfo != null && userInfo.isAdmin();
+ }
+ }
+
+ @Override
public boolean isPreCreated(@UserIdInt int userId) {
checkManageOrInteractPermissionIfCallerInOtherProfileGroup(userId, "isPreCreated");
synchronized (mUsersLock) {
@@ -3604,6 +3635,13 @@ public class UserManagerService extends IUserManager.Stub {
} finally {
IoUtils.closeQuietly(fis);
}
+
+ synchronized (mUsersLock) {
+ if (mUsers.size() == 0) {
+ Slog.e(LOG_TAG, "mUsers is empty, fallback to single user");
+ fallbackToSingleUserLP();
+ }
+ }
}
/**
@@ -7369,9 +7407,19 @@ public class UserManagerService extends IUserManager.Stub {
* If the main user is a permanent admin user it can't be deleted
* or downgraded to non-admin status.
*/
- private static boolean isMainUserPermanentAdmin() {
+ public boolean isMainUserPermanentAdmin() {
+ return Resources.getSystem()
+ .getBoolean(R.bool.config_isMainUserPermanentAdmin);
+ }
+
+ /**
+ * Returns true if {@link com.android.internal.R.bool#config_canSwitchToHeadlessSystemUser}
+ * is true. If allowed, headless system user can run in the foreground even though
+ * it is not a full user.
+ */
+ public boolean canSwitchToHeadlessSystemUser() {
return Resources.getSystem()
- .getBoolean(com.android.internal.R.bool.config_isMainUserPermanentAdmin);
+ .getBoolean(R.bool.config_canSwitchToHeadlessSystemUser);
}
}
diff --git a/services/core/java/com/android/server/pm/UserManagerServiceShellCommand.java b/services/core/java/com/android/server/pm/UserManagerServiceShellCommand.java
index eed2a7896fcd..98b24ea34853 100644
--- a/services/core/java/com/android/server/pm/UserManagerServiceShellCommand.java
+++ b/services/core/java/com/android/server/pm/UserManagerServiceShellCommand.java
@@ -150,6 +150,10 @@ public class UserManagerServiceShellCommand extends ShellCommand {
return runIsUserVisible();
case "get-main-user":
return runGetMainUserId();
+ case "can-switch-to-headless-system-user":
+ return canSwitchToHeadlessSystemUser();
+ case "is-main-user-permanent-admin":
+ return isMainUserPermanentAdmin();
default:
return handleDefaultCommands(cmd);
}
@@ -532,6 +536,20 @@ public class UserManagerServiceShellCommand extends ShellCommand {
return 0;
}
+ private int canSwitchToHeadlessSystemUser() {
+ PrintWriter pw = getOutPrintWriter();
+ boolean canSwitchToHeadlessSystemUser = mService.canSwitchToHeadlessSystemUser();
+ pw.println(canSwitchToHeadlessSystemUser);
+ return 0;
+ }
+
+ private int isMainUserPermanentAdmin() {
+ PrintWriter pw = getOutPrintWriter();
+ boolean isMainUserPermanentAdmin = mService.isMainUserPermanentAdmin();
+ pw.println(isMainUserPermanentAdmin);
+ return 0;
+ }
+
/**
* Gets the {@link UserManager} associated with the context of the given user.
*/
diff --git a/services/core/java/com/android/server/pm/UserVisibilityMediator.java b/services/core/java/com/android/server/pm/UserVisibilityMediator.java
index 3f7502bfa613..f87f50add5be 100644
--- a/services/core/java/com/android/server/pm/UserVisibilityMediator.java
+++ b/services/core/java/com/android/server/pm/UserVisibilityMediator.java
@@ -42,6 +42,7 @@ import android.util.Dumpable;
import android.util.EventLog;
import android.util.IndentingPrintWriter;
import android.util.IntArray;
+import android.util.Log;
import android.util.SparseIntArray;
import android.view.Display;
@@ -55,6 +56,8 @@ import com.android.server.pm.UserManagerInternal.UserVisibilityListener;
import com.android.server.utils.Slogf;
import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
@@ -77,11 +80,11 @@ import java.util.concurrent.CopyOnWriteArrayList;
*/
public final class UserVisibilityMediator implements Dumpable {
- private static final boolean DBG = false; // DO NOT SUBMIT WITH TRUE
- private static final boolean VERBOSE = false; // DO NOT SUBMIT WITH TRUE
-
private static final String TAG = UserVisibilityMediator.class.getSimpleName();
+ private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
+ private static final boolean VERBOSE = false; // DO NOT SUBMIT WITH TRUE
+
private static final String PREFIX_SECONDARY_DISPLAY_MAPPING = "SECONDARY_DISPLAY_MAPPING_";
public static final int SECONDARY_DISPLAY_MAPPING_NEEDED = 1;
public static final int SECONDARY_DISPLAY_MAPPING_NOT_NEEDED = 2;
@@ -98,7 +101,7 @@ public final class UserVisibilityMediator implements Dumpable {
})
public @interface SecondaryDisplayMappingStatus {}
- // TODO(b/242195409): might need to change this if boot logic is refactored for HSUM devices
+ // TODO(b/266158156): might need to change this if boot logic is refactored for HSUM devices
@VisibleForTesting
static final int INITIAL_CURRENT_USER_ID = USER_SYSTEM;
@@ -132,10 +135,23 @@ public final class UserVisibilityMediator implements Dumpable {
private final SparseIntArray mExtraDisplaysAssignedToUsers;
/**
- * Mapping from each started user to its profile group.
+ * Mapping of each user that started visible (key) to its profile group id (value).
+ *
+ * <p>It's used to determine not just if the user is visible, but also
+ * {@link #isProfile(int, int) if it's a profile}.
+ */
+ @GuardedBy("mLock")
+ private final SparseIntArray mStartedVisibleProfileGroupIds = new SparseIntArray();
+
+ /**
+ * List of profiles that have explicitly started invisible.
+ *
+ * <p>Only used for debugging purposes (and set when {@link #DBG} is {@code true}), hence we
+ * don't care about autoboxing.
*/
@GuardedBy("mLock")
- private final SparseIntArray mStartedProfileGroupIds = new SparseIntArray();
+ @Nullable
+ private final List<Integer> mStartedInvisibleProfileUserIds;
/**
* Handler user to call listeners
@@ -164,9 +180,14 @@ public final class UserVisibilityMediator implements Dumpable {
mUsersAssignedToDisplayOnStart = null;
mExtraDisplaysAssignedToUsers = null;
}
+ mStartedInvisibleProfileUserIds = DBG ? new ArrayList<>(4) : null;
mHandler = handler;
- // TODO(b/242195409): might need to change this if boot logic is refactored for HSUM devices
- mStartedProfileGroupIds.put(INITIAL_CURRENT_USER_ID, INITIAL_CURRENT_USER_ID);
+ // TODO(b/266158156): might need to change this if boot logic is refactored for HSUM devices
+ mStartedVisibleProfileGroupIds.put(INITIAL_CURRENT_USER_ID, INITIAL_CURRENT_USER_ID);
+
+ if (DBG) {
+ Slogf.i(TAG, "UserVisibilityMediator created with DBG on");
+ }
}
/**
@@ -177,6 +198,8 @@ public final class UserVisibilityMediator implements Dumpable {
int displayId) {
Preconditions.checkArgument(!isSpecialUserId(userId), "user id cannot be generic: %d",
userId);
+ validateUserStartMode(userStartMode);
+
// This method needs to perform 4 actions:
//
// 1. Check if the user can be started given the provided arguments
@@ -224,14 +247,29 @@ public final class UserVisibilityMediator implements Dumpable {
visibleUsersBefore = getVisibleUsers();
- // Set current user / profiles state
- if (userStartMode == USER_START_MODE_FOREGROUND) {
- mCurrentUserId = userId;
- }
- if (DBG) {
- Slogf.d(TAG, "adding user / profile mapping (%d -> %d)", userId, profileGroupId);
+ // Set current user / started users state
+ switch (userStartMode) {
+ case USER_START_MODE_FOREGROUND:
+ mCurrentUserId = userId;
+ // Fallthrough
+ case USER_START_MODE_BACKGROUND_VISIBLE:
+ if (DBG) {
+ Slogf.d(TAG, "adding visible user / profile group id mapping (%d -> %d)",
+ userId, profileGroupId);
+ }
+ mStartedVisibleProfileGroupIds.put(userId, profileGroupId);
+ break;
+ case USER_START_MODE_BACKGROUND:
+ if (mStartedInvisibleProfileUserIds != null
+ && isProfile(userId, profileGroupId)) {
+ Slogf.d(TAG, "adding user %d to list of invisible profiles", userId);
+ mStartedInvisibleProfileUserIds.add(userId);
+ }
+ break;
+ default:
+ Slogf.wtf(TAG, "invalid userStartMode passed to assignUserToDisplayOnStart: "
+ + "%d", userStartMode);
}
- mStartedProfileGroupIds.put(userId, profileGroupId);
// Set user / display state
switch (mappingResult) {
@@ -297,38 +335,44 @@ public final class UserVisibilityMediator implements Dumpable {
boolean foreground = userStartMode == USER_START_MODE_FOREGROUND;
if (displayId != DEFAULT_DISPLAY) {
if (foreground) {
- Slogf.w(TAG, "getUserVisibilityOnStartLocked(%d, %d, %b, %d) failed: cannot start "
+ Slogf.w(TAG, "getUserVisibilityOnStartLocked(%d, %d, %s, %d) failed: cannot start "
+ "foreground user on secondary display", userId, profileGroupId,
- foreground, displayId);
+ userStartModeToString(userStartMode), displayId);
return USER_ASSIGNMENT_RESULT_FAILURE;
}
if (!mVisibleBackgroundUsersEnabled) {
- Slogf.w(TAG, "getUserVisibilityOnStartLocked(%d, %d, %b, %d) failed: called on "
+ Slogf.w(TAG, "getUserVisibilityOnStartLocked(%d, %d, %s, %d) failed: called on "
+ "device that doesn't support multiple users on multiple displays",
- userId, profileGroupId, foreground, displayId);
+ userId, profileGroupId, userStartModeToString(userStartMode), displayId);
return USER_ASSIGNMENT_RESULT_FAILURE;
}
}
if (isProfile(userId, profileGroupId)) {
if (displayId != DEFAULT_DISPLAY) {
- Slogf.w(TAG, "canStartUserLocked(%d, %d, %b, %d) failed: cannot start profile user "
- + "on secondary display", userId, profileGroupId, foreground,
- displayId);
+ Slogf.w(TAG, "canStartUserLocked(%d, %d, %s, %d) failed: cannot start profile user "
+ + "on secondary display", userId, profileGroupId,
+ userStartModeToString(userStartMode), displayId);
return USER_ASSIGNMENT_RESULT_FAILURE;
}
- if (foreground) {
- Slogf.w(TAG, "startUser(%d, %d, %b, %d) failed: cannot start profile user in "
- + "foreground", userId, profileGroupId, foreground, displayId);
- return USER_ASSIGNMENT_RESULT_FAILURE;
- } else {
- boolean isParentVisibleOnDisplay = isUserVisible(profileGroupId, displayId);
- if (DBG) {
- Slogf.d(TAG, "parent visible on display: %b", isParentVisibleOnDisplay);
- }
- return isParentVisibleOnDisplay
- ? USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE
- : USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE;
+ switch (userStartMode) {
+ case USER_START_MODE_FOREGROUND:
+ Slogf.w(TAG, "startUser(%d, %d, %s, %d) failed: cannot start profile user in "
+ + "foreground", userId, profileGroupId,
+ userStartModeToString(userStartMode), displayId);
+ return USER_ASSIGNMENT_RESULT_FAILURE;
+ case USER_START_MODE_BACKGROUND_VISIBLE:
+ boolean isParentVisibleOnDisplay = isUserVisible(profileGroupId, displayId);
+ if (!isParentVisibleOnDisplay) {
+ Slogf.w(TAG, "getUserVisibilityOnStartLocked(%d, %d, %s, %d) failed: cannot"
+ + " start profile user visible when its parent is not visible in "
+ + "that display", userId, profileGroupId,
+ userStartModeToString(userStartMode), displayId);
+ return USER_ASSIGNMENT_RESULT_FAILURE;
+ }
+ return USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE;
+ case USER_START_MODE_BACKGROUND:
+ return USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE;
}
} else if (mUsersAssignedToDisplayOnStart != null
&& isUserAssignedToDisplayOnStartLocked(userId, displayId)) {
@@ -353,8 +397,9 @@ public final class UserVisibilityMediator implements Dumpable {
if (mVisibleBackgroundUserOnDefaultDisplayAllowed
&& userStartMode == USER_START_MODE_BACKGROUND_VISIBLE) {
int userStartedOnDefaultDisplay = getUserStartedOnDisplay(DEFAULT_DISPLAY);
- if (userStartedOnDefaultDisplay != USER_NULL) {
- Slogf.w(TAG, "getUserVisibilityOnStartLocked(): cannot start user %d visible on"
+ if (userStartedOnDefaultDisplay != USER_NULL
+ && userStartedOnDefaultDisplay != profileGroupId) {
+ Slogf.w(TAG, "canAssignUserToDisplayLocked(): cannot start user %d visible on"
+ " default display because user %d already did so", userId,
userStartedOnDefaultDisplay);
return SECONDARY_DISPLAY_MAPPING_FAILED;
@@ -468,7 +513,7 @@ public final class UserVisibilityMediator implements Dumpable {
userId, displayId);
return false;
}
- if (isStartedProfile(userId)) {
+ if (isStartedVisibleProfileLocked(userId)) {
Slogf.w(TAG, "assignUserToExtraDisplay(%d, %d): failed because user is a profile",
userId, displayId);
return false;
@@ -556,10 +601,14 @@ public final class UserVisibilityMediator implements Dumpable {
@GuardedBy("mLock")
private void unassignUserFromAllDisplaysOnStopLocked(@UserIdInt int userId) {
if (DBG) {
- Slogf.d(TAG, "Removing %d from mStartedProfileGroupIds (%s)", userId,
- mStartedProfileGroupIds);
+ Slogf.d(TAG, "Removing %d from mStartedVisibleProfileGroupIds (%s)", userId,
+ mStartedVisibleProfileGroupIds);
+ }
+ mStartedVisibleProfileGroupIds.delete(userId);
+ if (mStartedInvisibleProfileUserIds != null) {
+ Slogf.d(TAG, "Removing %d from list of invisible profiles", userId);
+ mStartedInvisibleProfileUserIds.remove(Integer.valueOf(userId));
}
- mStartedProfileGroupIds.delete(userId);
if (!mVisibleBackgroundUsersEnabled) {
// Don't need to update mUsersAssignedToDisplayOnStart because methods (such as
@@ -589,7 +638,8 @@ public final class UserVisibilityMediator implements Dumpable {
* See {@link UserManagerInternal#isUserVisible(int)}.
*/
public boolean isUserVisible(@UserIdInt int userId) {
- // First check current foreground user and their profiles (on main display)
+ // For optimization (as most devices don't support visible background users), check for
+ // current foreground user and their profiles first
if (isCurrentUserOrRunningProfileOfCurrentUser(userId)) {
if (VERBOSE) {
Slogf.v(TAG, "isUserVisible(%d): true to current user or profile", userId);
@@ -598,19 +648,31 @@ public final class UserVisibilityMediator implements Dumpable {
}
if (!mVisibleBackgroundUsersEnabled) {
- if (DBG) {
- Slogf.d(TAG, "isUserVisible(%d): false for non-current user (or its profiles) when"
+ if (VERBOSE) {
+ Slogf.v(TAG, "isUserVisible(%d): false for non-current user (or its profiles) when"
+ " device doesn't support visible background users", userId);
}
return false;
}
- boolean visible;
+
synchronized (mLock) {
- visible = mUsersAssignedToDisplayOnStart.indexOfKey(userId) >= 0;
+ int profileGroupId;
+ synchronized (mLock) {
+ profileGroupId = mStartedVisibleProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID);
+ }
+ if (isProfile(userId, profileGroupId)) {
+ return isUserAssignedToDisplayOnStartLocked(profileGroupId);
+ }
+ return isUserAssignedToDisplayOnStartLocked(userId);
}
- if (DBG) {
- Slogf.d(TAG, "isUserVisible(%d): %b from mapping", userId, visible);
+ }
+
+ @GuardedBy("mLock")
+ private boolean isUserAssignedToDisplayOnStartLocked(@UserIdInt int userId) {
+ boolean visible = mUsersAssignedToDisplayOnStart.indexOfKey(userId) >= 0;
+ if (VERBOSE) {
+ Slogf.v(TAG, "isUserAssignedToDisplayOnStartLocked(%d): %b", userId, visible);
}
return visible;
}
@@ -640,7 +702,8 @@ public final class UserVisibilityMediator implements Dumpable {
return false;
}
- // Current user is always visible on:
+ // For optimization (as most devices don't support visible background users), check for
+ // current user and profile first. Current user is always visible on:
// - Default display
// - Secondary displays when device doesn't support visible bg users
// - Or when explicitly added (which is checked below)
@@ -662,14 +725,26 @@ public final class UserVisibilityMediator implements Dumpable {
}
synchronized (mLock) {
- if (mUsersAssignedToDisplayOnStart.get(userId, Display.INVALID_DISPLAY) == displayId) {
- // User assigned to display on start
- return true;
+ int profileGroupId;
+ synchronized (mLock) {
+ profileGroupId = mStartedVisibleProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID);
}
+ if (isProfile(userId, profileGroupId)) {
+ return isFullUserVisibleOnBackgroundLocked(profileGroupId, displayId);
+ }
+ return isFullUserVisibleOnBackgroundLocked(userId, displayId);
+ }
+ }
- // Check for extra display assignment
- return mExtraDisplaysAssignedToUsers.get(displayId, USER_NULL) == userId;
+ // NOTE: it doesn't check if the userId is a full user, it's up to the caller to check that
+ @GuardedBy("mLock")
+ private boolean isFullUserVisibleOnBackgroundLocked(@UserIdInt int userId, int displayId) {
+ if (mUsersAssignedToDisplayOnStart.get(userId, Display.INVALID_DISPLAY) == displayId) {
+ // User assigned to display on start
+ return true;
}
+ // Check for extra display assignment
+ return mExtraDisplaysAssignedToUsers.get(displayId, USER_NULL) == userId;
}
/**
@@ -737,7 +812,7 @@ public final class UserVisibilityMediator implements Dumpable {
continue;
}
int userId = mUsersAssignedToDisplayOnStart.keyAt(i);
- if (!isStartedProfile(userId)) {
+ if (!isStartedVisibleProfileLocked(userId)) {
return userId;
} else if (DBG) {
Slogf.d(TAG, "getUserAssignedToDisplay(%d): skipping user %d because it's "
@@ -770,8 +845,8 @@ public final class UserVisibilityMediator implements Dumpable {
// number of users is too small, the gain is probably not worth the increase on complexity.
IntArray visibleUsers = new IntArray();
synchronized (mLock) {
- for (int i = 0; i < mStartedProfileGroupIds.size(); i++) {
- int userId = mStartedProfileGroupIds.keyAt(i);
+ for (int i = 0; i < mStartedVisibleProfileGroupIds.size(); i++) {
+ int userId = mStartedVisibleProfileGroupIds.keyAt(i);
if (isUserVisible(userId)) {
visibleUsers.add(userId);
}
@@ -804,7 +879,7 @@ public final class UserVisibilityMediator implements Dumpable {
}
}
- // TODO(b/242195409): remove this method if not needed anymore
+ // TODO(b/266158156): remove this method if not needed anymore
/**
* Nofify all listeners that the system user visibility changed.
*/
@@ -866,6 +941,9 @@ public final class UserVisibilityMediator implements Dumpable {
ipw.println("UserVisibilityMediator");
ipw.increaseIndent();
+ ipw.print("DBG: ");
+ ipw.println(DBG);
+
synchronized (mLock) {
ipw.print("Current user id: ");
ipw.println(mCurrentUserId);
@@ -873,8 +951,12 @@ public final class UserVisibilityMediator implements Dumpable {
ipw.print("Visible users: ");
ipw.println(getVisibleUsers());
- dumpSparseIntArray(ipw, mStartedProfileGroupIds, "started user / profile group",
- "u", "pg");
+ dumpSparseIntArray(ipw, mStartedVisibleProfileGroupIds,
+ "started visible user / profile group", "u", "pg");
+ if (mStartedInvisibleProfileUserIds != null) {
+ ipw.print("Profiles started invisible: ");
+ ipw.println(mStartedInvisibleProfileUserIds);
+ }
ipw.print("Supports visible background users on displays: ");
ipw.println(mVisibleBackgroundUsersEnabled);
@@ -982,22 +1064,25 @@ public final class UserVisibilityMediator implements Dumpable {
if (mCurrentUserId == userId) {
return true;
}
- return mStartedProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID) == mCurrentUserId;
+ return mStartedVisibleProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID)
+ == mCurrentUserId;
}
}
- private boolean isStartedProfile(@UserIdInt int userId) {
- int profileGroupId;
- synchronized (mLock) {
- profileGroupId = mStartedProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID);
- }
+ @GuardedBy("mLock")
+ private boolean isStartedVisibleProfileLocked(@UserIdInt int userId) {
+ int profileGroupId = mStartedVisibleProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID);
return isProfile(userId, profileGroupId);
}
- private @UserIdInt int getStartedProfileGroupId(@UserIdInt int userId) {
- synchronized (mLock) {
- return mStartedProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID);
+ private void validateUserStartMode(@UserStartMode int userStartMode) {
+ switch (userStartMode) {
+ case USER_START_MODE_FOREGROUND:
+ case USER_START_MODE_BACKGROUND:
+ case USER_START_MODE_BACKGROUND_VISIBLE:
+ return;
}
+ throw new IllegalArgumentException("Invalid user start mode: " + userStartMode);
}
private static String secondaryDisplayMappingStatusToString(
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index db44e1414ca7..0e99e7ee1daa 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -194,27 +194,38 @@ public final class PermissionPolicyService extends SystemService {
mPackageManagerInternal.getPackageList(new PackageListObserver() {
@Override
- public void onPackageAdded(String packageName, int uid) {
- final int userId = UserHandle.getUserId(uid);
- if (isStarted(userId)) {
- synchronizePackagePermissionsAndAppOpsForUser(packageName, userId);
+ public void onPackageAdded(String packageName, int appId) {
+ final int[] userIds = LocalServices.getService(UserManagerInternal.class)
+ .getUserIds();
+ for (final int userId : userIds) {
+ if (isStarted(userId)) {
+ synchronizePackagePermissionsAndAppOpsForUser(packageName, userId);
+ }
}
}
@Override
- public void onPackageChanged(String packageName, int uid) {
- final int userId = UserHandle.getUserId(uid);
- if (isStarted(userId)) {
- synchronizePackagePermissionsAndAppOpsForUser(packageName, userId);
- resetAppOpPermissionsIfNotRequestedForUid(uid);
+ public void onPackageChanged(String packageName, int appId) {
+ final int[] userIds = LocalServices.getService(UserManagerInternal.class)
+ .getUserIds();
+ for (final int userId : userIds) {
+ if (isStarted(userId)) {
+ synchronizePackagePermissionsAndAppOpsForUser(packageName, userId);
+ final int uid = UserHandle.getUid(userId, appId);
+ resetAppOpPermissionsIfNotRequestedForUid(uid);
+ }
}
}
@Override
- public void onPackageRemoved(String packageName, int uid) {
- final int userId = UserHandle.getUserId(uid);
- if (isStarted(userId)) {
- resetAppOpPermissionsIfNotRequestedForUid(uid);
+ public void onPackageRemoved(String packageName, int appId) {
+ final int[] userIds = LocalServices.getService(UserManagerInternal.class)
+ .getUserIds();
+ for (final int userId : userIds) {
+ if (isStarted(userId)) {
+ final int uid = UserHandle.getUid(userId, appId);
+ resetAppOpPermissionsIfNotRequestedForUid(uid);
+ }
}
}
});
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 96b37bf0b4cb..37a59da33ad8 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -89,6 +89,7 @@ import static com.android.server.wm.WindowManagerPolicyProto.WINDOW_MANAGER_DRAW
import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityServiceInfo;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManager.RecentTaskInfo;
@@ -129,7 +130,6 @@ import android.media.AudioSystem;
import android.media.IAudioService;
import android.media.session.MediaSessionLegacyHelper;
import android.os.Binder;
-import android.os.Build;
import android.os.Bundle;
import android.os.DeviceIdleManager;
import android.os.FactoryTest;
@@ -161,7 +161,9 @@ import android.service.dreams.IDreamManager;
import android.service.vr.IPersistentVrStateCallbacks;
import android.speech.RecognizerIntent;
import android.telecom.TelecomManager;
+import android.util.FeatureFlagUtils;
import android.util.Log;
+import android.util.MathUtils;
import android.util.MutableBoolean;
import android.util.PrintWriterPrinter;
import android.util.Slog;
@@ -203,6 +205,7 @@ import com.android.internal.policy.PhoneWindow;
import com.android.internal.policy.TransitionAnimation;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.widget.LockPatternUtils;
import com.android.server.AccessibilityManagerInternal;
import com.android.server.ExtconStateObserver;
import com.android.server.ExtconUEventObserver;
@@ -210,6 +213,7 @@ import com.android.server.GestureLauncherService;
import com.android.server.LocalServices;
import com.android.server.SystemServiceManager;
import com.android.server.UiThread;
+import com.android.server.display.BrightnessUtils;
import com.android.server.input.InputManagerInternal;
import com.android.server.inputmethod.InputMethodManagerInternal;
import com.android.server.policy.KeyCombinationManager.TwoKeysCombinationRule;
@@ -328,6 +332,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
static final int TRIPLE_PRESS_PRIMARY_NOTHING = 0;
static final int TRIPLE_PRESS_PRIMARY_TOGGLE_ACCESSIBILITY = 1;
+ // Must match: config_searchKeyBehavior in config.xml
+ static final int SEARCH_BEHAVIOR_DEFAULT_SEARCH = 0;
+ static final int SEARCH_BEHAVIOR_TARGET_ACTIVITY = 1;
+
static public final String SYSTEM_DIALOG_REASON_KEY = "reason";
static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
@@ -396,7 +404,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
ActivityTaskManagerInternal mActivityTaskManagerInternal;
AutofillManagerInternal mAutofillManagerInternal;
InputManagerInternal mInputManagerInternal;
- InputMethodManagerInternal mInputMethodManagerInternal;
DreamManagerInternal mDreamManagerInternal;
PowerManagerInternal mPowerManagerInternal;
IStatusBarService mStatusBarService;
@@ -416,6 +423,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
AppOpsManager mAppOpsManager;
PackageManager mPackageManager;
SideFpsEventHandler mSideFpsEventHandler;
+ LockPatternUtils mLockPatternUtils;
private boolean mHasFeatureAuto;
private boolean mHasFeatureWatch;
private boolean mHasFeatureLeanback;
@@ -536,6 +544,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
boolean mWakeOnAssistKeyPress;
boolean mWakeOnBackKeyPress;
long mWakeUpToLastStateTimeout;
+ int mSearchKeyBehavior;
+ ComponentName mSearchKeyTargetActivity;
private boolean mHandleVolumeKeysInWM;
@@ -656,6 +666,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
private static final int MSG_HANDLE_ALL_APPS = 22;
private static final int MSG_LAUNCH_ASSIST = 23;
private static final int MSG_RINGER_TOGGLE_CHORD = 24;
+ private static final int MSG_SWITCH_KEYBOARD_LAYOUT = 25;
private class PolicyHandler extends Handler {
@Override
@@ -726,6 +737,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case MSG_SCREENSHOT_CHORD:
handleScreenShot(msg.arg1);
break;
+ case MSG_SWITCH_KEYBOARD_LAYOUT:
+ handleSwitchKeyboardLayout(msg.arg1, msg.arg2);
+ break;
}
}
}
@@ -1022,14 +1036,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
break;
case SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME: {
if (mDismissImeOnBackKeyPressed) {
- if (mInputMethodManagerInternal == null) {
- mInputMethodManagerInternal =
- LocalServices.getService(InputMethodManagerInternal.class);
- }
- if (mInputMethodManagerInternal != null) {
- mInputMethodManagerInternal.hideCurrentInputMethod(
+ InputMethodManagerInternal.get().hideCurrentInputMethod(
SoftInputShowHideReason.HIDE_POWER_BUTTON_GO_HOME);
- }
} else {
shortPressPowerGoHome();
}
@@ -1074,8 +1082,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
synchronized (mLock) {
- // Lock the device after the dream transition has finished.
- mLockAfterAppTransitionFinished = true;
+ // If the setting to lock instantly on power button press is true, then set the flag to
+ // lock after the dream transition has finished.
+ mLockAfterAppTransitionFinished =
+ mLockPatternUtils.getPowerButtonInstantlyLocks(mCurrentUserId);
}
dreamManagerInternal.requestDream();
@@ -1993,6 +2003,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mAccessibilityShortcutController = injector.getAccessibilityShortcutController(
mContext, new Handler(), mCurrentUserId);
mGlobalActionsFactory = injector.getGlobalActionsFactory();
+ mLockPatternUtils = new LockPatternUtils(mContext);
mLogger = new MetricsLogger();
mScreenOffSleepTokenAcquirer = mActivityTaskManagerInternal
@@ -2134,6 +2145,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mWakeUpToLastStateTimeout = mContext.getResources().getInteger(
com.android.internal.R.integer.config_wakeUpToLastStateTimeoutMillis);
+ mSearchKeyBehavior = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_searchKeyBehavior);
+
+ mSearchKeyTargetActivity = ComponentName.unflattenFromString(
+ mContext.getResources().getString(
+ com.android.internal.R.string.config_searchKeyTargetActivity));
readConfigurationDependentBehaviors();
mDisplayFoldController = DisplayFoldController.create(mContext, DEFAULT_DISPLAY);
@@ -2960,7 +2977,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
break;
case KeyEvent.KEYCODE_H:
- if (down && event.isMetaPressed()) {
+ if (event.isMetaPressed()) {
return handleHomeShortcuts(displayId, focusedToken, event);
}
break;
@@ -2972,15 +2989,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
break;
case KeyEvent.KEYCODE_N:
if (down && event.isMetaPressed()) {
- IStatusBarService service = getStatusBarService();
- if (service != null) {
- try {
- service.expandNotificationsPanel();
- } catch (RemoteException e) {
- // do nothing.
- }
- return key_consumed;
- }
+ toggleNotificationPanel();
+ return key_consumed;
}
break;
case KeyEvent.KEYCODE_S:
@@ -2989,6 +2999,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return key_consumed;
}
break;
+ case KeyEvent.KEYCODE_T:
+ if (down && event.isMetaPressed()) {
+ toggleTaskbar();
+ return key_consumed;
+ }
+ break;
case KeyEvent.KEYCODE_DPAD_UP:
if (down && event.isMetaPressed() && event.isCtrlPressed() && repeatCount == 0) {
StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
@@ -3002,11 +3018,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (down && event.isMetaPressed() && event.isCtrlPressed() && repeatCount == 0) {
enterStageSplitFromRunningApp(true /* leftOrTop */);
return key_consumed;
- } else if (!down && event.isMetaPressed()) {
- boolean backKeyHandled = backKeyPress();
- if (backKeyHandled) {
- return key_consumed;
- }
}
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
@@ -3015,14 +3026,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return key_consumed;
}
break;
- case KeyEvent.KEYCODE_GRAVE:
- if (!down && event.isMetaPressed()) {
- boolean backKeyHandled = backKeyPress();
- if (backKeyHandled) {
- return key_consumed;
- }
- }
- break;
case KeyEvent.KEYCODE_SLASH:
if (down && repeatCount == 0 && event.isMetaPressed() && !keyguardOn) {
toggleKeyboardShortcutsMenu(event.getDeviceId());
@@ -3071,19 +3074,22 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
UserHandle.USER_CURRENT_OR_SELF);
}
- float min = mPowerManager.getBrightnessConstraint(
- PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM);
- float max = mPowerManager.getBrightnessConstraint(
- PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM);
- float step = (max - min) / BRIGHTNESS_STEPS * direction;
int screenDisplayId = displayId < 0 ? DEFAULT_DISPLAY : displayId;
- float brightness = mDisplayManager.getBrightness(screenDisplayId);
- brightness += step;
- // Make sure we don't go beyond the limits.
- brightness = Math.min(max, brightness);
- brightness = Math.max(min, brightness);
- mDisplayManager.setBrightness(screenDisplayId, brightness);
+ float linearBrightness = mDisplayManager.getBrightness(screenDisplayId);
+
+ float gammaBrightness = BrightnessUtils.convertLinearToGamma(linearBrightness);
+ float adjustedGammaBrightness =
+ gammaBrightness + 1f / BRIGHTNESS_STEPS * direction;
+
+ float adjustedLinearBrightness = BrightnessUtils.convertGammaToLinear(
+ adjustedGammaBrightness);
+
+ adjustedLinearBrightness = MathUtils.constrain(adjustedLinearBrightness, 0f,
+ 1f);
+
+ mDisplayManager.setBrightness(screenDisplayId, adjustedLinearBrightness);
+
startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG),
UserHandle.CURRENT_OR_SELF);
}
@@ -3154,7 +3160,19 @@ public class PhoneWindowManager implements WindowManagerPolicy {
toggleNotificationPanel();
}
return key_consumed;
-
+ case KeyEvent.KEYCODE_SEARCH:
+ if (down && repeatCount == 0 && !keyguardOn()) {
+ switch(mSearchKeyBehavior) {
+ case SEARCH_BEHAVIOR_TARGET_ACTIVITY: {
+ launchTargetSearchActivity();
+ return key_consumed;
+ }
+ case SEARCH_BEHAVIOR_DEFAULT_SEARCH:
+ default:
+ break;
+ }
+ }
+ break;
case KeyEvent.KEYCODE_SPACE:
// Handle keyboard layout switching. (META + SPACE)
if ((metaState & KeyEvent.META_META_MASK) == 0) {
@@ -3162,7 +3180,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
if (down && repeatCount == 0) {
int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1;
- mWindowManagerFuncs.switchKeyboardLayout(event.getDeviceId(), direction);
+ sendSwitchKeyboardLayout(event, direction);
return key_consumed;
}
break;
@@ -3412,7 +3430,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (KeyEvent.metaStateHasModifiers(metaState & ~KeyEvent.META_SHIFT_MASK,
KeyEvent.META_CTRL_ON)) {
int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1;
- mWindowManagerFuncs.switchKeyboardLayout(event.getDeviceId(), direction);
+ sendSwitchKeyboardLayout(event, direction);
return true;
}
}
@@ -3438,6 +3456,19 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return false;
}
+ private void sendSwitchKeyboardLayout(@NonNull KeyEvent event, int direction) {
+ mHandler.obtainMessage(MSG_SWITCH_KEYBOARD_LAYOUT, event.getDeviceId(),
+ direction).sendToTarget();
+ }
+
+ private void handleSwitchKeyboardLayout(int deviceId, int direction) {
+ if (FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_UI)) {
+ InputMethodManagerInternal.get().switchKeyboardLayout(direction);
+ } else {
+ mWindowManagerFuncs.switchKeyboardLayout(deviceId, direction);
+ }
+ }
+
private boolean interceptFallback(IBinder focusedToken, KeyEvent fallbackEvent,
int policyFlags) {
int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags);
@@ -3660,6 +3691,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
+ private void toggleTaskbar() {
+ StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
+ if (statusbar != null) {
+ statusbar.toggleTaskbar();
+ }
+ }
+
private void toggleRecentApps() {
mPreloadedRecentApps = false; // preloading no longer needs to be canceled
StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
@@ -6317,4 +6355,22 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
+ private void launchTargetSearchActivity() {
+ Intent intent;
+ if (mSearchKeyTargetActivity != null) {
+ intent = new Intent();
+ intent.setComponent(mSearchKeyTargetActivity);
+ } else {
+ intent = new Intent(Intent.ACTION_WEB_SEARCH);
+ }
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+ try {
+ startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
+ } catch (ActivityNotFoundException ignore) {
+ Slog.e(TAG, "Could not resolve activity with : "
+ + intent.getComponent().flattenToString()
+ + " name.");
+ }
+ }
}
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index b83d509b47b1..2e8a150f2b6d 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -40,7 +40,6 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
-import android.app.ActivityManagerInternal;
import android.app.AppOpsManager;
import android.app.SynchronousUserSwitchObserver;
import android.content.BroadcastReceiver;
@@ -317,7 +316,6 @@ public final class PowerManagerService extends SystemService
private SettingsObserver mSettingsObserver;
private DreamManagerInternal mDreamManager;
private LogicalLight mAttentionLight;
- private ActivityManagerInternal mAmInternal;
private final InattentiveSleepWarningController mInattentiveSleepWarningOverlayController;
private final AmbientDisplaySuppressionController mAmbientDisplaySuppressionController;
@@ -1244,7 +1242,6 @@ public final class PowerManagerService extends SystemService
mDisplayManagerInternal = getLocalService(DisplayManagerInternal.class);
mPolicy = getLocalService(WindowManagerPolicy.class);
mBatteryManagerInternal = getLocalService(BatteryManagerInternal.class);
- mAmInternal = getLocalService(ActivityManagerInternal.class);
mAttentionDetector.systemReady(mContext);
SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper());
@@ -4088,8 +4085,9 @@ public final class PowerManagerService extends SystemService
final UidState state = wakeLock.mUidState;
if (Arrays.binarySearch(mDeviceIdleWhitelist, appid) < 0 &&
Arrays.binarySearch(mDeviceIdleTempWhitelist, appid) < 0 &&
- (mAmInternal != null && !mAmInternal.canHoldWakeLocksInDeepDoze(
- state.mUid, state.mProcState))) {
+ state.mProcState != ActivityManager.PROCESS_STATE_NONEXISTENT &&
+ state.mProcState >
+ ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
disabled = true;
}
}
@@ -5695,6 +5693,7 @@ public final class PowerManagerService extends SystemService
}
if (eventTime > now) {
+ Slog.e(TAG, "Event time " + eventTime + " cannot be newer than " + now);
throw new IllegalArgumentException("event time must not be in the future");
}
@@ -5710,7 +5709,9 @@ public final class PowerManagerService extends SystemService
@Override // Binder call
public void wakeUp(long eventTime, @WakeReason int reason, String details,
String opPackageName) {
- if (eventTime > mClock.uptimeMillis()) {
+ final long now = mClock.uptimeMillis();
+ if (eventTime > now) {
+ Slog.e(TAG, "Event time " + eventTime + " cannot be newer than " + now);
throw new IllegalArgumentException("event time must not be in the future");
}
@@ -5762,7 +5763,9 @@ public final class PowerManagerService extends SystemService
@Override // Binder call
public void nap(long eventTime) {
- if (eventTime > mClock.uptimeMillis()) {
+ final long now = mClock.uptimeMillis();
+ if (eventTime > now) {
+ Slog.e(TAG, "Event time " + eventTime + " cannot be newer than " + now);
throw new IllegalArgumentException("event time must not be in the future");
}
@@ -6527,7 +6530,9 @@ public final class PowerManagerService extends SystemService
@Override // Binder call
public void boostScreenBrightness(long eventTime) {
+ final long now = mClock.uptimeMillis();
if (eventTime > mClock.uptimeMillis()) {
+ Slog.e(TAG, "Event time " + eventTime + " cannot be newer than " + now);
throw new IllegalArgumentException("event time must not be in the future");
}
@@ -6686,7 +6691,9 @@ public final class PowerManagerService extends SystemService
@RequiresPermission(android.Manifest.permission.DEVICE_POWER)
private void goToSleepInternal(IntArray groupIds, long eventTime, int reason, int flags) {
- if (eventTime > mClock.uptimeMillis()) {
+ final long now = mClock.uptimeMillis();
+ if (eventTime > now) {
+ Slog.e(TAG, "Event time " + eventTime + " cannot be newer than " + now);
throw new IllegalArgumentException("event time must not be in the future");
}
diff --git a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
index 3d3c5e26e4f7..f11c864edba0 100644
--- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
+++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
@@ -1743,7 +1743,8 @@ public class BatteryStatsImpl extends BatteryStats {
if (historyDirectory == null) {
mCheckinFile = null;
mStatsFile = null;
- mHistory = new BatteryStatsHistory(mStepDetailsCalculator, mClock);
+ mHistory = new BatteryStatsHistory(mConstants.MAX_HISTORY_FILES,
+ mConstants.MAX_HISTORY_BUFFER, mStepDetailsCalculator, mClock);
} else {
mCheckinFile = new AtomicFile(new File(historyDirectory, "batterystats-checkin.bin"));
mStatsFile = new AtomicFile(new File(historyDirectory, "batterystats.bin"));
@@ -10881,14 +10882,17 @@ public class BatteryStatsImpl extends BatteryStats {
if (systemDir == null) {
mStatsFile = null;
- mHistory = new BatteryStatsHistory(mStepDetailsCalculator, mClock);
+ mCheckinFile = null;
+ mDailyFile = null;
+ mHistory = new BatteryStatsHistory(mConstants.MAX_HISTORY_FILES,
+ mConstants.MAX_HISTORY_BUFFER, mStepDetailsCalculator, mClock);
} else {
mStatsFile = new AtomicFile(new File(systemDir, "batterystats.bin"));
+ mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
+ mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml"));
mHistory = new BatteryStatsHistory(systemDir, mConstants.MAX_HISTORY_FILES,
mConstants.MAX_HISTORY_BUFFER, mStepDetailsCalculator, mClock);
}
- mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
- mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml"));
mStartCount++;
initTimersAndCounters();
mOnBattery = mOnBatteryInternal = false;
diff --git a/services/core/java/com/android/server/power/stats/CpuWakeupStats.java b/services/core/java/com/android/server/power/stats/CpuWakeupStats.java
index 54f3476d3b86..706aedcbba7b 100644
--- a/services/core/java/com/android/server/power/stats/CpuWakeupStats.java
+++ b/services/core/java/com/android/server/power/stats/CpuWakeupStats.java
@@ -18,6 +18,7 @@ package com.android.server.power.stats;
import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_ALARM;
import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_UNKNOWN;
+import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_WIFI;
import android.content.Context;
import android.os.Handler;
@@ -49,6 +50,7 @@ public class CpuWakeupStats {
private static final String TAG = "CpuWakeupStats";
private static final String SUBSYSTEM_ALARM_STRING = "Alarm";
+ private static final String SUBSYSTEM_ALARM_WIFI = "Wifi";
@VisibleForTesting
static final long WAKEUP_RETENTION_MS = 3 * 24 * 60 * 60_000; // 3 days.
@VisibleForTesting
@@ -74,6 +76,8 @@ public class CpuWakeupStats {
switch (subsystem) {
case CPU_WAKEUP_SUBSYSTEM_ALARM:
return FrameworkStatsLog.KERNEL_WAKEUP_ATTRIBUTED__REASON__ALARM;
+ case CPU_WAKEUP_SUBSYSTEM_WIFI:
+ return FrameworkStatsLog.KERNEL_WAKEUP_ATTRIBUTED__REASON__WIFI;
}
return FrameworkStatsLog.KERNEL_WAKEUP_ATTRIBUTED__REASON__UNKNOWN;
}
@@ -122,7 +126,10 @@ public class CpuWakeupStats {
/** Notes a wakeup reason as reported by SuspendControlService to battery stats. */
public synchronized void noteWakeupTimeAndReason(long elapsedRealtime, long uptime,
String rawReason) {
- final Wakeup parsedWakeup = new Wakeup(rawReason, elapsedRealtime, uptime);
+ final Wakeup parsedWakeup = Wakeup.parseWakeup(rawReason, elapsedRealtime, uptime);
+ if (parsedWakeup == null) {
+ return;
+ }
mWakeupEvents.put(elapsedRealtime, parsedWakeup);
attemptAttributionFor(parsedWakeup);
// Assuming that wakeups always arrive in monotonically increasing elapsedRealtime order,
@@ -425,6 +432,8 @@ public class CpuWakeupStats {
switch (rawSubsystem) {
case SUBSYSTEM_ALARM_STRING:
return CPU_WAKEUP_SUBSYSTEM_ALARM;
+ case SUBSYSTEM_ALARM_WIFI:
+ return CPU_WAKEUP_SUBSYSTEM_WIFI;
}
return CPU_WAKEUP_SUBSYSTEM_UNKNOWN;
}
@@ -433,6 +442,8 @@ public class CpuWakeupStats {
switch (subsystem) {
case CPU_WAKEUP_SUBSYSTEM_ALARM:
return SUBSYSTEM_ALARM_STRING;
+ case CPU_WAKEUP_SUBSYSTEM_WIFI:
+ return SUBSYSTEM_ALARM_WIFI;
case CPU_WAKEUP_SUBSYSTEM_UNKNOWN:
return "Unknown";
}
@@ -443,28 +454,25 @@ public class CpuWakeupStats {
private static final String PARSER_TAG = "CpuWakeupStats.Wakeup";
private static final String ABORT_REASON_PREFIX = "Abort";
private static final Pattern sIrqPattern = Pattern.compile("^(\\d+)\\s+(\\S+)");
-
- String mRawReason;
long mElapsedMillis;
long mUptimeMillis;
IrqDevice[] mDevices;
- Wakeup(String rawReason, long elapsedMillis, long uptimeMillis) {
- mRawReason = rawReason;
+ private Wakeup(IrqDevice[] devices, long elapsedMillis, long uptimeMillis) {
mElapsedMillis = elapsedMillis;
mUptimeMillis = uptimeMillis;
- mDevices = parseIrqDevices(rawReason);
+ mDevices = devices;
}
- private static IrqDevice[] parseIrqDevices(String rawReason) {
+ static Wakeup parseWakeup(String rawReason, long elapsedMillis, long uptimeMillis) {
final String[] components = rawReason.split(":");
if (ArrayUtils.isEmpty(components) || components[0].startsWith(ABORT_REASON_PREFIX)) {
- // We don't support parsing aborts yet.
+ // Accounting of aborts is not supported yet.
return null;
}
int parsedDeviceCount = 0;
- IrqDevice[] parsedDevices = new IrqDevice[components.length];
+ final IrqDevice[] parsedDevices = new IrqDevice[components.length];
for (String component : components) {
final Matcher matcher = sIrqPattern.matcher(component.trim());
@@ -482,14 +490,17 @@ public class CpuWakeupStats {
parsedDevices[parsedDeviceCount++] = new IrqDevice(line, device);
}
}
- return (parsedDeviceCount > 0) ? Arrays.copyOf(parsedDevices, parsedDeviceCount) : null;
+ if (parsedDeviceCount == 0) {
+ return null;
+ }
+ return new Wakeup(Arrays.copyOf(parsedDevices, parsedDeviceCount), elapsedMillis,
+ uptimeMillis);
}
@Override
public String toString() {
return "Wakeup{"
- + "mRawReason='" + mRawReason + '\''
- + ", mElapsedMillis=" + mElapsedMillis
+ + "mElapsedMillis=" + mElapsedMillis
+ ", mUptimeMillis=" + TimeUtils.formatDuration(mUptimeMillis)
+ ", mDevices=" + Arrays.toString(mDevices)
+ '}';
@@ -506,7 +517,7 @@ public class CpuWakeupStats {
@Override
public String toString() {
- return "IrqDevice{" + "mLine=" + mLine + ", mDevice='" + mDevice + '\'' + '}';
+ return "IrqDevice{" + "mLine=" + mLine + ", mDevice=\'" + mDevice + '\'' + '}';
}
}
}
diff --git a/services/core/java/com/android/server/rollback/OWNERS b/services/core/java/com/android/server/rollback/OWNERS
index 7feb85f929cd..daa02111f71f 100644
--- a/services/core/java/com/android/server/rollback/OWNERS
+++ b/services/core/java/com/android/server/rollback/OWNERS
@@ -1 +1,3 @@
-olilan@google.com
+ancr@google.com
+harshitmahajan@google.com
+robertogil@google.com
diff --git a/services/core/java/com/android/server/sensors/SensorManagerInternal.java b/services/core/java/com/android/server/sensors/SensorManagerInternal.java
index 41c2fbfd3314..6c32ec2e8df8 100644
--- a/services/core/java/com/android/server/sensors/SensorManagerInternal.java
+++ b/services/core/java/com/android/server/sensors/SensorManagerInternal.java
@@ -17,6 +17,8 @@
package com.android.server.sensors;
import android.annotation.NonNull;
+import android.hardware.SensorDirectChannel;
+import android.os.ParcelFileDescriptor;
import java.util.concurrent.Executor;
@@ -58,7 +60,7 @@ public abstract class SensorManagerInternal {
* @return The sensor handle.
*/
public abstract int createRuntimeSensor(int deviceId, int type, @NonNull String name,
- @NonNull String vendor, @NonNull RuntimeSensorCallback callback);
+ @NonNull String vendor, int flags, @NonNull RuntimeSensorCallback callback);
/**
* Unregisters the sensor with the given handle from the framework.
@@ -98,9 +100,31 @@ public abstract class SensorManagerInternal {
public interface RuntimeSensorCallback {
/**
* Invoked when the listeners of the runtime sensor have changed.
- * Returns an error code if the invocation was unsuccessful, zero otherwise.
+ * Returns zero on success, negative error code otherwise.
*/
int onConfigurationChanged(int handle, boolean enabled, int samplingPeriodMicros,
int batchReportLatencyMicros);
+
+ /**
+ * Invoked when a direct sensor channel has been created.
+ * Wraps the file descriptor in a {@link android.os.SharedMemory} object and passes it to
+ * the client process.
+ * Returns a positive identifier of the channel on success, negative error code otherwise.
+ */
+ int onDirectChannelCreated(ParcelFileDescriptor fd);
+
+ /**
+ * Invoked when a direct sensor channel has been destroyed.
+ */
+ void onDirectChannelDestroyed(int channelHandle);
+
+ /**
+ * Invoked when a direct sensor channel has been configured for a sensor.
+ * If the invocation is unsuccessful, a negative error code is returned.
+ * On success, the return value is zero if the rate level is {@code RATE_STOP}, and a
+ * positive report token otherwise.
+ */
+ int onDirectChannelConfigured(int channelHandle, int sensorHandle,
+ @SensorDirectChannel.RateLevel int rateLevel);
}
}
diff --git a/services/core/java/com/android/server/sensors/SensorService.java b/services/core/java/com/android/server/sensors/SensorService.java
index 979065950dc4..1baa0a6d79a1 100644
--- a/services/core/java/com/android/server/sensors/SensorService.java
+++ b/services/core/java/com/android/server/sensors/SensorService.java
@@ -56,7 +56,8 @@ public class SensorService extends SystemService {
private static native void unregisterProximityActiveListenerNative(long ptr);
private static native int registerRuntimeSensorNative(long ptr, int deviceId, int type,
- String name, String vendor, SensorManagerInternal.RuntimeSensorCallback callback);
+ String name, String vendor, int flags,
+ SensorManagerInternal.RuntimeSensorCallback callback);
private static native void unregisterRuntimeSensorNative(long ptr, int handle);
private static native boolean sendRuntimeSensorEventNative(long ptr, int handle, int type,
long timestampNanos, float[] values);
@@ -95,9 +96,9 @@ public class SensorService extends SystemService {
class LocalService extends SensorManagerInternal {
@Override
public int createRuntimeSensor(int deviceId, int type, @NonNull String name,
- @NonNull String vendor, @NonNull RuntimeSensorCallback callback) {
+ @NonNull String vendor, int flags, @NonNull RuntimeSensorCallback callback) {
synchronized (mLock) {
- int handle = registerRuntimeSensorNative(mPtr, deviceId, type, name, vendor,
+ int handle = registerRuntimeSensorNative(mPtr, deviceId, type, name, vendor, flags,
callback);
mRuntimeSensorHandles.add(handle);
return handle;
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index ec052ecd20f2..efd8b6d9a943 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -122,6 +122,10 @@ public interface StatusBarManagerInternal {
*/
void onEmergencyActionLaunchGestureDetected();
+ /** Toggle the task bar stash state. */
+ void toggleTaskbar();
+
+ /** Toggle recents. */
void toggleRecentApps();
void setCurrentUser(int newUserId);
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 4489ba94235c..5bace0ebe13a 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -418,6 +418,15 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
}
@Override
+ public void toggleTaskbar() {
+ if (mBar != null) {
+ try {
+ mBar.toggleTaskbar();
+ } catch (RemoteException ex) {}
+ }
+ }
+
+ @Override
public void toggleRecentApps() {
if (mBar != null) {
try {
diff --git a/services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java b/services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java
index 4a6c794cf11d..de631bb53377 100644
--- a/services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java
+++ b/services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java
@@ -65,7 +65,7 @@ import java.util.function.Supplier;
* If a request fails, it retries a number of times with a "short" interval and then resets to the
* normal interval. The process then repeats.
*
- * <p>When a valid network time is available, the time is always suggested to the {@link
+ * <p>When a valid network time is available, the network time is always suggested to the {@link
* com.android.server.timedetector.TimeDetectorService} where it may be used to set the device
* system clock, depending on user settings and what other signals are available.
*/
@@ -181,24 +181,6 @@ public class NetworkTimeUpdateService extends Binder {
}
/**
- * Clears the cached NTP time. For use during tests to simulate when no NTP time is available.
- *
- * <p>This operation takes place in the calling thread rather than the service's handler thread.
- */
- @RequiresPermission(android.Manifest.permission.SET_TIME)
- void clearTimeForTests() {
- mContext.enforceCallingPermission(
- android.Manifest.permission.SET_TIME, "clear latest network time");
-
- final long token = Binder.clearCallingIdentity();
- try {
- mNtpTrustedTime.clearCachedTimeResult();
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- /**
* Forces the service to refresh the NTP time.
*
* <p>This operation takes place in the calling thread rather than the service's handler thread.
@@ -286,7 +268,7 @@ public class NetworkTimeUpdateService extends Binder {
}
/**
- * Checks if the user prefers to automatically set the time.
+ * Checks if the user prefers to automatically set the device's system clock time.
*/
private boolean isAutomaticTimeEnabled() {
ContentResolver resolver = mContext.getContentResolver();
@@ -313,7 +295,7 @@ public class NetworkTimeUpdateService extends Binder {
}
/**
- * The interface the service uses to interact with the time refresh logic.
+ * The interface the service uses to interact with the network time refresh logic.
* Extracted for testing.
*/
@VisibleForTesting
@@ -387,10 +369,10 @@ public class NetworkTimeUpdateService extends Binder {
private final NtpTrustedTime mNtpTrustedTime;
/**
- * Records the time of the last refresh attempt (successful or otherwise) by this service.
- * This is used when scheduling the next refresh attempt. In cases where {@link
- * #refreshAndRescheduleIfRequired} is called too frequently, this will prevent each call
- * resulting in a network request. See also {@link #mShortPollingIntervalMillis}.
+ * Records the elapsed realtime of the last refresh attempt (successful or otherwise) by
+ * this service. This is used when scheduling the next refresh attempt. In cases where
+ * {@link #refreshAndRescheduleIfRequired} is called too frequently, this will prevent each
+ * call resulting in a network request. See also {@link #mShortPollingIntervalMillis}.
*
* <p>Time servers are a shared resource and so Android should avoid loading them.
* Generally, a refresh attempt will succeed and the service won't need to make further
@@ -454,8 +436,11 @@ public class NetworkTimeUpdateService extends Binder {
return;
}
- // Attempt to refresh the network time if there is no latest time result, or if the
- // latest time result is considered too old.
+ // Step 1: Work out if the latest time result, if any, needs to be refreshed and handle
+ // the refresh.
+
+ // A refresh should be attempted if there is no latest time result, or if the latest
+ // time result is considered too old.
NtpTrustedTime.TimeResult initialTimeResult = mNtpTrustedTime.getCachedTimeResult();
boolean shouldAttemptRefresh;
synchronized (this) {
@@ -472,22 +457,42 @@ public class NetworkTimeUpdateService extends Binder {
boolean refreshSuccessful = false;
if (shouldAttemptRefresh) {
// This is a blocking call. Deliberately invoked without holding the "this" monitor
- // to avoid blocking logic that wants to use the "this" monitor.
+ // to avoid blocking other logic that wants to use the "this" monitor, e.g. dump().
refreshSuccessful = tryRefresh(network);
}
synchronized (this) {
- // Manage mTryAgainCounter.
+ // This section of code deliberately doesn't assume it is the only component using
+ // the NtpTrustedTime singleton to obtain NTP times: another component in the same
+ // process could be gathering NTP signals (which then won't have been suggested to
+ // the time detector).
+ // TODO(b/222295093): Make this class the sole user of the NtpTrustedTime singleton
+ // and simplify / reduce duplicate suggestions and other logic.
+ NtpTrustedTime.TimeResult latestTimeResult = mNtpTrustedTime.getCachedTimeResult();
+
+ // currentElapsedRealtimeMillis is used to evaluate ages and refresh scheduling
+ // below. Capturing this after obtaining the cached time result ensures that latest
+ // time result ages will be >= 0.
+ long currentElapsedRealtimeMillis = mElapsedRealtimeMillisSupplier.get();
+
+ long latestTimeResultAgeMillis = calculateTimeResultAgeMillis(
+ latestTimeResult, currentElapsedRealtimeMillis);
+
+ // Step 2: Set mTryAgainCounter.
+ // + == 0: The last attempt was successful OR the latest time result is acceptable
+ // OR the mTryAgainCounter exceeded mTryAgainTimesMax and has been reset
+ // to 0. In all these cases the normal refresh interval should be used.
+ // + > 0: The last refresh attempt was unsuccessful. Some number of retries are
+ // allowed using the short interval depending on mTryAgainTimesMax.
if (shouldAttemptRefresh) {
if (refreshSuccessful) {
- // Reset failure tracking.
mTryAgainCounter = 0;
} else {
if (mTryAgainTimesMax < 0) {
// When mTryAgainTimesMax is negative there's no enforced maximum and
// short intervals should be used until a successful refresh. Setting
// mTryAgainCounter to 1 is sufficient for the interval calculations
- // below. There's no need to increment.
+ // below, i.e. there's no need to increment.
mTryAgainCounter = 1;
} else {
mTryAgainCounter++;
@@ -497,58 +502,97 @@ public class NetworkTimeUpdateService extends Binder {
}
}
}
+ if (latestTimeResultAgeMillis < mNormalPollingIntervalMillis) {
+ // The latest time result may indicate a successful refresh has been achieved by
+ // another user of the NtpTrustedTime singleton. This could be an "else if", but
+ // this is deliberately done defensively in all cases to maintain the invariant
+ // that mTryAgainCounter will be 0 if the latest time result is currently ok.
+ mTryAgainCounter = 0;
+ }
- // currentElapsedRealtimeMillis is used to evaluate ages and refresh scheduling
- // below. Capturing this after a possible successful refresh ensures that latest
- // time result ages will be >= 0.
- long currentElapsedRealtimeMillis = mElapsedRealtimeMillisSupplier.get();
-
- // This section of code deliberately doesn't assume it is the only component using
- // mNtpTrustedTime to obtain NTP times: another component in the same process could
- // be gathering NTP signals (which then won't have been suggested to the time
- // detector).
- // TODO(b/222295093): Make this class the sole owner of mNtpTrustedTime and
- // simplify / reduce duplicate suggestions.
- NtpTrustedTime.TimeResult latestTimeResult = mNtpTrustedTime.getCachedTimeResult();
- long latestTimeResultAgeMillis = calculateTimeResultAgeMillis(
- latestTimeResult, currentElapsedRealtimeMillis);
-
- // Suggest the latest time result to the time detector if it is fresh regardless of
- // whether refresh happened above.
+ // Step 3: Suggest the latest time result to the time detector if it is fresh
+ // regardless of whether a refresh happened / succeeded above. The time detector
+ // service can detect duplicate suggestions and not do more work than it has to, so
+ // there is no need to avoid making duplicate suggestions.
if (latestTimeResultAgeMillis < mNormalPollingIntervalMillis) {
- // We assume the time detector service will detect duplicate suggestions and not
- // do more work than it has to, so no need to avoid making duplicate
- // suggestions.
makeNetworkTimeSuggestion(latestTimeResult, reason, refreshCallbacks);
}
- // (Re)schedule the next refresh based on the latest state.
- // Determine which refresh delay to use by using the current value of
- // mTryAgainCounter. The refresh delay is applied to a different point in time
- // depending on whether the latest available time result (if any) is still
- // considered fresh to ensure the delay acts correctly.
- long refreshDelayMillis = mTryAgainCounter > 0
+ // Step 4: (Re)schedule the next refresh attempt based on the latest state.
+
+ // Determine which refresh attempt delay to use by using the current value of
+ // mTryAgainCounter.
+ long refreshAttemptDelayMillis = mTryAgainCounter > 0
? mShortPollingIntervalMillis : mNormalPollingIntervalMillis;
+
+ // The refresh attempt delay is applied to a different point in time depending on
+ // whether a refresh attempt is overdue to ensure the refresh attempt scheduling
+ // acts correctly / safely, i.e. won't schedule actions for immediate execution or
+ // in the past.
long nextRefreshElapsedRealtimeMillis;
- if (latestTimeResultAgeMillis < mNormalPollingIntervalMillis) {
- // The latest time result is fresh, use it to determine when next to refresh.
+ if (latestTimeResultAgeMillis < refreshAttemptDelayMillis) {
+ // The latestTimeResultAgeMillis and refreshAttemptDelayMillis indicate a
+ // refresh attempt is not yet due. This branch uses the elapsed realtime of the
+ // latest time result to calculate when the latest time result will become too
+ // old and the next refresh attempt will be due.
+ //
+ // Possibilities:
+ // + A refresh was attempted and successful, mTryAgainCounter will be set
+ // to 0, refreshAttemptDelayMillis == mNormalPollingIntervalMillis, and this
+ // branch will execute.
+ // + No refresh was attempted, but something else refreshed the latest time
+ // result held by the NtpTrustedTime.
+ //
+ // If a refresh was attempted but was unsuccessful, latestTimeResultAgeMillis >=
+ // mNormalPollingIntervalMillis (because otherwise it wouldn't be attempted),
+ // this branch won't be executed, and the one below will be instead.
nextRefreshElapsedRealtimeMillis =
- latestTimeResult.getElapsedRealtimeMillis() + refreshDelayMillis;
+ latestTimeResult.getElapsedRealtimeMillis() + refreshAttemptDelayMillis;
} else if (mLastRefreshAttemptElapsedRealtimeMillis != null) {
- // The latest time result is missing or old and still needs to be refreshed.
- // mLastRefreshAttemptElapsedRealtimeMillis, which should always be set by this
- // point because there's no fresh time result, should be very close to
- // currentElapsedRealtimeMillis unless the refresh was not allowed.
+ // This branch is executed when the latest time result is missing, or it's older
+ // than refreshAttemptDelayMillis. There may already have been attempts to
+ // refresh the network time that have failed, so the important point for this
+ // branch is not how old the latest time result is, but when the last refresh
+ // attempt took place:
+ // + If a refresh was just attempted (and failed), then
+ // mLastRefreshAttemptElapsedRealtimeMillis will be close to
+ // currentElapsedRealtimeMillis.
+ // + If a refresh was not just attempted, for a refresh not to have been
+ // attempted EITHER:
+ // + The latest time result must be < mNormalPollingIntervalMillis ago
+ // (would be handled by the branch above)
+ // + A refresh wasn't allowed because {time since last refresh attempt}
+ // < mShortPollingIntervalMillis, so
+ // (mLastRefreshAttemptElapsedRealtimeMillis + refreshAttemptDelayMillis)
+ // would have to be in the future regardless of the
+ // refreshAttemptDelayMillis value. This ignores the execution time
+ // between the "current time" used to work out whether a refresh needed to
+ // happen, and "current time" used to compute the last time result age,
+ // but a single short interval shouldn't matter.
nextRefreshElapsedRealtimeMillis =
- mLastRefreshAttemptElapsedRealtimeMillis + refreshDelayMillis;
+ mLastRefreshAttemptElapsedRealtimeMillis + refreshAttemptDelayMillis;
} else {
- // This should not happen: mLastRefreshAttemptElapsedRealtimeMillis should
- // always be non-null by this point.
- logToDebugAndDumpsys(
- "mLastRefreshAttemptElapsedRealtimeMillis unexpectedly missing."
- + " Scheduling using currentElapsedRealtimeMillis");
+ // This branch should never execute: mLastRefreshAttemptElapsedRealtimeMillis
+ // should always be non-null because a refresh should always be attempted at
+ // least once above. Regardelss, the calculation below should result in safe
+ // scheduling behavior.
+ String logMsg = "mLastRefreshAttemptElapsedRealtimeMillis unexpectedly missing."
+ + " Scheduling using currentElapsedRealtimeMillis";
+ Log.w(TAG, logMsg);
+ logToDebugAndDumpsys(logMsg);
nextRefreshElapsedRealtimeMillis =
- currentElapsedRealtimeMillis + refreshDelayMillis;
+ currentElapsedRealtimeMillis + refreshAttemptDelayMillis;
+ }
+
+ // Defensive coding to guard against bad scheduling / logic errors above: Try to
+ // ensure that alarms aren't scheduled in the past.
+ if (nextRefreshElapsedRealtimeMillis <= currentElapsedRealtimeMillis) {
+ String logMsg = "nextRefreshElapsedRealtimeMillis is a time in the past."
+ + " Scheduling using currentElapsedRealtimeMillis instead";
+ Log.w(TAG, logMsg);
+ logToDebugAndDumpsys(logMsg);
+ nextRefreshElapsedRealtimeMillis =
+ currentElapsedRealtimeMillis + refreshAttemptDelayMillis;
}
refreshCallbacks.scheduleNextRefresh(nextRefreshElapsedRealtimeMillis);
@@ -562,7 +606,7 @@ public class NetworkTimeUpdateService extends Binder {
+ formatElapsedRealtimeMillis(currentElapsedRealtimeMillis)
+ ", latestTimeResult=" + latestTimeResult
+ ", mTryAgainCounter=" + mTryAgainCounter
- + ", refreshDelayMillis=" + refreshDelayMillis
+ + ", refreshAttemptDelayMillis=" + refreshAttemptDelayMillis
+ ", nextRefreshElapsedRealtimeMillis="
+ formatElapsedRealtimeMillis(nextRefreshElapsedRealtimeMillis));
}
@@ -592,6 +636,12 @@ public class NetworkTimeUpdateService extends Binder {
return currentElapsedRealtimeMillis >= nextRefreshAllowedElapsedRealtimeMillis;
}
+ /**
+ * Attempts a network time refresh. Updates {@link
+ * #mLastRefreshAttemptElapsedRealtimeMillis} regardless of the outcome and returns whether
+ * the attempt was successful. The latest successful refresh result can be found in {@link
+ * NtpTrustedTime#getCachedTimeResult()}.
+ */
private boolean tryRefresh(@NonNull Network network) {
long currentElapsedRealtimeMillis = mElapsedRealtimeMillisSupplier.get();
synchronized (this) {
@@ -600,15 +650,18 @@ public class NetworkTimeUpdateService extends Binder {
return mNtpTrustedTime.forceRefresh(network);
}
- /** Suggests the time to the time detector. It may choose use it to set the system clock. */
- private void makeNetworkTimeSuggestion(@NonNull TimeResult ntpResult,
+ /**
+ * Suggests the network time to the time detector. It may choose use it to set the system
+ * clock.
+ */
+ private void makeNetworkTimeSuggestion(@NonNull TimeResult timeResult,
@NonNull String debugInfo, @NonNull RefreshCallbacks refreshCallbacks) {
UnixEpochTime timeSignal = new UnixEpochTime(
- ntpResult.getElapsedRealtimeMillis(), ntpResult.getTimeMillis());
+ timeResult.getElapsedRealtimeMillis(), timeResult.getTimeMillis());
NetworkTimeSuggestion timeSuggestion =
- new NetworkTimeSuggestion(timeSignal, ntpResult.getUncertaintyMillis());
+ new NetworkTimeSuggestion(timeSignal, timeResult.getUncertaintyMillis());
timeSuggestion.addDebugInfo(debugInfo);
- timeSuggestion.addDebugInfo(ntpResult.toString());
+ timeSuggestion.addDebugInfo(timeResult.toString());
refreshCallbacks.submitSuggestion(timeSuggestion);
}
diff --git a/services/core/java/com/android/server/timedetector/NetworkTimeUpdateServiceShellCommand.java b/services/core/java/com/android/server/timedetector/NetworkTimeUpdateServiceShellCommand.java
index afc0bdd30f29..cfc95df1ef15 100644
--- a/services/core/java/com/android/server/timedetector/NetworkTimeUpdateServiceShellCommand.java
+++ b/services/core/java/com/android/server/timedetector/NetworkTimeUpdateServiceShellCommand.java
@@ -37,11 +37,6 @@ class NetworkTimeUpdateServiceShellCommand extends ShellCommand {
private static final String SHELL_COMMAND_SERVICE_NAME = "network_time_update_service";
/**
- * A shell command that clears the time signal received from the network.
- */
- private static final String SHELL_COMMAND_CLEAR_TIME = "clear_time";
-
- /**
* A shell command that forces the time signal to be refreshed from the network.
*/
private static final String SHELL_COMMAND_FORCE_REFRESH = "force_refresh";
@@ -73,8 +68,6 @@ class NetworkTimeUpdateServiceShellCommand extends ShellCommand {
}
switch (cmd) {
- case SHELL_COMMAND_CLEAR_TIME:
- return runClearTime();
case SHELL_COMMAND_FORCE_REFRESH:
return runForceRefresh();
case SHELL_COMMAND_SET_SERVER_CONFIG:
@@ -87,11 +80,6 @@ class NetworkTimeUpdateServiceShellCommand extends ShellCommand {
}
}
- private int runClearTime() {
- mNetworkTimeUpdateService.clearTimeForTests();
- return 0;
- }
-
private int runForceRefresh() {
boolean success = mNetworkTimeUpdateService.forceRefreshForTests();
getOutPrintWriter().println(success);
@@ -147,8 +135,6 @@ class NetworkTimeUpdateServiceShellCommand extends ShellCommand {
pw.printf("Network Time Update Service (%s) commands:\n", SHELL_COMMAND_SERVICE_NAME);
pw.printf(" help\n");
pw.printf(" Print this help text.\n");
- pw.printf(" %s\n", SHELL_COMMAND_CLEAR_TIME);
- pw.printf(" Clears the latest time.\n");
pw.printf(" %s\n", SHELL_COMMAND_FORCE_REFRESH);
pw.printf(" Refreshes the latest time. Prints whether it was successful.\n");
pw.printf(" %s\n", SHELL_COMMAND_SET_SERVER_CONFIG);
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorService.java b/services/core/java/com/android/server/timedetector/TimeDetectorService.java
index 0da967a3bc00..22f096b11f18 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorService.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorService.java
@@ -37,6 +37,7 @@ import android.os.ParcelableException;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ShellCallback;
+import android.os.SystemClock;
import android.util.ArrayMap;
import android.util.IndentingPrintWriter;
import android.util.NtpTrustedTime;
@@ -53,6 +54,7 @@ import com.android.server.timezonedetector.CurrentUserIdentityInjector;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.net.InetSocketAddress;
import java.time.DateTimeException;
import java.util.Objects;
@@ -377,7 +379,7 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub
*
* <p>This operation takes place in the calling thread.
*/
- void clearNetworkTime() {
+ void clearLatestNetworkTime() {
enforceSuggestNetworkTimePermission();
final long token = Binder.clearCallingIdentity();
@@ -390,12 +392,29 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub
@Override
public UnixEpochTime latestNetworkTime() {
- NetworkTimeSuggestion suggestion = getLatestNetworkSuggestion();
- if (suggestion != null) {
- return suggestion.getUnixEpochTime();
+ NetworkTimeSuggestion latestNetworkTime;
+ // TODO(b/222295093): Remove this condition once we can be sure that all uses of
+ // NtpTrustedTime result in a suggestion being made to the time detector.
+ // mNtpTrustedTime can be removed once this happens.
+ if (TimeDetectorNetworkTimeHelper.isInUse()) {
+ // The new implementation.
+ latestNetworkTime = mTimeDetectorStrategy.getLatestNetworkSuggestion();
} else {
+ // The old implementation.
+ NtpTrustedTime.TimeResult ntpResult = mNtpTrustedTime.getCachedTimeResult();
+ if (ntpResult != null) {
+ latestNetworkTime = new NetworkTimeSuggestion(
+ new UnixEpochTime(
+ ntpResult.getElapsedRealtimeMillis(), ntpResult.getTimeMillis()),
+ ntpResult.getUncertaintyMillis());
+ } else {
+ latestNetworkTime = null;
+ }
+ }
+ if (latestNetworkTime == null) {
throw new ParcelableException(new DateTimeException("Missing network time fix"));
}
+ return latestNetworkTime.getUnixEpochTime();
}
/**
@@ -403,23 +422,7 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub
*/
@Nullable
NetworkTimeSuggestion getLatestNetworkSuggestion() {
- // TODO(b/222295093): Return the latest network time from mTimeDetectorStrategy once we can
- // be sure that all uses of NtpTrustedTime results in a suggestion being made to the time
- // detector. mNtpTrustedTime can be removed once this happens.
- if (TimeDetectorNetworkTimeHelper.isInUse()) {
- // The new implementation.
- return mTimeDetectorStrategy.getLatestNetworkSuggestion();
- } else {
- // The old implementation.
- NtpTrustedTime.TimeResult ntpResult = mNtpTrustedTime.getCachedTimeResult();
- if (ntpResult != null) {
- UnixEpochTime unixEpochTime = new UnixEpochTime(
- ntpResult.getElapsedRealtimeMillis(), ntpResult.getTimeMillis());
- return new NetworkTimeSuggestion(unixEpochTime, ntpResult.getUncertaintyMillis());
- } else {
- return null;
- }
- }
+ return mTimeDetectorStrategy.getLatestNetworkSuggestion();
}
/**
@@ -440,6 +443,57 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub
mHandler.post(() -> mTimeDetectorStrategy.suggestExternalTime(timeSignal));
}
+ /**
+ * Sets the network time for testing {@link SystemClock#currentNetworkTimeClock()}.
+ *
+ * <p>This operation takes place in the calling thread.
+ */
+ void setNetworkTimeForSystemClockForTests(
+ @NonNull UnixEpochTime unixEpochTime, int uncertaintyMillis) {
+ enforceSuggestNetworkTimePermission();
+
+ // TODO(b/222295093): Remove this condition once we can be sure that all uses of
+ // NtpTrustedTime result in a suggestion being made to the time detector.
+ // mNtpTrustedTime can be removed once this happens.
+ if (TimeDetectorNetworkTimeHelper.isInUse()) {
+ NetworkTimeSuggestion suggestion =
+ new NetworkTimeSuggestion(unixEpochTime, uncertaintyMillis);
+ suggestion.addDebugInfo("Injected for tests");
+ mTimeDetectorStrategy.suggestNetworkTime(suggestion);
+ } else {
+ NtpTrustedTime.TimeResult timeResult = new NtpTrustedTime.TimeResult(
+ unixEpochTime.getUnixEpochTimeMillis(),
+ unixEpochTime.getElapsedRealtimeMillis(),
+ uncertaintyMillis,
+ InetSocketAddress.createUnresolved("time.set.for.tests", 123));
+ mNtpTrustedTime.setCachedTimeResult(timeResult);
+ }
+ }
+
+ /**
+ * Clears the network time for testing {@link SystemClock#currentNetworkTimeClock()}.
+ *
+ * <p>This operation takes place in the calling thread.
+ */
+ void clearNetworkTimeForSystemClockForTests() {
+ enforceSuggestNetworkTimePermission();
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ // TODO(b/222295093): Remove this condition once we can be sure that all uses of
+ // NtpTrustedTime result in a suggestion being made to the time detector.
+ // mNtpTrustedTime can be removed once this happens.
+ if (TimeDetectorNetworkTimeHelper.isInUse()) {
+ // Clear the latest network suggestion. Done in all c
+ mTimeDetectorStrategy.clearLatestNetworkSuggestion();
+ } else {
+ mNtpTrustedTime.clearCachedTimeResult();
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
@Override
protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw,
@Nullable String[] args) {
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorShellCommand.java b/services/core/java/com/android/server/timedetector/TimeDetectorShellCommand.java
index cce570986168..fe0127fc11f2 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorShellCommand.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorShellCommand.java
@@ -16,12 +16,14 @@
package com.android.server.timedetector;
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_CLEAR_NETWORK_TIME;
+import static android.app.timedetector.TimeDetector.SHELL_COMMAND_CLEAR_SYSTEM_CLOCK_NETWORK_TIME;
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_CONFIRM_TIME;
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_GET_NETWORK_TIME;
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_GET_TIME_STATE;
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_IS_AUTO_DETECTION_ENABLED;
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SERVICE_NAME;
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SET_AUTO_DETECTION_ENABLED;
+import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SET_SYSTEM_CLOCK_NETWORK_TIME;
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SET_TIME_STATE;
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SUGGEST_EXTERNAL_TIME;
import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SUGGEST_GNSS_TIME;
@@ -73,9 +75,9 @@ class TimeDetectorShellCommand extends ShellCommand {
case SHELL_COMMAND_SUGGEST_NETWORK_TIME:
return runSuggestNetworkTime();
case SHELL_COMMAND_GET_NETWORK_TIME:
- return runGetNetworkTime();
+ return runGetLatestNetworkTime();
case SHELL_COMMAND_CLEAR_NETWORK_TIME:
- return runClearNetworkTime();
+ return runClearLatestNetworkTime();
case SHELL_COMMAND_SUGGEST_GNSS_TIME:
return runSuggestGnssTime();
case SHELL_COMMAND_SUGGEST_EXTERNAL_TIME:
@@ -86,6 +88,10 @@ class TimeDetectorShellCommand extends ShellCommand {
return runSetTimeState();
case SHELL_COMMAND_CONFIRM_TIME:
return runConfirmTime();
+ case SHELL_COMMAND_CLEAR_SYSTEM_CLOCK_NETWORK_TIME:
+ return runClearSystemClockNetworkTime();
+ case SHELL_COMMAND_SET_SYSTEM_CLOCK_NETWORK_TIME:
+ return runSetSystemClockNetworkTime();
default: {
return handleDefaultCommands(cmd);
}
@@ -128,15 +134,15 @@ class TimeDetectorShellCommand extends ShellCommand {
mInterface::suggestNetworkTime);
}
- private int runGetNetworkTime() {
+ private int runGetLatestNetworkTime() {
NetworkTimeSuggestion networkTimeSuggestion = mInterface.getLatestNetworkSuggestion();
final PrintWriter pw = getOutPrintWriter();
pw.println(networkTimeSuggestion);
return 0;
}
- private int runClearNetworkTime() {
- mInterface.clearNetworkTime();
+ private int runClearLatestNetworkTime() {
+ mInterface.clearLatestNetworkTime();
return 0;
}
@@ -187,6 +193,20 @@ class TimeDetectorShellCommand extends ShellCommand {
return 0;
}
+ private int runClearSystemClockNetworkTime() {
+ mInterface.clearNetworkTimeForSystemClockForTests();
+ return 0;
+ }
+
+ private int runSetSystemClockNetworkTime() {
+ NetworkTimeSuggestion networkTimeSuggestion =
+ NetworkTimeSuggestion.parseCommandLineArg(this);
+ mInterface.setNetworkTimeForSystemClockForTests(
+ networkTimeSuggestion.getUnixEpochTime(),
+ networkTimeSuggestion.getUncertaintyMillis());
+ return 0;
+ }
+
@Override
public void onHelp() {
final PrintWriter pw = getOutPrintWriter();
@@ -218,6 +238,16 @@ class TimeDetectorShellCommand extends ShellCommand {
pw.printf(" Prints the network time information held by the detector.\n");
pw.printf(" %s\n", SHELL_COMMAND_CLEAR_NETWORK_TIME);
pw.printf(" Clears the network time information held by the detector.\n");
+ // TODO(b/222295093) Remove these "system_clock" commands when
+ // SystemClock.currentNetworkTimeClock() is guaranteed to use the latest network
+ // suggestion. Then, commands above can be used instead.
+ pw.printf(" %s <network suggestion opts>\n",
+ SHELL_COMMAND_SET_SYSTEM_CLOCK_NETWORK_TIME);
+ pw.printf(" Sets the network time information used for"
+ + " SystemClock.currentNetworkTimeClock().\n");
+ pw.printf(" %s\n", SHELL_COMMAND_CLEAR_SYSTEM_CLOCK_NETWORK_TIME);
+ pw.printf(" Clears the network time information used for"
+ + " SystemClock.currentNetworkTimeClock().\n");
pw.println();
ManualTimeSuggestion.printCommandLineOpts(pw);
pw.println();
diff --git a/services/core/java/com/android/server/utils/Slogf.java b/services/core/java/com/android/server/utils/Slogf.java
index 6efbd89daf4c..a4b2bfb3a771 100644
--- a/services/core/java/com/android/server/utils/Slogf.java
+++ b/services/core/java/com/android/server/utils/Slogf.java
@@ -30,11 +30,13 @@ import java.util.Locale;
/**
* Extends {@link Slog} by providing overloaded methods that take string formatting.
*
- * <p><strong>Note: </strong>the overloaded methods won't create the formatted message if the
- * respective logging level is disabled for the tag, but the compiler will still create an
- * intermediate array of the objects for the {@code vargars}, which could affect garbage collection.
- * So, if you're calling these method in a critical path, make sure to explicitly check for the
- * level before calling them.
+ * <p><strong>Note: </strong>Like the other logging classes, e.g. {@link Log} and {@link Slog}, the
+ * methods in this class log unconditionally regardless of {@link Log#isLoggable(String, int)}.
+ * Therefore, these methods exist just for the convenience of handling formatting. (Even if they
+ * did check {@link Log#isLoggable(String, int)} before formatting and logging, calling a varargs
+ * method in Java still involves an array allocation.) If you need to avoid the overhead of logging
+ * on a performance-critical path, either don't use logging in that place, or make the logging
+ * conditional on a static boolean defaulting to false.
*/
public final class Slogf {
@@ -56,11 +58,6 @@ public final class Slogf {
throw new UnsupportedOperationException("provides only static methods");
}
- /** Same as {@link Log#isLoggable(String, int)}. */
- public static boolean isLoggable(String tag, int level) {
- return Log.isLoggable(tag, level);
- }
-
/** Same as {@link Slog#v(String, String)}. */
public static int v(String tag, String msg) {
return Slog.v(tag, msg);
@@ -146,166 +143,62 @@ public final class Slogf {
return Slog.println(priority, tag, msg);
}
- /**
- * Logs a {@link Log.VERBOSE} message.
- *
- * <p><strong>Note: </strong>the message will only be formatted if {@link Log#VERBOSE} logging
- * is enabled for the given {@code tag}, but the compiler will still create an intermediate
- * array of the objects for the {@code vargars}, which could affect garbage collection. So, if
- * you're calling this method in a critical path, make sure to explicitly do the check before
- * calling it.
- */
+ /** Logs a {@link Log.VERBOSE} message. */
public static void v(String tag, String format, @Nullable Object... args) {
- if (!isLoggable(tag, Log.VERBOSE)) return;
-
v(tag, getMessage(format, args));
}
- /**
- * Logs a {@link Log.VEBOSE} message with a throwable
- *
- * <p><strong>Note: </strong>the message will only be formatted if {@link Log#VERBOSE} logging
- * is enabled for the given {@code tag}, but the compiler will still create an intermediate
- * array of the objects for the {@code vargars}, which could affect garbage collection. So, if
- * you're calling this method in a critical path, make sure to explicitly do the check before
- * calling it.
- */
+ /** Logs a {@link Log.VERBOSE} message with a throwable. */
public static void v(String tag, Throwable throwable, String format, @Nullable Object... args) {
- if (!isLoggable(tag, Log.VERBOSE)) return;
-
v(tag, getMessage(format, args), throwable);
}
- /**
- * Logs a {@link Log.DEBUG} message.
- *
- * <p><strong>Note: </strong>the message will only be formatted if {@link Log#DEBUG} logging is
- * enabled for the given {@code tag}, but the compiler will still create an intermediate array
- * of the objects for the {@code vargars}, which could affect garbage collection. So, if you're
- * calling this method in a critical path, make sure to explicitly do the check before calling
- * it.
- */
+ /** Logs a {@link Log.DEBUG} message. */
public static void d(String tag, String format, @Nullable Object... args) {
- if (!isLoggable(tag, Log.DEBUG)) return;
-
d(tag, getMessage(format, args));
}
- /**
- * Logs a {@link Log.DEBUG} message with a throwable
- *
- * <p><strong>Note: </strong>the message will only be formatted if {@link Log#DEBUG} logging
- * is enabled for the given {@code tag}, but the compiler will still create an intermediate
- * array of the objects for the {@code vargars}, which could affect garbage collection. So, if
- * you're calling this method in a critical path, make sure to explicitly do the check before
- * calling it.
- */
+ /** Logs a {@link Log.DEBUG} message with a throwable. */
public static void d(String tag, Throwable throwable, String format, @Nullable Object... args) {
- if (!isLoggable(tag, Log.DEBUG)) return;
-
d(tag, getMessage(format, args), throwable);
}
- /**
- * Logs a {@link Log.INFO} message.
- *
- * <p><strong>Note: </strong>the message will only be formatted if {@link Log#INFO} logging is
- * enabled for the given {@code tag}, but the compiler will still create an intermediate array
- * of the objects for the {@code vargars}, which could affect garbage collection. So, if you're
- * calling this method in a critical path, make sure to explicitly do the check before calling
- * it.
- */
+ /** Logs a {@link Log.INFO} message. */
public static void i(String tag, String format, @Nullable Object... args) {
- if (!isLoggable(tag, Log.INFO)) return;
-
i(tag, getMessage(format, args));
}
- /**
- * Logs a {@link Log.INFO} message with a throwable
- *
- * <p><strong>Note: </strong>the message will only be formatted if {@link Log#INFO} logging
- * is enabled for the given {@code tag}, but the compiler will still create an intermediate
- * array of the objects for the {@code vargars}, which could affect garbage collection. So, if
- * you're calling this method in a critical path, make sure to explicitly do the check before
- * calling it.
- */
+ /** Logs a {@link Log.INFO} message with a throwable. */
public static void i(String tag, Throwable throwable, String format, @Nullable Object... args) {
- if (!isLoggable(tag, Log.INFO)) return;
-
i(tag, getMessage(format, args), throwable);
}
- /**
- * Logs a {@link Log.WARN} message.
- *
- * <p><strong>Note: </strong>the message will only be formatted if {@link Log#WARN} logging is
- * enabled for the given {@code tag}, but the compiler will still create an intermediate array
- * of the objects for the {@code vargars}, which could affect garbage collection. So, if you're
- * calling this method in a critical path, make sure to explicitly do the check before calling
- * it.
- */
+ /** Logs a {@link Log.WARN} message. */
public static void w(String tag, String format, @Nullable Object... args) {
- if (!isLoggable(tag, Log.WARN)) return;
-
w(tag, getMessage(format, args));
}
- /**
- * Logs a {@link Log.WARN} message with a throwable
- *
- * <p><strong>Note: </strong>the message will only be formatted if {@link Log#WARN} logging is
- * enabled for the given {@code tag}, but the compiler will still create an intermediate array
- * of the objects for the {@code vargars}, which could affect garbage collection. So, if you're
- * calling this method in a critical path, make sure to explicitly do the check before calling
- * it.
- */
+ /** Logs a {@link Log.WARN} message with a throwable. */
public static void w(String tag, Throwable throwable, String format, @Nullable Object... args) {
- if (!isLoggable(tag, Log.WARN)) return;
-
w(tag, getMessage(format, args), throwable);
}
- /**
- * Logs a {@link Log.ERROR} message.
- *
- * <p><strong>Note: </strong>the message will only be formatted if {@link Log#ERROR} logging is
- * enabled for the given {@code tag}, but the compiler will still create an intermediate array
- * of the objects for the {@code vargars}, which could affect garbage collection. So, if you're
- * calling this method in a critical path, make sure to explicitly do the check before calling
- * it.
- */
+ /** Logs a {@link Log.ERROR} message. */
public static void e(String tag, String format, @Nullable Object... args) {
- if (!isLoggable(tag, Log.ERROR)) return;
-
e(tag, getMessage(format, args));
}
- /**
- * Logs a {@link Log.ERROR} message with a throwable
- *
- * <p><strong>Note: </strong>the message will only be formatted if {@link Log#ERROR} logging is
- * enabled for the given {@code tag}, but the compiler will still create an intermediate array
- * of the objects for the {@code vargars}, which could affect garbage collection. So, if you're
- * calling this method in a critical path, make sure to explicitly do the check before calling
- * it.
- */
+ /** Logs a {@link Log.ERROR} message with a throwable. */
public static void e(String tag, Throwable throwable, String format, @Nullable Object... args) {
- if (!isLoggable(tag, Log.ERROR)) return;
-
e(tag, getMessage(format, args), throwable);
}
- /**
- * Logs a {@code wtf} message.
- */
+ /** Logs a {@code wtf} message. */
public static void wtf(String tag, String format, @Nullable Object... args) {
wtf(tag, getMessage(format, args));
}
- /**
- * Logs a {@code wtf} message with a throwable.
- */
+ /** Logs a {@code wtf} message with a throwable. */
public static void wtf(String tag, Throwable throwable, String format,
@Nullable Object... args) {
wtf(tag, getMessage(format, args), throwable);
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index ac03808deba1..7a733592b30c 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -945,7 +945,9 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
mWindowManagerInternal.removeWindowToken(mToken, false/* removeWindows */,
mDisplayId);
try {
- connection.mService.detach(mToken);
+ if (connection.mService != null) {
+ connection.mService.detach(mToken);
+ }
} catch (RemoteException e) {
Slog.w(TAG, "connection.mService.destroy() threw a RemoteException");
}
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index a0d8dfb2a034..9aa7e56f8877 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -19,7 +19,6 @@ package com.android.server.wm;
import static android.accessibilityservice.AccessibilityTrace.FLAGS_MAGNIFICATION_CALLBACK;
import static android.accessibilityservice.AccessibilityTrace.FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK;
import static android.os.Build.IS_USER;
-import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_EXCLUDE_FROM_SCREEN_MAGNIFICATION;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY;
@@ -85,7 +84,6 @@ import android.util.SparseBooleanArray;
import android.util.TypedValue;
import android.util.proto.ProtoOutputStream;
import android.view.Display;
-import android.view.InsetsSource;
import android.view.MagnificationSpec;
import android.view.Surface;
import android.view.Surface.OutOfResourcesException;
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index 01e9522044a1..d108f0de5d15 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -1714,4 +1714,20 @@ class ActivityClientController extends IActivityClientController.Stub {
}
}
}
+
+ /**
+ * Returns {@code true} if the activity was explicitly requested to be launched in its
+ * current TaskFragment.
+ *
+ * @see ActivityRecord#mRequestedLaunchingTaskFragmentToken
+ */
+ public boolean isRequestedToLaunchInTaskFragment(IBinder activityToken,
+ IBinder taskFragmentToken) {
+ synchronized (mGlobalLock) {
+ final ActivityRecord r = ActivityRecord.isInRootTaskLocked(activityToken);
+ if (r == null) return false;
+
+ return r.mRequestedLaunchingTaskFragmentToken == taskFragmentToken;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 89b796836617..37e4890bad0e 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -344,6 +344,7 @@ import android.window.TransitionInfo.AnimationOptions;
import android.window.WindowContainerToken;
import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ResolverActivity;
import com.android.internal.content.ReferrerIntent;
@@ -508,7 +509,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
private RemoteTransition mPendingRemoteTransition;
ActivityOptions returningOptions; // options that are coming back via convertToTranslucent
AppTimeTracker appTimeTracker; // set if we are tracking the time in this app/task/activity
+ @GuardedBy("this")
ActivityServiceConnectionsHolder mServiceConnectionsHolder; // Service connections.
+ /** @see android.content.Context#BIND_ADJUST_WITH_ACTIVITY */
+ volatile boolean mVisibleForServiceConnection;
UriPermissionOwner uriPermissions; // current special URI access perms.
WindowProcessController app; // if non-null, hosting application
private State mState; // current state we are in
@@ -557,9 +561,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
long lastLaunchTime; // time of last launch of this activity
ComponentName requestedVrComponent; // the requested component for handling VR mode.
- boolean inHistory; // are we in the history task?
+ /** Whether this activity is reachable from hierarchy. */
+ volatile boolean inHistory;
final ActivityTaskSupervisor mTaskSupervisor;
final RootWindowContainer mRootWindowContainer;
+ // The token of the TaskFragment that this activity was requested to be launched into.
+ IBinder mRequestedLaunchingTaskFragmentToken;
// Tracking splash screen status from previous activity
boolean mSplashScreenStyleSolidColor = false;
@@ -1600,6 +1607,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (oldParent != null) {
oldParent.cleanUpActivityReferences(this);
+ // Clear the state as this activity is removed from its old parent.
+ mRequestedLaunchingTaskFragmentToken = null;
}
if (newParent != null) {
@@ -1917,7 +1926,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
}
- static @Nullable ActivityRecord forTokenLocked(IBinder token) {
+ /** Gets the corresponding record by the token. Note that it may not exist in the hierarchy. */
+ @Nullable
+ static ActivityRecord forToken(IBinder token) {
if (token == null) return null;
final Token activityToken;
try {
@@ -1926,7 +1937,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
Slog.w(TAG, "Bad activity token: " + token, e);
return null;
}
- final ActivityRecord r = activityToken.mActivityRef.get();
+ return activityToken.mActivityRef.get();
+ }
+
+ static @Nullable ActivityRecord forTokenLocked(IBinder token) {
+ final ActivityRecord r = forToken(token);
return r == null || r.getRootTask() == null ? null : r;
}
@@ -4059,17 +4074,32 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
mDisplayContent.getDisplayPolicy().removeRelaunchingApp(this);
}
+ ActivityServiceConnectionsHolder getOrCreateServiceConnectionsHolder() {
+ synchronized (this) {
+ if (mServiceConnectionsHolder == null) {
+ mServiceConnectionsHolder = new ActivityServiceConnectionsHolder(this);
+ }
+ return mServiceConnectionsHolder;
+ }
+ }
+
/**
* Perform clean-up of service connections in an activity record.
*/
private void cleanUpActivityServices() {
- if (mServiceConnectionsHolder == null) {
- return;
+ synchronized (this) {
+ if (mServiceConnectionsHolder == null) {
+ return;
+ }
+ // Throw away any services that have been bound by this activity.
+ mServiceConnectionsHolder.disconnectActivityFromServices();
+ // This activity record is removing, make sure not to disconnect twice.
+ mServiceConnectionsHolder = null;
}
- // Throw away any services that have been bound by this activity.
- mServiceConnectionsHolder.disconnectActivityFromServices();
- // This activity record is removing, make sure not to disconnect twice.
- mServiceConnectionsHolder = null;
+ }
+
+ private void updateVisibleForServiceConnection() {
+ mVisibleForServiceConnection = mVisibleRequested || mState == RESUMED || mState == PAUSING;
}
/**
@@ -5155,6 +5185,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
boolean setVisibleRequested(boolean visible) {
if (!super.setVisibleRequested(visible)) return false;
setInsetsFrozen(!visible);
+ updateVisibleForServiceConnection();
if (app != null) {
mTaskSupervisor.onProcessActivityStateChanged(app, false /* forceBatch */);
}
@@ -5197,8 +5228,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
mTaskSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
}
- @VisibleForTesting
- void setVisibility(boolean visible, boolean deferHidingClient) {
+ private void setVisibility(boolean visible, boolean deferHidingClient) {
final AppTransition appTransition = getDisplayContent().mAppTransition;
// Don't set visibility to false if we were already not visible. This prevents WM from
@@ -5225,7 +5255,16 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
Debug.getCallers(6));
// Before setting mVisibleRequested so we can track changes.
- mTransitionController.collect(this);
+ boolean isCollecting = false;
+ if (mTransitionController.isShellTransitionsEnabled()) {
+ isCollecting = mTransitionController.isCollecting();
+ if (isCollecting) {
+ mTransitionController.collect(this);
+ } else {
+ Slog.e(TAG, "setVisibility=" + visible + " while transition is not collecting "
+ + this + " caller=" + Debug.getCallers(8));
+ }
+ }
onChildVisibilityRequested(visible);
@@ -5297,9 +5336,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
// Defer committing visibility until transition starts.
- if (inTransition()) {
- if (!visible && mTransitionController.inPlayingTransition(this)
- && mTransitionController.isCollecting(this)) {
+ if (isCollecting) {
+ // It may be occluded by the activity above that calls convertFromTranslucent().
+ if (!visible && mTransitionController.inPlayingTransition(this)) {
mTransitionChangeFlags |= FLAG_IS_OCCLUDED;
}
return;
@@ -5319,11 +5358,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
* Then its visibility will be committed until the transition is ready.
*/
private boolean deferCommitVisibilityChange(boolean visible) {
+ if (mTransitionController.isShellTransitionsEnabled()) {
+ // Shell transition doesn't use opening/closing sets.
+ return false;
+ }
if (!mDisplayContent.mAppTransition.isTransitionSet()) {
- if (mTransitionController.isShellTransitionsEnabled()) {
- // Shell transition doesn't use opening/closing sets.
- return false;
- }
// Defer committing visibility for non-home app which is animating by recents.
if (isActivityTypeHome() || !isAnimating(PARENTS, ANIMATION_TYPE_RECENTS)) {
return false;
@@ -5651,6 +5690,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
return;
}
}
+ updateVisibleForServiceConnection();
if (app != null) {
mTaskSupervisor.onProcessActivityStateChanged(app, false /* forceBatch */);
}
@@ -7896,7 +7936,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
return getTask().getConfiguration().smallestScreenWidthDp
- >= mAtmService.mLargeScreenSmallestScreenWidthDp;
+ >= WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP;
}
/**
@@ -7978,6 +8018,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
/**
+ * @return The {@code true} if the current instance has {@link mCompatDisplayInsets} without
+ * considering the inheritance implemented in {@link #getCompatDisplayInsets()}
+ */
+ boolean hasCompatDisplayInsetsWithoutInheritance() {
+ return mCompatDisplayInsets != null;
+ }
+
+ /**
* @return {@code true} if this activity is in size compatibility mode that uses the different
* density than its parent or its bounds don't fit in parent naturally.
*/
@@ -7985,7 +8033,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (mInSizeCompatModeForBounds) {
return true;
}
- if (mCompatDisplayInsets == null || !shouldCreateCompatDisplayInsets()
+ if (getCompatDisplayInsets() == null || !shouldCreateCompatDisplayInsets()
// The orientation is different from parent when transforming.
|| isFixedRotationTransforming()) {
return false;
@@ -8035,11 +8083,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
return false;
}
}
- // Activity should be resizable if the task is.
- final boolean isResizeable = task != null
- ? task.isResizeable() || isResizeable()
- : isResizeable();
- return !isResizeable && (info.isFixedOrientation() || hasFixedAspectRatio())
+ return !isResizeable() && (info.isFixedOrientation() || hasFixedAspectRatio())
// The configuration of non-standard type should be enforced by system.
// {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD} is set when this activity is
// added to a task, but this function is called when resolving the launch params, at
@@ -8056,11 +8100,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
private void updateCompatDisplayInsets() {
- if (mLetterboxUiController.hasInheritedLetterboxBehavior()) {
- mCompatDisplayInsets = mLetterboxUiController.getInheritedCompatDisplayInsets();
- return;
- }
- if (mCompatDisplayInsets != null || !shouldCreateCompatDisplayInsets()) {
+ if (getCompatDisplayInsets() != null || !shouldCreateCompatDisplayInsets()) {
// The override configuration is set only once in size compatibility mode.
return;
}
@@ -8123,9 +8163,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
@Override
float getCompatScale() {
- if (mLetterboxUiController.hasInheritedLetterboxBehavior()) {
- return mLetterboxUiController.getInheritedSizeCompatScale();
- }
return hasSizeCompatBounds() ? mSizeCompatScale : super.getCompatScale();
}
@@ -8172,7 +8209,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
resolveFixedOrientationConfiguration(newParentConfiguration);
}
- if (mCompatDisplayInsets != null) {
+ if (getCompatDisplayInsets() != null) {
resolveSizeCompatModeConfiguration(newParentConfiguration);
} else if (inMultiWindowMode() && !isFixedOrientationLetterboxAllowed) {
// We ignore activities' requested orientation in multi-window modes. They may be
@@ -8190,7 +8227,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
resolveAspectRatioRestriction(newParentConfiguration);
}
- if (isFixedOrientationLetterboxAllowed || mCompatDisplayInsets != null
+ if (isFixedOrientationLetterboxAllowed || getCompatDisplayInsets() != null
// In fullscreen, can be letterboxed for aspect ratio.
|| !inMultiWindowMode()) {
updateResolvedBoundsPosition(newParentConfiguration);
@@ -8198,7 +8235,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
boolean isIgnoreOrientationRequest = mDisplayContent != null
&& mDisplayContent.getIgnoreOrientationRequest();
- if (mCompatDisplayInsets == null // for size compat mode set in updateCompatDisplayInsets
+ if (getCompatDisplayInsets() == null
+ // for size compat mode set in updateCompatDisplayInsets
// Fixed orientation letterboxing is possible on both large screen devices
// with ignoreOrientationRequest enabled and on phones in split screen even with
// ignoreOrientationRequest disabled.
@@ -8244,7 +8282,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
info.neverSandboxDisplayApis(sConstrainDisplayApisConfig),
info.alwaysSandboxDisplayApis(sConstrainDisplayApisConfig),
!matchParentBounds(),
- mCompatDisplayInsets != null,
+ getCompatDisplayInsets() != null,
shouldCreateCompatDisplayInsets());
}
resolvedConfig.windowConfiguration.setMaxBounds(mTmpBounds);
@@ -8551,8 +8589,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|| orientationRespectedWithInsets)) {
return;
}
+ final CompatDisplayInsets compatDisplayInsets = getCompatDisplayInsets();
- if (mCompatDisplayInsets != null && !mCompatDisplayInsets.mIsInFixedOrientationLetterbox) {
+ if (compatDisplayInsets != null && !compatDisplayInsets.mIsInFixedOrientationLetterbox) {
// App prefers to keep its original size.
// If the size compat is from previous fixed orientation letterboxing, we may want to
// have fixed orientation letterbox again, otherwise it will show the size compat
@@ -8607,9 +8646,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
mIsAspectRatioApplied = applyAspectRatio(resolvedBounds, containingBoundsWithInsets,
containingBounds, desiredAspectRatio);
- if (mCompatDisplayInsets != null) {
- mCompatDisplayInsets.getBoundsByRotation(
- mTmpBounds, newParentConfig.windowConfiguration.getRotation());
+ if (compatDisplayInsets != null) {
+ compatDisplayInsets.getBoundsByRotation(mTmpBounds,
+ newParentConfig.windowConfiguration.getRotation());
if (resolvedBounds.width() != mTmpBounds.width()
|| resolvedBounds.height() != mTmpBounds.height()) {
// The app shouldn't be resized, we only do fixed orientation letterboxing if the
@@ -8623,7 +8662,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// Calculate app bounds using fixed orientation bounds because they will be needed later
// for comparison with size compat app bounds in {@link resolveSizeCompatModeConfiguration}.
getTaskFragment().computeConfigResourceOverrides(getResolvedOverrideConfiguration(),
- newParentConfig, mCompatDisplayInsets);
+ newParentConfig, compatDisplayInsets);
mLetterboxBoundsForFixedOrientationAndAspectRatio = new Rect(resolvedBounds);
}
@@ -8680,13 +8719,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
? requestedOrientation
// We should use the original orientation of the activity when possible to avoid
// forcing the activity in the opposite orientation.
- : mCompatDisplayInsets.mOriginalRequestedOrientation != ORIENTATION_UNDEFINED
- ? mCompatDisplayInsets.mOriginalRequestedOrientation
+ : getCompatDisplayInsets().mOriginalRequestedOrientation != ORIENTATION_UNDEFINED
+ ? getCompatDisplayInsets().mOriginalRequestedOrientation
: newParentConfiguration.orientation;
int rotation = newParentConfiguration.windowConfiguration.getRotation();
final boolean isFixedToUserRotation = mDisplayContent == null
|| mDisplayContent.getDisplayRotation().isFixedToUserRotation();
- if (!isFixedToUserRotation && !mCompatDisplayInsets.mIsFloating) {
+ if (!isFixedToUserRotation && !getCompatDisplayInsets().mIsFloating) {
// Use parent rotation because the original display can be rotated.
resolvedConfig.windowConfiguration.setRotation(rotation);
} else {
@@ -8702,11 +8741,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// rely on them to contain the original and unchanging width and height of the app.
final Rect containingAppBounds = new Rect();
final Rect containingBounds = mTmpBounds;
- mCompatDisplayInsets.getContainerBounds(containingAppBounds, containingBounds, rotation,
+ getCompatDisplayInsets().getContainerBounds(containingAppBounds, containingBounds, rotation,
orientation, orientationRequested, isFixedToUserRotation);
resolvedBounds.set(containingBounds);
// The size of floating task is fixed (only swap), so the aspect ratio is already correct.
- if (!mCompatDisplayInsets.mIsFloating) {
+ if (!getCompatDisplayInsets().mIsFloating) {
mIsAspectRatioApplied =
applyAspectRatio(resolvedBounds, containingAppBounds, containingBounds);
}
@@ -8715,7 +8754,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// are calculated in compat container space. The actual position on screen will be applied
// later, so the calculation is simpler that doesn't need to involve offset from parent.
getTaskFragment().computeConfigResourceOverrides(resolvedConfig, newParentConfiguration,
- mCompatDisplayInsets);
+ getCompatDisplayInsets());
// Use current screen layout as source because the size of app is independent to parent.
resolvedConfig.screenLayout = computeScreenLayout(
getConfiguration().screenLayout, resolvedConfig.screenWidthDp,
@@ -8750,14 +8789,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// Calculates the scale the size compatibility bounds into the region which is available
// to application.
- final int contentW = resolvedAppBounds.width();
- final int contentH = resolvedAppBounds.height();
- final int viewportW = containerAppBounds.width();
- final int viewportH = containerAppBounds.height();
final float lastSizeCompatScale = mSizeCompatScale;
- // Only allow to scale down.
- mSizeCompatScale = (contentW <= viewportW && contentH <= viewportH)
- ? 1f : Math.min((float) viewportW / contentW, (float) viewportH / contentH);
+ updateSizeCompatScale(resolvedAppBounds, containerAppBounds);
+
final int containerTopInset = containerAppBounds.top - containerBounds.top;
final boolean topNotAligned =
containerTopInset != resolvedAppBounds.top - resolvedBounds.top;
@@ -8797,6 +8831,20 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
isInSizeCompatModeForBounds(resolvedAppBounds, containerAppBounds);
}
+ void updateSizeCompatScale(Rect resolvedAppBounds, Rect containerAppBounds) {
+ // Only allow to scale down.
+ mSizeCompatScale = mLetterboxUiController.findOpaqueNotFinishingActivityBelow()
+ .map(activityRecord -> activityRecord.mSizeCompatScale)
+ .orElseGet(() -> {
+ final int contentW = resolvedAppBounds.width();
+ final int contentH = resolvedAppBounds.height();
+ final int viewportW = containerAppBounds.width();
+ final int viewportH = containerAppBounds.height();
+ return (contentW <= viewportW && contentH <= viewportH) ? 1f : Math.min(
+ (float) viewportW / contentW, (float) viewportH / contentH);
+ });
+ }
+
private boolean isInSizeCompatModeForBounds(final Rect appBounds, final Rect containerBounds) {
if (mLetterboxUiController.hasInheritedLetterboxBehavior()) {
// To avoid wrong app behaviour, we decided to disable SCM when a translucent activity
@@ -8859,10 +8907,16 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
@Override
public Rect getBounds() {
- if (mSizeCompatBounds != null) {
- return mSizeCompatBounds;
- }
- return super.getBounds();
+ // TODO(b/268458693): Refactor configuration inheritance in case of translucent activities
+ final Rect superBounds = super.getBounds();
+ return mLetterboxUiController.findOpaqueNotFinishingActivityBelow()
+ .map(ActivityRecord::getBounds)
+ .orElseGet(() -> {
+ if (mSizeCompatBounds != null) {
+ return mSizeCompatBounds;
+ }
+ return superBounds;
+ });
}
@Override
@@ -8887,7 +8941,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// Max bounds should be sandboxed when an activity should have compatDisplayInsets, and it
// will keep the same bounds and screen configuration when it was first launched regardless
// how its parent window changes, so that the sandbox API will provide a consistent result.
- if (mCompatDisplayInsets != null || shouldCreateCompatDisplayInsets()) {
+ if (getCompatDisplayInsets() != null || shouldCreateCompatDisplayInsets()) {
return true;
}
@@ -8929,7 +8983,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
mTransitionController.collect(this);
}
}
- if (mCompatDisplayInsets != null) {
+ if (getCompatDisplayInsets() != null) {
Configuration overrideConfig = getRequestedOverrideConfiguration();
// Adapt to changes in orientation locking. The app is still non-resizable, but
// it can change which orientation is fixed. If the fixed orientation changes,
@@ -9005,7 +9059,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (mVisibleRequested) {
// It may toggle the UI for user to restart the size compatibility mode activity.
display.handleActivitySizeCompatModeIfNeeded(this);
- } else if (mCompatDisplayInsets != null && !visibleIgnoringKeyguard
+ } else if (getCompatDisplayInsets() != null && !visibleIgnoringKeyguard
&& (app == null || !app.hasVisibleActivities())) {
// visibleIgnoringKeyguard is checked to avoid clearing mCompatDisplayInsets during
// displays change. Displays are turned off during the change so mVisibleRequested
diff --git a/services/core/java/com/android/server/wm/ActivitySecurityModelFeatureFlags.java b/services/core/java/com/android/server/wm/ActivitySecurityModelFeatureFlags.java
index 91c4a2ff03e0..1f7af41df6e0 100644
--- a/services/core/java/com/android/server/wm/ActivitySecurityModelFeatureFlags.java
+++ b/services/core/java/com/android/server/wm/ActivitySecurityModelFeatureFlags.java
@@ -42,6 +42,9 @@ class ActivitySecurityModelFeatureFlags {
// TODO(b/230590090): Replace with public documentation once ready
static final String DOC_LINK = "go/android-asm";
+ /** Used to determine which version of the ASM logic was used in logs while we iterate */
+ static final int ASM_VERSION = 6;
+
private static final String NAMESPACE = NAMESPACE_WINDOW_MANAGER;
private static final String KEY_ASM_PREFIX = "ActivitySecurity__";
private static final String KEY_ASM_RESTRICTIONS_ENABLED = KEY_ASM_PREFIX
diff --git a/services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java b/services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java
index 0859d40c0fd1..5f56af7fd4e0 100644
--- a/services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java
+++ b/services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java
@@ -16,14 +16,14 @@
package com.android.server.wm;
-import static com.android.server.wm.ActivityRecord.State.PAUSING;
-import static com.android.server.wm.ActivityRecord.State.RESUMED;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import android.util.ArraySet;
import android.util.Slog;
+import com.android.internal.annotations.GuardedBy;
+
import java.io.PrintWriter;
import java.util.function.Consumer;
@@ -38,8 +38,6 @@ import java.util.function.Consumer;
*/
public class ActivityServiceConnectionsHolder<T> {
- private final ActivityTaskManagerService mService;
-
/** The activity the owns this service connection object. */
private final ActivityRecord mActivity;
@@ -49,19 +47,19 @@ public class ActivityServiceConnectionsHolder<T> {
* on the WM side since we don't perform operations on the object. Mainly here for communication
* and booking with the AM side.
*/
+ @GuardedBy("mActivity")
private ArraySet<T> mConnections;
/** Whether all connections of {@link #mActivity} are being removed. */
private volatile boolean mIsDisconnecting;
- ActivityServiceConnectionsHolder(ActivityTaskManagerService service, ActivityRecord activity) {
- mService = service;
+ ActivityServiceConnectionsHolder(ActivityRecord activity) {
mActivity = activity;
}
/** Adds a connection record that the activity has bound to a specific service. */
public void addConnection(T c) {
- synchronized (mService.mGlobalLock) {
+ synchronized (mActivity) {
if (mIsDisconnecting) {
// This is unlikely to happen because the caller should create a new holder.
if (DEBUG_CLEANUP) {
@@ -79,7 +77,7 @@ public class ActivityServiceConnectionsHolder<T> {
/** Removed a connection record between the activity and a specific service. */
public void removeConnection(T c) {
- synchronized (mService.mGlobalLock) {
+ synchronized (mActivity) {
if (mConnections == null) {
return;
}
@@ -90,20 +88,18 @@ public class ActivityServiceConnectionsHolder<T> {
}
}
+ /** @see android.content.Context#BIND_ADJUST_WITH_ACTIVITY */
public boolean isActivityVisible() {
- synchronized (mService.mGlobalLock) {
- return mActivity.isVisibleRequested() || mActivity.isState(RESUMED, PAUSING);
- }
+ return mActivity.mVisibleForServiceConnection;
}
public int getActivityPid() {
- synchronized (mService.mGlobalLock) {
- return mActivity.hasProcess() ? mActivity.app.getPid() : -1;
- }
+ final WindowProcessController wpc = mActivity.app;
+ return wpc != null ? wpc.getPid() : -1;
}
public void forEachConnection(Consumer<T> consumer) {
- synchronized (mService.mGlobalLock) {
+ synchronized (mActivity) {
if (mConnections == null || mConnections.isEmpty()) {
return;
}
@@ -118,6 +114,7 @@ public class ActivityServiceConnectionsHolder<T> {
* general, this method is used to clean up if the activity didn't unbind services before it
* is destroyed.
*/
+ @GuardedBy("mActivity")
void disconnectActivityFromServices() {
if (mConnections == null || mConnections.isEmpty() || mIsDisconnecting) {
return;
@@ -130,16 +127,14 @@ public class ActivityServiceConnectionsHolder<T> {
// still in the message queue, so keep the reference of {@link #mConnections} to make sure
// the connection list is up-to-date.
mIsDisconnecting = true;
- mService.mH.post(() -> {
- mService.mAmInternal.disconnectActivityFromServices(this);
+ mActivity.mAtmService.mH.post(() -> {
+ mActivity.mAtmService.mAmInternal.disconnectActivityFromServices(this);
mIsDisconnecting = false;
});
}
public void dump(PrintWriter pw, String prefix) {
- synchronized (mService.mGlobalLock) {
- pw.println(prefix + "activity=" + mActivity);
- }
+ pw.println(prefix + "activity=" + mActivity);
}
/** Used by {@link ActivityRecord#dump}. */
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 32dac49102bd..88d10866d776 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -60,7 +60,6 @@ import static android.window.TaskFragmentOperation.OP_TYPE_START_ACTIVITY_IN_TAS
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_TASKS;
-import static com.android.server.wm.ActivityRecord.State.FINISHING;
import static com.android.server.wm.ActivityRecord.State.RESUMED;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RESULTS;
@@ -75,6 +74,7 @@ import static com.android.server.wm.ActivityTaskManagerService.ANIMATE;
import static com.android.server.wm.ActivityTaskSupervisor.DEFER_RESUME;
import static com.android.server.wm.ActivityTaskSupervisor.ON_TOP;
import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
+import static com.android.server.wm.ActivityTaskSupervisor.getApplicationLabel;
import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_ALLOWLISTED_COMPONENT;
import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_ALLOWLISTED_UID;
import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_DEFAULT;
@@ -83,6 +83,7 @@ import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_
import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_SAW_PERMISSION;
import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_VISIBLE_WINDOW;
import static com.android.server.wm.BackgroundActivityStartController.BAL_BLOCK;
+import static com.android.server.wm.BackgroundActivityStartController.balCodeToString;
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_BOUNDS;
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_DISPLAY;
import static com.android.server.wm.Task.REPARENT_MOVE_ROOT_TASK_TO_FRONT;
@@ -150,6 +151,9 @@ import com.android.server.wm.TaskFragment.EmbeddingCheckResult;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.util.Date;
+import java.util.StringJoiner;
+import java.util.function.Consumer;
+import java.util.function.Function;
import java.util.function.Predicate;
/**
@@ -1944,9 +1948,13 @@ class ActivityStarter {
boolean passesAsmChecks = true;
Task sourceTask = mSourceRecord.getTask();
- // Don't allow launches into a new task if the current task is not foreground.
+ // Allow launching into a new task (or a task matching the launched activity's
+ // affinity) only if the current task is foreground or mutating its own task.
+ // The latter can happen eg. if caller uses NEW_TASK flag and the activity being
+ // launched matches affinity of source task.
if (taskToFront) {
- passesAsmChecks = sourceTask != null && sourceTask.isVisible();
+ passesAsmChecks = sourceTask != null
+ && (sourceTask.isVisible() || sourceTask == targetTask);
}
if (passesAsmChecks) {
@@ -1967,8 +1975,7 @@ class ActivityStarter {
// ASM rules have failed. Log why
ActivityRecord targetTopActivity = targetTask == null ? null
- : targetTask.getActivity(ar ->
- !ar.isState(FINISHING) && !ar.isAlwaysOnTop());
+ : targetTask.getActivity(ar -> !ar.finishing && !ar.isAlwaysOnTop());
int action = newTask || mSourceRecord == null
? FrameworkStatsLog.ACTIVITY_ACTION_BLOCKED__ACTION__ACTIVITY_START_NEW_TASK
@@ -1999,7 +2006,7 @@ class ActivityStarter {
/* action */
action,
/* version */
- 4,
+ ActivitySecurityModelFeatureFlags.ASM_VERSION,
/* multi_window - we have our source not in the target task, but both are visible */
targetTask != null && mSourceRecord != null
&& !targetTask.equals(mSourceRecord.getTask()) && targetTask.isVisible(),
@@ -2011,22 +2018,26 @@ class ActivityStarter {
.shouldRestrictActivitySwitch(mCallingUid)
&& shouldBlockActivityStart;
+ String launchedFromPackageName = r.launchedFromPackage;
if (ActivitySecurityModelFeatureFlags.shouldShowToast(mCallingUid)) {
+ String toastText = ActivitySecurityModelFeatureFlags.DOC_LINK
+ + (blockActivityStartAndFeatureEnabled ? " blocked " : " would block ")
+ + getApplicationLabel(mService.mContext.getPackageManager(),
+ launchedFromPackageName);
UiThread.getHandler().post(() -> Toast.makeText(mService.mContext,
- "Activity start from " + r.launchedFromPackage
- + (blockActivityStartAndFeatureEnabled ? " " : " would be ")
- + "blocked by " + ActivitySecurityModelFeatureFlags.DOC_LINK,
- Toast.LENGTH_SHORT).show());
- }
+ toastText, Toast.LENGTH_LONG).show());
+ logDebugInfoForActivitySecurity("Launch", r, targetTask, targetTopActivity,
+ blockActivityStartAndFeatureEnabled, /* taskToFront */ taskToFront);
+ }
if (blockActivityStartAndFeatureEnabled) {
- Slog.e(TAG, "Abort Launching r: " + r
+ Slog.e(TAG, "[ASM] Abort Launching r: " + r
+ " as source: "
- + (mSourceRecord != null ? mSourceRecord : r.launchedFromPackage)
+ + (mSourceRecord != null ? mSourceRecord : launchedFromPackageName)
+ " is in background. New task: " + newTask
+ ". Top activity: " + targetTopActivity
- + ". BAL Code: " + mBalCode);
+ + ". BAL Code: " + balCodeToString(mBalCode));
return false;
}
@@ -2034,6 +2045,71 @@ class ActivityStarter {
return true;
}
+ /** Only called when an activity launch may be blocked, which should happen very rarely */
+ private void logDebugInfoForActivitySecurity(String action, ActivityRecord r, Task targetTask,
+ ActivityRecord targetTopActivity, boolean blockActivityStartAndFeatureEnabled,
+ boolean taskToFront) {
+ final String prefix = "[ASM] ";
+ Function<ActivityRecord, String> recordToString = (ar) -> {
+ if (ar == null) {
+ return null;
+ }
+ return (ar == mSourceRecord ? " [source]=> "
+ : ar == targetTopActivity ? " [ top ]=> "
+ : ar == r ? " [target]=> "
+ : " => ")
+ + ar
+ + " :: visible=" + ar.isVisible()
+ + ", finishing=" + ar.isFinishing()
+ + ", alwaysOnTop=" + ar.isAlwaysOnTop()
+ + ", taskFragment=" + ar.getTaskFragment();
+ };
+
+ StringJoiner joiner = new StringJoiner("\n");
+ joiner.add(prefix + "------ Activity Security " + action + " Debug Logging Start ------");
+ joiner.add(prefix + "Block Enabled: " + blockActivityStartAndFeatureEnabled);
+ joiner.add(prefix + "ASM Version: " + ActivitySecurityModelFeatureFlags.ASM_VERSION);
+
+ boolean targetTaskMatchesSourceTask = targetTask != null
+ && mSourceRecord != null && mSourceRecord.getTask() == targetTask;
+
+ if (mSourceRecord == null) {
+ joiner.add(prefix + "Source Package: " + r.launchedFromPackage);
+ String realCallingPackage = mService.mContext.getPackageManager().getNameForUid(
+ mRealCallingUid);
+ joiner.add(prefix + "Real Calling Uid Package: " + realCallingPackage);
+ } else {
+ joiner.add(prefix + "Source Record: " + recordToString.apply(mSourceRecord));
+ if (targetTaskMatchesSourceTask) {
+ joiner.add(prefix + "Source/Target Task: " + mSourceRecord.getTask());
+ joiner.add(prefix + "Source/Target Task Stack: ");
+ } else {
+ joiner.add(prefix + "Source Task: " + mSourceRecord.getTask());
+ joiner.add(prefix + "Source Task Stack: ");
+ }
+ mSourceRecord.getTask().forAllActivities((Consumer<ActivityRecord>)
+ ar -> joiner.add(prefix + recordToString.apply(ar)));
+ }
+
+ joiner.add(prefix + "Target Task Top: " + recordToString.apply(targetTopActivity));
+ if (!targetTaskMatchesSourceTask) {
+ joiner.add(prefix + "Target Task: " + targetTask);
+ if (targetTask != null) {
+ joiner.add(prefix + "Target Task Stack: ");
+ targetTask.forAllActivities((Consumer<ActivityRecord>)
+ ar -> joiner.add(prefix + recordToString.apply(ar)));
+ }
+ }
+
+ joiner.add(prefix + "Target Record: " + recordToString.apply(r));
+ joiner.add(prefix + "Intent: " + mIntent);
+ joiner.add(prefix + "TaskToFront: " + taskToFront);
+ joiner.add(prefix + "BalCode: " + balCodeToString(mBalCode));
+
+ joiner.add(prefix + "------ Activity Security " + action + " Debug Logging End ------");
+ Slog.i(TAG, joiner.toString());
+ }
+
/**
* Returns whether embedding of {@code starting} is allowed.
*
@@ -2165,8 +2241,8 @@ class ActivityStarter {
return;
}
- Predicate<ActivityRecord> isLaunchingOrLaunched = ar -> !ar.finishing && (ar.isUid(
- startingUid) || ar.isUid(callingUid) || ar.isUid(realCallingUid));
+ Predicate<ActivityRecord> isLaunchingOrLaunched = ar -> !ar.finishing
+ && (ar.isUid(startingUid) || ar.isUid(callingUid) || ar.isUid(realCallingUid));
// Return early if we know for sure we won't need to clear any activities by just checking
// the top activity.
@@ -2202,7 +2278,10 @@ class ActivityStarter {
? "Top activities cleared by "
: "Top activities would be cleared by ")
+ ActivitySecurityModelFeatureFlags.DOC_LINK,
- Toast.LENGTH_SHORT).show());
+ Toast.LENGTH_LONG).show());
+
+ logDebugInfoForActivitySecurity("Clear Top", mStartActivity, targetTask, targetTaskTop,
+ shouldBlockActivityStart, /* taskToFront */ true);
}
}
@@ -2957,6 +3036,8 @@ class ActivityStarter {
int embeddingCheckResult = canEmbedActivity(mInTaskFragment, mStartActivity, task);
if (embeddingCheckResult == EMBEDDING_ALLOWED) {
newParent = mInTaskFragment;
+ mStartActivity.mRequestedLaunchingTaskFragmentToken =
+ mInTaskFragment.getFragmentToken();
} else {
// Start mStartActivity to task instead if it can't be embedded to mInTaskFragment.
sendCanNotEmbedActivityError(mInTaskFragment, embeddingCheckResult);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 8d671f768e87..923ca794e840 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -45,6 +45,7 @@ import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
import static android.content.pm.ConfigurationInfo.GL_ES_VERSION_UNDEFINED;
import static android.content.pm.PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS;
import static android.content.pm.PackageManager.FEATURE_CANT_SAVE_STATE;
+import static android.content.pm.PackageManager.FEATURE_COMPANION_DEVICE_SETUP;
import static android.content.pm.PackageManager.FEATURE_EXPANDED_PICTURE_IN_PICTURE;
import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
import static android.content.pm.PackageManager.FEATURE_LEANBACK;
@@ -65,6 +66,7 @@ import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_PIP;
+import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_LAUNCHER_CLEAR_SNAPSHOT;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION;
@@ -201,6 +203,7 @@ import android.os.Parcel;
import android.os.PowerManager;
import android.os.PowerManagerInternal;
import android.os.Process;
+import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.StrictMode;
@@ -227,7 +230,6 @@ import android.util.SparseArray;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
import android.view.IRecentsAnimationRunner;
-import android.view.IWindowFocusObserver;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationDefinition;
import android.view.WindowManager;
@@ -400,6 +402,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
volatile WindowProcessController mHeavyWeightProcess;
boolean mHasHeavyWeightFeature;
boolean mHasLeanbackFeature;
+ boolean mHasCompanionDeviceSetupFeature;
/** The process of the top most activity. */
volatile WindowProcessController mTopApp;
/**
@@ -606,7 +609,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
* Whether the device supports non-resizable in multi windowing modes.
* -1: The device doesn't support non-resizable in multi windowing modes.
* 0: The device supports non-resizable in multi windowing modes only if this is a large
- * screen (smallest width >= {@link #mLargeScreenSmallestScreenWidthDp}).
+ * screen (smallest width >= {@link WindowManager#LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP}).
* 1: The device always supports non-resizable in multi windowing modes.
*/
int mSupportsNonResizableMultiWindow;
@@ -616,7 +619,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
* windowing modes.
* -1: The device ignores activity min width/height when determining if it can be shown in multi
* windowing modes.
- * 0: If it is a small screen (smallest width < {@link #mLargeScreenSmallestScreenWidthDp}),
+ * 0: If it is a small screen (smallest width <
+ * {@link WindowManager#LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP}),
* the device compares the activity min width/height with the min multi windowing modes
* dimensions {@link #mMinPercentageMultiWindowSupportHeight} the device supports to
* determine whether the activity can be shown in multi windowing modes
@@ -644,13 +648,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
*/
float mMinPercentageMultiWindowSupportWidth;
- /**
- * If the display {@link Configuration#smallestScreenWidthDp} is greater or equal to this value,
- * we will treat it as a large screen device, which will have some multi window features enabled
- * by default.
- */
- int mLargeScreenSmallestScreenWidthDp;
-
final List<ActivityTaskManagerInternal.ScreenObserver> mScreenObservers = new ArrayList<>();
// VR Vr2d Display Id.
@@ -858,6 +855,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
final PackageManager pm = mContext.getPackageManager();
mHasHeavyWeightFeature = pm.hasSystemFeature(FEATURE_CANT_SAVE_STATE);
mHasLeanbackFeature = pm.hasSystemFeature(FEATURE_LEANBACK);
+ mHasCompanionDeviceSetupFeature = pm.hasSystemFeature(FEATURE_COMPANION_DEVICE_SETUP);
mVrController.onSystemReady();
mRecentTasks.onSystemReadyLocked();
mTaskSupervisor.onSystemReady();
@@ -910,8 +908,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
com.android.internal.R.dimen.config_minPercentageMultiWindowSupportHeight);
final float minPercentageMultiWindowSupportWidth = mContext.getResources().getFloat(
com.android.internal.R.dimen.config_minPercentageMultiWindowSupportWidth);
- final int largeScreenSmallestScreenWidthDp = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_largeScreenSmallestScreenWidthDp);
// Transfer any global setting for forcing RTL layout, into a System Property
DisplayProperties.debug_force_rtl(forceRtl);
@@ -930,7 +926,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
mRespectsActivityMinWidthHeightMultiWindow = respectsActivityMinWidthHeightMultiWindow;
mMinPercentageMultiWindowSupportHeight = minPercentageMultiWindowSupportHeight;
mMinPercentageMultiWindowSupportWidth = minPercentageMultiWindowSupportWidth;
- mLargeScreenSmallestScreenWidthDp = largeScreenSmallestScreenWidthDp;
final boolean multiWindowFormEnabled = freeformWindowManagement
|| supportsSplitScreenMultiWindow
|| supportsPictureInPicture
@@ -1852,11 +1847,11 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@Override
public BackNavigationInfo startBackNavigation(
- IWindowFocusObserver observer, BackAnimationAdapter adapter) {
+ RemoteCallback navigationObserver, BackAnimationAdapter adapter) {
mAmInternal.enforceCallingPermission(START_TASKS_FROM_RECENTS,
"startBackNavigation()");
- return mBackNavigationController.startBackNavigation(observer, adapter);
+ return mBackNavigationController.startBackNavigation(navigationObserver, adapter);
}
/**
@@ -2034,7 +2029,20 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
return;
}
- if (r.moveFocusableActivityToTop("setFocusedTask")) {
+ final Transition transition = (getTransitionController().isCollecting()
+ || !getTransitionController().isShellTransitionsEnabled()) ? null
+ : getTransitionController().createTransition(TRANSIT_TO_FRONT);
+ if (transition != null) {
+ // Set ready before doing anything. If order does change, then that will set it unready
+ // so that we wait for the new lifecycles to complete.
+ transition.setReady(task, true /* ready */);
+ }
+ final boolean movedToTop = r.moveFocusableActivityToTop("setFocusedTask");
+ if (movedToTop) {
+ if (transition != null) {
+ getTransitionController().requestStartTransition(
+ transition, null /* startTask */, null /* remote */, null /* display */);
+ }
mRootWindowContainer.resumeFocusedTasksTopActivities();
} else if (touchedActivity != null && touchedActivity.isFocusable()) {
final TaskFragment parent = touchedActivity.getTaskFragment();
@@ -2046,6 +2054,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
true /* updateInputWindows */);
}
}
+ if (transition != null && !movedToTop) {
+ // No order changes and focus-changes, alone, aren't captured in transitions.
+ transition.abort();
+ }
}
@Override
@@ -6081,18 +6093,11 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@Override
public ActivityServiceConnectionsHolder getServiceConnectionsHolder(IBinder token) {
- synchronized (mGlobalLock) {
- final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
- if (r == null) {
- return null;
- }
- if (r.mServiceConnectionsHolder == null) {
- r.mServiceConnectionsHolder = new ActivityServiceConnectionsHolder(
- ActivityTaskManagerService.this, r);
- }
-
- return r.mServiceConnectionsHolder;
+ final ActivityRecord r = ActivityRecord.forToken(token);
+ if (r == null || !r.inHistory) {
+ return null;
}
+ return r.getOrCreateServiceConnectionsHolder();
}
@Override
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index ef47b6e5d70a..df471c56fec9 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -51,7 +51,6 @@ import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_TASKS;
-import static com.android.server.wm.ActivityRecord.State.FINISHING;
import static com.android.server.wm.ActivityRecord.State.PAUSED;
import static com.android.server.wm.ActivityRecord.State.PAUSING;
import static com.android.server.wm.ActivityRecord.State.RESTARTING_PROCESS;
@@ -103,6 +102,7 @@ import android.app.servertransaction.PauseActivityItem;
import android.app.servertransaction.ResumeActivityItem;
import android.companion.virtual.VirtualDeviceManager;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
@@ -1236,11 +1236,16 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
int getDeviceIdForDisplayId(int displayId) {
if (displayId == DEFAULT_DISPLAY || displayId == INVALID_DISPLAY) {
- return VirtualDeviceManager.DEVICE_ID_DEFAULT;
+ return Context.DEVICE_ID_DEFAULT;
}
if (mVirtualDeviceManager == null) {
- mVirtualDeviceManager =
- mService.mContext.getSystemService(VirtualDeviceManager.class);
+ if (mService.mHasCompanionDeviceSetupFeature) {
+ mVirtualDeviceManager =
+ mService.mContext.getSystemService(VirtualDeviceManager.class);
+ }
+ if (mVirtualDeviceManager == null) {
+ return Context.DEVICE_ID_DEFAULT;
+ }
}
return mVirtualDeviceManager.getDeviceIdForDisplayId(displayId);
}
@@ -1636,50 +1641,6 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
// Prevent recursion.
return;
}
- boolean shouldBlockActivitySwitchIfFeatureEnabled = false;
- boolean wouldBlockActivitySwitchIgnoringFlags = false;
- // We may have already checked that the callingUid has additional clearTask privileges, and
- // cleared the calling identify. If so, we infer we do not need further restrictions here.
- // TODO(b/263368846) Move to live with the rest of the ASM logic.
- if (callingUid != SYSTEM_UID) {
- Pair<Boolean, Boolean> pair = doesTopActivityMatchingUidExistForAsm(task,
- callingUid,
- null);
- shouldBlockActivitySwitchIfFeatureEnabled = !pair.first;
- wouldBlockActivitySwitchIgnoringFlags = !pair.second;
- if (wouldBlockActivitySwitchIgnoringFlags) {
- ActivityRecord topActivity = task.getActivity(ar ->
- !ar.isState(FINISHING) && !ar.isAlwaysOnTop());
- FrameworkStatsLog.write(FrameworkStatsLog.ACTIVITY_ACTION_BLOCKED,
- /* caller_uid */
- callingUid,
- /* caller_activity_class_name */
- callerActivityClassName,
- /* target_task_top_activity_uid */
- topActivity == null ? -1 : topActivity.getUid(),
- /* target_task_top_activity_class_name */
- topActivity == null ? null : topActivity.info.name,
- /* target_task_is_different */
- false,
- /* target_activity_uid */
- -1,
- /* target_activity_class_name */
- null,
- /* target_intent_action */
- null,
- /* target_intent_flags */
- 0,
- /* action */
- FrameworkStatsLog.ACTIVITY_ACTION_BLOCKED__ACTION__FINISH_TASK,
- /* version */
- 3,
- /* multi_window */
- false,
- /* bal_code */
- -1
- );
- }
- }
task.mTransitionController.requestCloseTransitionIfNeeded(task);
task.mInRemoveTask = true;
try {
@@ -1690,33 +1651,107 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
if (task.isPersistable) {
mService.notifyTaskPersisterLocked(null, true);
}
- if (wouldBlockActivitySwitchIgnoringFlags) {
- boolean restrictActivitySwitch = ActivitySecurityModelFeatureFlags
- .shouldRestrictActivitySwitch(callingUid)
- && shouldBlockActivitySwitchIfFeatureEnabled;
- if (ActivitySecurityModelFeatureFlags.shouldShowToast(callingUid)) {
- UiThread.getHandler().post(() -> Toast.makeText(mService.mContext,
- (restrictActivitySwitch
- ? "Returning home due to "
- : "Would return home due to ")
- + ActivitySecurityModelFeatureFlags.DOC_LINK,
- Toast.LENGTH_SHORT).show());
- }
-
- // If the activity switch should be restricted, return home rather than the
- // previously top task, to prevent users from being confused which app they're
- // viewing
- if (restrictActivitySwitch) {
- Slog.w(TAG, "Return to home as source uid: " + callingUid
- + "is not on top of task t: " + task);
- task.getTaskDisplayArea().moveHomeActivityToTop("taskRemoved");
- }
- }
+ checkActivitySecurityForTaskClear(callingUid, task, callerActivityClassName);
} finally {
task.mInRemoveTask = false;
}
}
+ // TODO(b/263368846) Move to live with the rest of the ASM logic.
+ /**
+ * Returns home if the passed in callingUid is not top of the stack, rather than returning to
+ * previous task.
+ */
+ private void checkActivitySecurityForTaskClear(int callingUid, Task task,
+ String callerActivityClassName) {
+ // We may have already checked that the callingUid has additional clearTask privileges, and
+ // cleared the calling identify. If so, we infer we do not need further restrictions here.
+ if (callingUid == SYSTEM_UID) {
+ return;
+ }
+
+ TaskDisplayArea displayArea = task.getTaskDisplayArea();
+ if (displayArea == null) {
+ // If there is no associated display area, we can not return home.
+ return;
+ }
+
+ Pair<Boolean, Boolean> pair = doesTopActivityMatchingUidExistForAsm(task, callingUid, null);
+ boolean shouldBlockActivitySwitchIfFeatureEnabled = !pair.first;
+ boolean wouldBlockActivitySwitchIgnoringFlags = !pair.second;
+
+ if (!wouldBlockActivitySwitchIgnoringFlags) {
+ return;
+ }
+
+ ActivityRecord topActivity = task.getActivity(ar -> !ar.finishing && !ar.isAlwaysOnTop());
+ FrameworkStatsLog.write(FrameworkStatsLog.ACTIVITY_ACTION_BLOCKED,
+ /* caller_uid */
+ callingUid,
+ /* caller_activity_class_name */
+ callerActivityClassName,
+ /* target_task_top_activity_uid */
+ topActivity == null ? -1 : topActivity.getUid(),
+ /* target_task_top_activity_class_name */
+ topActivity == null ? null : topActivity.info.name,
+ /* target_task_is_different */
+ false,
+ /* target_activity_uid */
+ -1,
+ /* target_activity_class_name */
+ null,
+ /* target_intent_action */
+ null,
+ /* target_intent_flags */
+ 0,
+ /* action */
+ FrameworkStatsLog.ACTIVITY_ACTION_BLOCKED__ACTION__FINISH_TASK,
+ /* version */
+ ActivitySecurityModelFeatureFlags.ASM_VERSION,
+ /* multi_window */
+ false,
+ /* bal_code */
+ -1
+ );
+
+ boolean restrictActivitySwitch = ActivitySecurityModelFeatureFlags
+ .shouldRestrictActivitySwitch(callingUid)
+ && shouldBlockActivitySwitchIfFeatureEnabled;
+
+ PackageManager pm = mService.mContext.getPackageManager();
+ String callingPackage = pm.getNameForUid(callingUid);
+ final CharSequence callingLabel;
+ if (callingPackage == null) {
+ callingPackage = String.valueOf(callingUid);
+ callingLabel = callingPackage;
+ } else {
+ callingLabel = getApplicationLabel(pm, callingPackage);
+ }
+
+ if (ActivitySecurityModelFeatureFlags.shouldShowToast(callingUid)) {
+ Toast toast = Toast.makeText(mService.mContext,
+ (ActivitySecurityModelFeatureFlags.DOC_LINK
+ + (restrictActivitySwitch
+ ? "returned home due to "
+ : "would return home due to ")
+ + callingLabel),
+ Toast.LENGTH_LONG);
+ UiThread.getHandler().post(toast::show);
+ }
+
+ // If the activity switch should be restricted, return home rather than the
+ // previously top task, to prevent users from being confused which app they're
+ // viewing
+ if (restrictActivitySwitch) {
+ Slog.w(TAG, "[ASM] Return to home as source: " + callingPackage
+ + " is not on top of task t: " + task);
+ displayArea.moveHomeActivityToTop("taskRemoved");
+ } else {
+ Slog.i(TAG, "[ASM] Would return to home as source: " + callingPackage
+ + " is not on top of task t: " + task);
+ }
+ }
+
/**
* For the purpose of ASM, ‘Top UID” for a task is defined as an activity UID
* 1. Which is top of the stack in z-order
@@ -1743,7 +1778,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
// Consider the source activity, whether or not it is finishing. Do not consider any other
// finishing activity.
Predicate<ActivityRecord> topOfStackPredicate = (ar) -> ar.equals(sourceRecord)
- || (!ar.isState(FINISHING) && !ar.isAlwaysOnTop());
+ || (!ar.finishing && !ar.isAlwaysOnTop());
// Check top of stack (or the first task fragment for embedding).
ActivityRecord topActivity = task.getActivity(topOfStackPredicate);
@@ -1777,6 +1812,16 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
return topActivity.allowCrossUidActivitySwitchFromBelow(uid);
}
+ static CharSequence getApplicationLabel(PackageManager pm, String packageName) {
+ try {
+ ApplicationInfo launchedFromPackageInfo = pm.getApplicationInfo(
+ packageName, PackageManager.ApplicationInfoFlags.of(0));
+ return pm.getApplicationLabel(launchedFromPackageInfo);
+ } catch (PackageManager.NameNotFoundException e) {
+ return packageName;
+ }
+ }
+
void cleanUpRemovedTaskLocked(Task task, boolean killProcess, boolean removeFromRecents) {
if (removeFromRecents) {
mRecentTasks.remove(task);
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index f73c68a42ec7..939cf1ae471b 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -888,8 +888,11 @@ public class AppTransition implements Dump {
} else {
int animAttr = mapOpenCloseTransitTypes(transit, enter);
if (animAttr != 0) {
- a = loadCustomActivityAnimation(animAttr, enter, container);
- if (a == null) {
+ final CustomAppTransition customAppTransition =
+ getCustomAppTransition(animAttr, container);
+ if (customAppTransition != null) {
+ a = loadCustomActivityAnimation(customAppTransition, enter, container);
+ } else {
if (canCustomizeAppTransition) {
a = loadAnimationAttr(lp, animAttr, transit);
} else {
@@ -911,7 +914,7 @@ public class AppTransition implements Dump {
return a;
}
- Animation loadCustomActivityAnimation(int animAttr, boolean enter, WindowContainer container) {
+ CustomAppTransition getCustomAppTransition(int animAttr, WindowContainer container) {
ActivityRecord customAnimationSource = container.asActivityRecord();
if (customAnimationSource == null) {
return null;
@@ -927,31 +930,28 @@ public class AppTransition implements Dump {
return null;
}
}
- final CustomAppTransition custom;
switch (animAttr) {
case WindowAnimation_activityOpenEnterAnimation:
case WindowAnimation_activityOpenExitAnimation:
- custom = customAnimationSource.getCustomAnimation(true /* open */);
- break;
+ return customAnimationSource.getCustomAnimation(true /* open */);
case WindowAnimation_activityCloseEnterAnimation:
case WindowAnimation_activityCloseExitAnimation:
- custom = customAnimationSource.getCustomAnimation(false /* open */);
- break;
- default:
- return null;
- }
- if (custom != null) {
- final Animation a = mTransitionAnimation.loadAppTransitionAnimation(
- customAnimationSource.packageName, enter
- ? custom.mEnterAnim : custom.mExitAnim);
- if (a != null && custom.mBackgroundColor != 0) {
- a.setBackdropColor(custom.mBackgroundColor);
- a.setShowBackdrop(true);
- }
- return a;
+ return customAnimationSource.getCustomAnimation(false /* open */);
}
return null;
}
+ private Animation loadCustomActivityAnimation(@NonNull CustomAppTransition custom,
+ boolean enter, WindowContainer container) {
+ final ActivityRecord customAnimationSource = container.asActivityRecord();
+ final Animation a = mTransitionAnimation.loadAppTransitionAnimation(
+ customAnimationSource.packageName, enter
+ ? custom.mEnterAnim : custom.mExitAnim);
+ if (a != null && custom.mBackgroundColor != 0) {
+ a.setBackdropColor(custom.mBackgroundColor);
+ a.setShowBackdrop(true);
+ }
+ return a;
+ }
int getAppRootTaskClipMode() {
return mNextAppTransitionRequests.contains(TRANSIT_RELAUNCH)
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index 75c85d785617..4e94f96af37b 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -253,7 +253,7 @@ public class AppTransitionController {
ArraySet<ActivityRecord> tmpOpenApps = mDisplayContent.mOpeningApps;
ArraySet<ActivityRecord> tmpCloseApps = mDisplayContent.mClosingApps;
- if (mDisplayContent.mAtmService.mBackNavigationController.isWaitBackTransition()) {
+ if (mDisplayContent.mAtmService.mBackNavigationController.isMonitoringTransition()) {
tmpOpenApps = new ArraySet<>(mDisplayContent.mOpeningApps);
tmpCloseApps = new ArraySet<>(mDisplayContent.mClosingApps);
if (mDisplayContent.mAtmService.mBackNavigationController
diff --git a/services/core/java/com/android/server/wm/AsyncRotationController.java b/services/core/java/com/android/server/wm/AsyncRotationController.java
index dcafe80686ad..5c9c81300e0d 100644
--- a/services/core/java/com/android/server/wm/AsyncRotationController.java
+++ b/services/core/java/com/android/server/wm/AsyncRotationController.java
@@ -217,6 +217,34 @@ class AsyncRotationController extends FadeAnimationController implements Consume
if (DEBUG) Slog.d(TAG, "Requested to sync draw transaction");
}
+ /**
+ * If an async window is not requested to redraw or its surface is removed, then complete its
+ * operation directly to avoid waiting until timeout.
+ */
+ void updateTargetWindows() {
+ if (mTransitionOp == OP_LEGACY || !mIsStartTransactionCommitted) return;
+ for (int i = mTargetWindowTokens.size() - 1; i >= 0; i--) {
+ final Operation op = mTargetWindowTokens.valueAt(i);
+ if (op.mIsCompletionPending || op.mAction == Operation.ACTION_SEAMLESS) {
+ // Skip completed target. And seamless windows use the signal from blast sync.
+ continue;
+ }
+ final WindowToken token = mTargetWindowTokens.keyAt(i);
+ int readyCount = 0;
+ final int childCount = token.getChildCount();
+ for (int j = childCount - 1; j >= 0; j--) {
+ final WindowState w = token.getChildAt(j);
+ // If the token no longer contains pending drawn windows, then it is ready.
+ if (w.isDrawn() || !w.mWinAnimator.getShown()) {
+ readyCount++;
+ }
+ }
+ if (readyCount == childCount) {
+ mDisplayContent.finishAsyncRotation(token);
+ }
+ }
+ }
+
/** Lets the window fit in new rotation naturally. */
private void finishOp(WindowToken windowToken) {
final Operation op = mTargetWindowTokens.remove(windowToken);
@@ -336,6 +364,7 @@ class AsyncRotationController extends FadeAnimationController implements Consume
/** Hides the window immediately until it is drawn in new rotation. */
void hideImmediately(WindowToken windowToken) {
+ if (isTargetToken(windowToken)) return;
final boolean original = mHideImmediately;
mHideImmediately = true;
final Operation op = new Operation(Operation.ACTION_FADE);
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index bc5f67bb50d0..2d45dc20c963 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -41,7 +41,6 @@ import android.os.SystemProperties;
import android.util.ArraySet;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
-import android.view.IWindowFocusObserver;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.view.WindowInsets;
@@ -66,16 +65,21 @@ import java.util.function.Consumer;
class BackNavigationController {
private static final String TAG = "BackNavigationController";
private WindowManagerService mWindowManagerService;
- private IWindowFocusObserver mFocusObserver;
private boolean mBackAnimationInProgress;
private @BackNavigationInfo.BackTargetType int mLastBackType;
private boolean mShowWallpaper;
private Runnable mPendingAnimation;
+ private final NavigationMonitor mNavigationMonitor = new NavigationMonitor();
private AnimationHandler mAnimationHandler;
private final ArrayList<WindowContainer> mTmpOpenApps = new ArrayList<>();
private final ArrayList<WindowContainer> mTmpCloseApps = new ArrayList<>();
+ // This will be set if the back navigation is in progress and the current transition is still
+ // running. The pending animation builder will do the animation stuff includes creating leashes,
+ // re-parenting leashes and set launch behind, etc. Will be handled when transition finished.
+ private AnimationHandler.ScheduleAnimationBuilder mPendingAnimationBuilder;
+
/**
* true if the back predictability feature is enabled
*/
@@ -86,6 +90,11 @@ class BackNavigationController {
return SystemProperties.getInt("persist.wm.debug.predictive_back_screenshot", 0) != 0;
}
+ // Notify focus window changed
+ void onFocusChanged(WindowState newFocus) {
+ mNavigationMonitor.onFocusWindowChanged(newFocus);
+ }
+
/**
* Set up the necessary leashes and build a {@link BackNavigationInfo} instance for an upcoming
* back gesture animation.
@@ -96,13 +105,12 @@ class BackNavigationController {
*/
@VisibleForTesting
@Nullable
- BackNavigationInfo startBackNavigation(
- IWindowFocusObserver observer, BackAnimationAdapter adapter) {
+ BackNavigationInfo startBackNavigation(@NonNull RemoteCallback navigationObserver,
+ BackAnimationAdapter adapter) {
if (!sPredictBackEnable) {
return null;
}
final WindowManagerService wmService = mWindowManagerService;
- mFocusObserver = observer;
int backType = BackNavigationInfo.TYPE_UNDEFINED;
@@ -202,9 +210,7 @@ class BackNavigationController {
backType = BackNavigationInfo.TYPE_CALLBACK;
}
infoBuilder.setOnBackInvokedCallback(callbackInfo.getCallback());
- if (mFocusObserver != null) {
- window.registerFocusObserver(mFocusObserver);
- }
+ mNavigationMonitor.startMonitor(window, navigationObserver);
}
ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "startBackNavigation currentTask=%s, "
@@ -228,10 +234,8 @@ class BackNavigationController {
|| currentActivity.isActivityTypeHome()
|| currentActivity.mHasSceneTransition) {
infoBuilder.setType(BackNavigationInfo.TYPE_CALLBACK);
- final WindowState finalFocusedWindow = window;
infoBuilder.setOnBackNavigationDone(new RemoteCallback(result ->
- onBackNavigationDone(result, finalFocusedWindow,
- BackNavigationInfo.TYPE_CALLBACK)));
+ onBackNavigationDone(result, BackNavigationInfo.TYPE_CALLBACK)));
mLastBackType = BackNavigationInfo.TYPE_CALLBACK;
return infoBuilder.build();
}
@@ -306,25 +310,26 @@ class BackNavigationController {
|| backType == BackNavigationInfo.TYPE_CROSS_ACTIVITY)
&& adapter != null;
- // Only prepare animation if no leash has been created (no animation is running).
- // TODO(b/241808055): Cancel animation when preparing back animation.
- if (prepareAnimation
- && (removedWindowContainer.hasCommittedReparentToAnimationLeash()
- || removedWindowContainer.mTransitionController.inTransition())) {
- Slog.w(TAG, "Can't prepare back animation due to another animation is running.");
- prepareAnimation = false;
- }
-
if (prepareAnimation) {
- mPendingAnimation = mAnimationHandler.scheduleAnimation(backType, adapter,
- currentTask, prevTask, currentActivity, prevActivity);
- prepareAnimation = mPendingAnimation != null;
- mBackAnimationInProgress = prepareAnimation;
- if (prepareAnimation) {
- mWindowManagerService.mWindowPlacerLocked.requestTraversal();
- if (mShowWallpaper) {
- currentTask.getDisplayContent().mWallpaperController
- .adjustWallpaperWindows();
+ final AnimationHandler.ScheduleAnimationBuilder builder =
+ mAnimationHandler.prepareAnimation(backType, adapter,
+ currentTask, prevTask, currentActivity, prevActivity);
+ mBackAnimationInProgress = builder != null;
+ if (mBackAnimationInProgress) {
+ if (removedWindowContainer.hasCommittedReparentToAnimationLeash()
+ || removedWindowContainer.mTransitionController.inTransition()
+ || mWindowManagerService.mSyncEngine.hasPendingSyncSets()) {
+ ProtoLog.w(WM_DEBUG_BACK_PREVIEW,
+ "Pending back animation due to another animation is running");
+ mPendingAnimationBuilder = builder;
+ // Current transition is still running, we have to defer the hiding to the
+ // client process to prevent the unexpected relayout when handling the back
+ // animation.
+ if (prevActivity != null) {
+ prevActivity.setDeferHidingClient(true);
+ }
+ } else {
+ scheduleAnimation(builder);
}
}
}
@@ -334,16 +339,28 @@ class BackNavigationController {
WindowContainer<?> finalRemovedWindowContainer = removedWindowContainer;
if (finalRemovedWindowContainer != null) {
final int finalBackType = backType;
- final WindowState finalFocusedWindow = window;
RemoteCallback onBackNavigationDone = new RemoteCallback(result -> onBackNavigationDone(
- result, finalFocusedWindow, finalBackType));
+ result, finalBackType));
infoBuilder.setOnBackNavigationDone(onBackNavigationDone);
}
mLastBackType = backType;
return infoBuilder.build();
}
- boolean isWaitBackTransition() {
+ boolean isMonitoringTransition() {
+ return isWaitBackTransition() || mNavigationMonitor.isMonitoring();
+ }
+
+ private void scheduleAnimation(@NonNull AnimationHandler.ScheduleAnimationBuilder builder) {
+ mPendingAnimation = builder.build();
+ mWindowManagerService.mWindowPlacerLocked.requestTraversal();
+ if (mShowWallpaper) {
+ mWindowManagerService.getDefaultDisplayContentLocked().mWallpaperController
+ .adjustWallpaperWindows();
+ }
+ }
+
+ private boolean isWaitBackTransition() {
return mAnimationHandler.mComposed && mAnimationHandler.mWaitTransition;
}
@@ -363,11 +380,23 @@ class BackNavigationController {
*/
boolean removeIfContainsBackAnimationTargets(ArraySet<ActivityRecord> openApps,
ArraySet<ActivityRecord> closeApps) {
- if (!isWaitBackTransition()) {
+ if (!isMonitoringTransition()) {
return false;
}
mTmpCloseApps.addAll(closeApps);
- boolean result = false;
+ final boolean matchAnimationTargets = removeIfWaitForBackTransition(openApps, closeApps);
+ if (!matchAnimationTargets) {
+ mNavigationMonitor.onTransitionReadyWhileNavigate(mTmpOpenApps, mTmpCloseApps);
+ }
+ mTmpCloseApps.clear();
+ return matchAnimationTargets;
+ }
+
+ boolean removeIfWaitForBackTransition(ArraySet<ActivityRecord> openApps,
+ ArraySet<ActivityRecord> closeApps) {
+ if (!isWaitBackTransition()) {
+ return false;
+ }
// Note: TmpOpenApps is empty. Unlike shell transition, the open apps will be removed from
// mOpeningApps if there is no visibility change.
if (mAnimationHandler.containsBackAnimationTargets(mTmpOpenApps, mTmpCloseApps)) {
@@ -386,10 +415,76 @@ class BackNavigationController {
closeApps.removeAt(i);
}
}
- result = true;
+ return true;
+ }
+ return false;
+ }
+
+ private static class NavigationMonitor {
+ // The window which triggering the back navigation.
+ private WindowState mNavigatingWindow;
+ private RemoteCallback mObserver;
+
+ void startMonitor(@NonNull WindowState window, @NonNull RemoteCallback observer) {
+ mNavigatingWindow = window;
+ mObserver = observer;
+ }
+
+ void stopMonitor() {
+ mNavigatingWindow = null;
+ mObserver = null;
+ }
+
+ boolean isMonitoring() {
+ return mNavigatingWindow != null && mObserver != null;
+ }
+
+ /**
+ * Notify focus window changed during back navigation. This will cancel the gesture for
+ * scenarios like: a system window popup, or when an activity add a new window.
+ *
+ * This method should only be used to check window-level change, otherwise it may cause
+ * misjudgment in multi-window mode. For example: in split-screen, when user is
+ * navigating on the top task, bottom task can start a new task, which will gain focus for
+ * a short time, but we should not cancel the navigation.
+ */
+ private void onFocusWindowChanged(WindowState newFocus) {
+ if (!isMonitoring() || !atSameDisplay(newFocus)) {
+ return;
+ }
+ // Keep navigating if either new focus == navigating window or null.
+ if (newFocus != null && newFocus != mNavigatingWindow
+ && (newFocus.mActivityRecord == null
+ || (newFocus.mActivityRecord == mNavigatingWindow.mActivityRecord))) {
+ EventLogTags.writeWmBackNaviCanceled("focusWindowChanged");
+ mObserver.sendResult(null /* result */);
+ }
+ }
+
+ /**
+ * Notify an unexpected transition has happened during back navigation.
+ */
+ private void onTransitionReadyWhileNavigate(ArrayList<WindowContainer> opening,
+ ArrayList<WindowContainer> closing) {
+ if (!isMonitoring()) {
+ return;
+ }
+ final ArrayList<WindowContainer> all = new ArrayList<>(opening);
+ all.addAll(closing);
+ for (WindowContainer app : all) {
+ if (app.hasChild(mNavigatingWindow)) {
+ EventLogTags.writeWmBackNaviCanceled("transitionHappens");
+ mObserver.sendResult(null /* result */);
+ break;
+ }
+ }
+
+ }
+
+ private boolean atSameDisplay(WindowState newFocus) {
+ final int navigatingDisplayId = mNavigatingWindow.getDisplayId();
+ return newFocus == null || newFocus.getDisplayId() == navigatingDisplayId;
}
- mTmpCloseApps.clear();
- return result;
}
// For shell transition
@@ -403,8 +498,7 @@ class BackNavigationController {
* animations, and shouldn't join next transition.
*/
boolean containsBackAnimationTargets(Transition transition) {
- if (!mAnimationHandler.mComposed
- || (transition.mType != TRANSIT_CLOSE && transition.mType != TRANSIT_TO_BACK)) {
+ if (!isMonitoringTransition()) {
return false;
}
final ArraySet<WindowContainer> targets = transition.mParticipants;
@@ -420,19 +514,19 @@ class BackNavigationController {
mTmpCloseApps.add(wc);
}
}
- final boolean result = mAnimationHandler.containsBackAnimationTargets(
- mTmpOpenApps, mTmpCloseApps);
- if (result) {
- mAnimationHandler.mOpenTransitionTargetMatch =
- mAnimationHandler.containTarget(mTmpOpenApps, true);
+ final boolean matchAnimationTargets = isWaitBackTransition()
+ && (transition.mType == TRANSIT_CLOSE || transition.mType == TRANSIT_TO_BACK)
+ && mAnimationHandler.containsBackAnimationTargets(mTmpOpenApps, mTmpCloseApps);
+ if (!matchAnimationTargets) {
+ mNavigationMonitor.onTransitionReadyWhileNavigate(mTmpOpenApps, mTmpCloseApps);
}
mTmpOpenApps.clear();
mTmpCloseApps.clear();
- return result;
+ return matchAnimationTargets;
}
boolean isMonitorTransitionTarget(WindowContainer wc) {
- if (!mAnimationHandler.mComposed || !mAnimationHandler.mWaitTransition) {
+ if (!isWaitBackTransition()) {
return false;
}
return mAnimationHandler.isTarget(wc, wc.isVisibleRequested() /* open */);
@@ -447,6 +541,57 @@ class BackNavigationController {
mAnimationHandler.clearBackAnimateTarget(cleanupTransaction);
}
+ /**
+ * Handle the pending animation when the running transition finished.
+ * @param targets The final animation targets derived in transition.
+ */
+ boolean handleDeferredBackAnimation(@NonNull ArrayList<Transition.ChangeInfo> targets) {
+ if (!mBackAnimationInProgress || mPendingAnimationBuilder == null) {
+ return false;
+ }
+
+ ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
+ "Handling the deferred animation after transition finished");
+
+ // Show the target surface and its parents to prevent it or its parents hidden when
+ // the transition finished.
+ // The target could be affected by transition when :
+ // Open transition -> the open target in back navigation
+ // Close transition -> the close target in back navigation.
+ boolean hasTarget = false;
+ final SurfaceControl.Transaction t =
+ mPendingAnimationBuilder.mCloseTarget.getPendingTransaction();
+ for (int i = 0; i < targets.size(); i++) {
+ final WindowContainer wc = targets.get(i).mContainer;
+ if (wc.asActivityRecord() == null && wc.asTask() == null) {
+ continue;
+ } else if (!mPendingAnimationBuilder.containTarget(wc)) {
+ continue;
+ }
+
+ hasTarget = true;
+ t.show(wc.getSurfaceControl());
+ }
+
+ if (!hasTarget) {
+ // Skip if no target participated in current finished transition.
+ Slog.w(TAG, "Finished transition didn't include the targets"
+ + " open: " + mPendingAnimationBuilder.mOpenTarget
+ + " close: " + mPendingAnimationBuilder.mCloseTarget);
+ try {
+ mPendingAnimationBuilder.mBackAnimationAdapter.getRunner().onAnimationCancelled();
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ mPendingAnimationBuilder = null;
+ return false;
+ }
+
+ scheduleAnimation(mPendingAnimationBuilder);
+ mPendingAnimationBuilder = null;
+ return true;
+ }
+
/**
* Create and handling animations status for an open/close animation targets.
*/
@@ -559,6 +704,7 @@ class BackNavigationController {
if (open) {
return wc == mOpenAdaptor.mTarget || mOpenAdaptor.mTarget.hasChild(wc);
}
+
if (mSwitchType == TASK_SWITCH) {
return wc == mCloseAdaptor.mTarget
|| (wc.asTask() != null && wc.hasChild(mCloseAdaptor.mTarget));
@@ -762,23 +908,22 @@ class BackNavigationController {
}
}
- Runnable scheduleAnimation(int backType, BackAnimationAdapter adapter,
+ ScheduleAnimationBuilder prepareAnimation(int backType, BackAnimationAdapter adapter,
Task currentTask, Task previousTask, ActivityRecord currentActivity,
ActivityRecord previousActivity) {
switch (backType) {
case BackNavigationInfo.TYPE_RETURN_TO_HOME:
return new ScheduleAnimationBuilder(backType, adapter)
.setIsLaunchBehind(true)
- .setComposeTarget(currentTask, previousTask)
- .build();
+ .setComposeTarget(currentTask, previousTask);
case BackNavigationInfo.TYPE_CROSS_ACTIVITY:
return new ScheduleAnimationBuilder(backType, adapter)
.setComposeTarget(currentActivity, previousActivity)
- .setOpeningSnapshot(getActivitySnapshot(previousActivity)).build();
+ .setOpeningSnapshot(getActivitySnapshot(previousActivity));
case BackNavigationInfo.TYPE_CROSS_TASK:
return new ScheduleAnimationBuilder(backType, adapter)
.setComposeTarget(currentTask, previousTask)
- .setOpeningSnapshot(getTaskSnapshot(previousTask)).build();
+ .setOpeningSnapshot(getTaskSnapshot(previousTask));
}
return null;
}
@@ -812,6 +957,11 @@ class BackNavigationController {
return this;
}
+ boolean containTarget(@NonNull WindowContainer wc) {
+ return wc == mOpenTarget || wc == mCloseTarget
+ || wc.hasChild(mOpenTarget) || wc.hasChild(mCloseTarget);
+ }
+
Runnable build() {
if (mOpenTarget == null || mCloseTarget == null) {
return null;
@@ -888,47 +1038,41 @@ class BackNavigationController {
}
};
}
+ }
+ }
- private void setLaunchBehind(ActivityRecord activity) {
- if (activity == null) {
- return;
- }
- if (!activity.isVisibleRequested()) {
- activity.setVisibility(true);
- }
- activity.mLaunchTaskBehind = true;
-
- // Handle fixed rotation launching app.
- final DisplayContent dc = activity.mDisplayContent;
- dc.rotateInDifferentOrientationIfNeeded(activity);
- if (activity.hasFixedRotationTransform()) {
- // Set the record so we can recognize it to continue to update display
- // orientation if the previous activity becomes the top later.
- dc.setFixedRotationLaunchingApp(activity,
- activity.getWindowConfiguration().getRotation());
- }
+ private static void setLaunchBehind(@NonNull ActivityRecord activity) {
+ if (!activity.isVisibleRequested()) {
+ activity.setVisibility(true);
+ }
+ activity.mLaunchTaskBehind = true;
+
+ // Handle fixed rotation launching app.
+ final DisplayContent dc = activity.mDisplayContent;
+ dc.rotateInDifferentOrientationIfNeeded(activity);
+ if (activity.hasFixedRotationTransform()) {
+ // Set the record so we can recognize it to continue to update display
+ // orientation if the previous activity becomes the top later.
+ dc.setFixedRotationLaunchingApp(activity,
+ activity.getWindowConfiguration().getRotation());
+ }
- ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
- "Setting Activity.mLauncherTaskBehind to true. Activity=%s", activity);
- activity.mTaskSupervisor.mStoppingActivities.remove(activity);
- activity.getDisplayContent().ensureActivitiesVisible(null /* starting */,
- 0 /* configChanges */, false /* preserveWindows */, true);
- }
- private void restoreLaunchBehind(ActivityRecord activity) {
- if (activity == null) {
- return;
- }
+ ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
+ "Setting Activity.mLauncherTaskBehind to true. Activity=%s", activity);
+ activity.mTaskSupervisor.mStoppingActivities.remove(activity);
+ activity.getDisplayContent().ensureActivitiesVisible(null /* starting */,
+ 0 /* configChanges */, false /* preserveWindows */, true);
+ }
- activity.mDisplayContent.continueUpdateOrientationForDiffOrienLaunchingApp();
+ private static void restoreLaunchBehind(@NonNull ActivityRecord activity) {
+ activity.mDisplayContent.continueUpdateOrientationForDiffOrienLaunchingApp();
- // Restore the launch-behind state.
- activity.mTaskSupervisor.scheduleLaunchTaskBehindComplete(activity.token);
- activity.mLaunchTaskBehind = false;
- ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
- "Setting Activity.mLauncherTaskBehind to false. Activity=%s",
- activity);
- }
- }
+ // Restore the launch-behind state.
+ activity.mTaskSupervisor.scheduleLaunchTaskBehindComplete(activity.token);
+ activity.mLaunchTaskBehind = false;
+ ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
+ "Setting Activity.mLauncherTaskBehind to false. Activity=%s",
+ activity);
}
void checkAnimationReady(WallpaperController wallpaperController) {
@@ -951,18 +1095,16 @@ class BackNavigationController {
}
}
- private void onBackNavigationDone(Bundle result, WindowState focusedWindow, int backType) {
+ private void onBackNavigationDone(Bundle result, int backType) {
boolean triggerBack = result != null && result.getBoolean(
BackNavigationInfo.KEY_TRIGGER_BACK);
ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "onBackNavigationDone backType=%s, "
+ "triggerBack=%b", backType, triggerBack);
- if (mFocusObserver != null) {
- focusedWindow.unregisterFocusObserver(mFocusObserver);
- mFocusObserver = null;
- }
+ mNavigationMonitor.stopMonitor();
mBackAnimationInProgress = false;
mShowWallpaper = false;
+ mPendingAnimationBuilder = null;
}
private static TaskSnapshot getActivitySnapshot(@NonNull ActivityRecord r) {
diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
index 587138ded8cb..8fc379724475 100644
--- a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
+++ b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
@@ -114,6 +114,35 @@ public class BackgroundActivityStartController {
/** Process belongs to a SDK sandbox */
static final int BAL_ALLOW_SDK_SANDBOX = 10;
+ static String balCodeToString(@BalCode int balCode) {
+ switch (balCode) {
+ case BAL_ALLOW_ALLOWLISTED_COMPONENT:
+ return "BAL_ALLOW_ALLOWLISTED_COMPONENT";
+ case BAL_ALLOW_ALLOWLISTED_UID:
+ return "BAL_ALLOW_ALLOWLISTED_UID";
+ case BAL_ALLOW_DEFAULT:
+ return "BAL_ALLOW_DEFAULT";
+ case BAL_ALLOW_FOREGROUND:
+ return "BAL_ALLOW_FOREGROUND";
+ case BAL_ALLOW_GRACE_PERIOD:
+ return "BAL_ALLOW_GRACE_PERIOD";
+ case BAL_ALLOW_PENDING_INTENT:
+ return "BAL_ALLOW_PENDING_INTENT";
+ case BAL_ALLOW_PERMISSION:
+ return "BAL_ALLOW_PERMISSION";
+ case BAL_ALLOW_SAW_PERMISSION:
+ return "BAL_ALLOW_SAW_PERMISSION";
+ case BAL_ALLOW_SDK_SANDBOX:
+ return "BAL_ALLOW_SDK_SANDBOX";
+ case BAL_ALLOW_VISIBLE_WINDOW:
+ return "BAL_ALLOW_VISIBLE_WINDOW";
+ case BAL_BLOCK:
+ return "BAL_BLOCK";
+ default:
+ throw new IllegalArgumentException("Unexpected value: " + balCode);
+ }
+ }
+
BackgroundActivityStartController(
final ActivityTaskManagerService service, final ActivityTaskSupervisor supervisor) {
mService = service;
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index ade2fe7152c0..87f5703bdbc5 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -38,6 +38,9 @@ import static android.os.Process.SYSTEM_UID;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.util.DisplayMetrics.DENSITY_DEFAULT;
import static android.util.RotationUtils.deltaRotation;
+import static android.util.TypedValue.COMPLEX_UNIT_DIP;
+import static android.util.TypedValue.COMPLEX_UNIT_MASK;
+import static android.util.TypedValue.COMPLEX_UNIT_SHIFT;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
import static android.view.Display.FLAG_PRIVATE;
@@ -170,6 +173,7 @@ import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.ScreenOrientation;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
+import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.ColorSpace;
import android.graphics.Insets;
@@ -206,6 +210,7 @@ import android.util.Size;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
+import android.util.TypedValue;
import android.util.proto.ProtoOutputStream;
import android.view.ContentRecordingSession;
import android.view.Display;
@@ -1684,14 +1689,16 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
private int getMinimalTaskSizeDp() {
final Context displayConfigurationContext =
mAtmService.mContext.createConfigurationContext(getConfiguration());
- final float minimalSize =
- displayConfigurationContext.getResources().getDimension(
- R.dimen.default_minimal_size_resizable_task);
- if (Double.compare(mDisplayMetrics.density, 0.0) == 0) {
- throw new IllegalArgumentException("Display with ID=" + getDisplayId() + "has invalid "
- + "DisplayMetrics.density= 0.0");
+ final Resources res = displayConfigurationContext.getResources();
+ final TypedValue value = new TypedValue();
+ res.getValue(R.dimen.default_minimal_size_resizable_task, value, true /* resolveRefs */);
+ final int valueUnit = ((value.data >> COMPLEX_UNIT_SHIFT) & COMPLEX_UNIT_MASK);
+ if (value.type != TypedValue.TYPE_DIMENSION || valueUnit != COMPLEX_UNIT_DIP) {
+ throw new IllegalArgumentException(
+ "Resource ID #0x" + Integer.toHexString(R.dimen.default_minimal_size_resizable_task)
+ + " is not in valid type or unit");
}
- return (int) (minimalSize / mDisplayMetrics.density);
+ return (int) TypedValue.complexToFloat(value.data);
}
private boolean updateOrientation(boolean forceUpdate) {
@@ -3809,6 +3816,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
}
getDisplayPolicy().focusChangedLw(oldFocus, newFocus);
+ mAtmService.mBackNavigationController.onFocusChanged(newFocus);
if (imWindowChanged && oldFocus != mInputMethodWindow) {
// Focus of the input method window changed. Perform layout if needed.
@@ -4150,13 +4158,13 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
/** @see WindowManagerInternal#onToggleImeRequested */
void onShowImeRequested() {
- if (mImeLayeringTarget == null || mInputMethodWindow == null) {
+ if (mInputMethodWindow == null) {
return;
}
// If IME window will be shown on the rotated activity, share the transformed state to
// IME window so it can compute rotated frame with rotated configuration.
- if (mImeLayeringTarget.mToken.isFixedRotationTransforming()) {
- mInputMethodWindow.mToken.linkFixedRotationTransform(mImeLayeringTarget.mToken);
+ if (mFixedRotationLaunchingApp != null) {
+ mInputMethodWindow.mToken.linkFixedRotationTransform(mFixedRotationLaunchingApp);
// Hide the window until the rotation is done to avoid intermediate artifacts if the
// parent surface of IME container is changed.
if (mAsyncRotationController != null) {
@@ -4589,8 +4597,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
*/
@VisibleForTesting
SurfaceControl computeImeParent() {
- if (!ImeTargetVisibilityPolicy.isValidToComputeImeParent(mImeLayeringTarget,
- mImeInputTarget)) {
+ if (!ImeTargetVisibilityPolicy.canComputeImeParent(mImeLayeringTarget, mImeInputTarget)) {
return null;
}
// Attach it to app if the target is part of an app and such app is covering the entire
@@ -4761,6 +4768,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
void updateWindowsForAnimator() {
forAllWindows(mUpdateWindowsForAnimator, true /* traverseTopToBottom */);
+ if (mAsyncRotationController != null) {
+ mAsyncRotationController.updateTargetWindows();
+ }
}
boolean isInputMethodClientFocus(int uid, int pid) {
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 2b34660d307f..ce3379ec4394 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -931,7 +931,7 @@ public class DisplayPolicy {
}
final InsetsSourceProvider provider = win.getControllableInsetProvider();
- if (provider != null && provider.getSource().getInsetsRoundedCornerFrame()
+ if (provider != null && provider.getSource().insetsRoundedCornerFrame()
!= attrs.insetsRoundedCornerFrame) {
provider.getSource().setInsetsRoundedCornerFrame(attrs.insetsRoundedCornerFrame);
}
@@ -1364,9 +1364,8 @@ public class DisplayPolicy {
applyKeyguardPolicy(win, imeTarget);
// Check if the freeform window overlaps with the navigation bar area.
- final boolean isOverlappingWithNavBar = isOverlappingWithNavBar(win);
- if (isOverlappingWithNavBar && !mIsFreeformWindowOverlappingWithNavBar
- && win.inFreeformWindowingMode()) {
+ if (!mIsFreeformWindowOverlappingWithNavBar && win.inFreeformWindowingMode()
+ && win.mActivityRecord != null && isOverlappingWithNavBar(win)) {
mIsFreeformWindowOverlappingWithNavBar = true;
}
@@ -1454,7 +1453,7 @@ public class DisplayPolicy {
// mode; if it's in gesture navigation mode, the navigation bar will be
// NAV_BAR_FORCE_TRANSPARENT and its appearance won't be decided by overlapping
// windows.
- if (isOverlappingWithNavBar) {
+ if (isOverlappingWithNavBar(win)) {
if (mNavBarColorWindowCandidate == null) {
mNavBarColorWindowCandidate = win;
addSystemBarColorApp(win);
@@ -1482,7 +1481,7 @@ public class DisplayPolicy {
addSystemBarColorApp(win);
}
}
- if (isOverlappingWithNavBar && mNavBarColorWindowCandidate == null) {
+ if (isOverlappingWithNavBar(win) && mNavBarColorWindowCandidate == null) {
mNavBarColorWindowCandidate = win;
}
}
@@ -2591,6 +2590,7 @@ public class DisplayPolicy {
lp.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+ lp.privateFlags |= LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
lp.setFitInsetsTypes(0);
lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
if (ActivityManager.isHighEndGfx()) {
@@ -2646,7 +2646,7 @@ public class DisplayPolicy {
@VisibleForTesting
static boolean isOverlappingWithNavBar(@NonNull WindowState win) {
- if (win.mActivityRecord == null || !win.isVisible()) {
+ if (!win.isVisible()) {
return false;
}
diff --git a/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java b/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java
index 47bdba34ee24..41eb2c92923f 100644
--- a/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java
@@ -359,12 +359,6 @@ final class DisplayRotationCompatPolicy {
CAMERA_OPENED_ROTATION_UPDATE_DELAY_MS);
}
- private void updateOrientationWithWmLock() {
- synchronized (mWmService.mGlobalLock) {
- mDisplayContent.updateOrientation();
- }
- }
-
private void delayedUpdateOrientationWithWmLock(
@NonNull String cameraId, @NonNull String packageName) {
synchronized (this) {
@@ -375,25 +369,28 @@ final class DisplayRotationCompatPolicy {
}
mCameraIdPackageBiMap.put(packageName, cameraId);
}
- ActivityRecord topActivity = mDisplayContent.topRunningActivity(
- /* considerKeyguardState= */ true);
- if (topActivity == null || topActivity.getTask() == null) {
- return;
- }
- // Checking whether an activity in fullscreen rather than the task as this camera compat
- // treatment doesn't cover activity embedding.
- if (topActivity.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
- if (topActivity.mLetterboxUiController.isOverrideOrientationOnlyForCameraEnabled()) {
- topActivity.recomputeConfiguration();
+ synchronized (mWmService.mGlobalLock) {
+ ActivityRecord topActivity = mDisplayContent.topRunningActivity(
+ /* considerKeyguardState= */ true);
+ if (topActivity == null || topActivity.getTask() == null) {
+ return;
+ }
+ // Checking whether an activity in fullscreen rather than the task as this camera
+ // compat treatment doesn't cover activity embedding.
+ if (topActivity.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
+ if (topActivity.mLetterboxUiController
+ .isOverrideOrientationOnlyForCameraEnabled()) {
+ topActivity.recomputeConfiguration();
+ }
+ mDisplayContent.updateOrientation();
+ return;
+ }
+ // Checking that the whole app is in multi-window mode as we shouldn't show toast
+ // for the activity embedding case.
+ if (topActivity.getTask().getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW
+ && isTreatmentEnabledForActivity(topActivity, /* mustBeFullscreen */ false)) {
+ showToast(R.string.display_rotation_camera_compat_toast_in_split_screen);
}
- updateOrientationWithWmLock();
- return;
- }
- // Checking that the whole app is in multi-window mode as we shouldn't show toast
- // for the activity embedding case.
- if (topActivity.getTask().getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW
- && isTreatmentEnabledForActivity(topActivity, /* mustBeFullscreen */ false)) {
- showToast(R.string.display_rotation_camera_compat_toast_in_split_screen);
}
}
@@ -441,18 +438,20 @@ final class DisplayRotationCompatPolicy {
ProtoLog.v(WM_DEBUG_ORIENTATION,
"Display id=%d is notified that Camera %s is closed, updating rotation.",
mDisplayContent.mDisplayId, cameraId);
- ActivityRecord topActivity = mDisplayContent.topRunningActivity(
- /* considerKeyguardState= */ true);
- if (topActivity == null
- // Checking whether an activity in fullscreen rather than the task as this camera
- // compat treatment doesn't cover activity embedding.
- || topActivity.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
- return;
- }
- if (topActivity.mLetterboxUiController.isOverrideOrientationOnlyForCameraEnabled()) {
- topActivity.recomputeConfiguration();
+ synchronized (mWmService.mGlobalLock) {
+ ActivityRecord topActivity = mDisplayContent.topRunningActivity(
+ /* considerKeyguardState= */ true);
+ if (topActivity == null
+ // Checking whether an activity in fullscreen rather than the task as this
+ // camera compat treatment doesn't cover activity embedding.
+ || topActivity.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
+ return;
+ }
+ if (topActivity.mLetterboxUiController.isOverrideOrientationOnlyForCameraEnabled()) {
+ topActivity.recomputeConfiguration();
+ }
+ mDisplayContent.updateOrientation();
}
- updateOrientationWithWmLock();
}
private boolean isActivityForCameraIdRefreshing(String cameraId) {
diff --git a/services/core/java/com/android/server/wm/EventLogTags.logtags b/services/core/java/com/android/server/wm/EventLogTags.logtags
index 031e022f0746..594929bea77a 100644
--- a/services/core/java/com/android/server/wm/EventLogTags.logtags
+++ b/services/core/java/com/android/server/wm/EventLogTags.logtags
@@ -66,6 +66,8 @@ option java_package com.android.server.wm
# bootanim finished:
31007 wm_boot_animation_done (time|2|3)
+# Back navigation.
+31100 wm_back_navi_canceled (Reason|3)
# IME surface parent is updated.
32003 imf_update_ime_parent (surface name|3)
diff --git a/services/core/java/com/android/server/wm/ImeTargetVisibilityPolicy.java b/services/core/java/com/android/server/wm/ImeTargetVisibilityPolicy.java
index 471bdf224b59..71dd91785384 100644
--- a/services/core/java/com/android/server/wm/ImeTargetVisibilityPolicy.java
+++ b/services/core/java/com/android/server/wm/ImeTargetVisibilityPolicy.java
@@ -55,11 +55,14 @@ public abstract class ImeTargetVisibilityPolicy {
* @param imeInputTarget The window which start the input connection, receive input from IME.
* @return {@code true} to keep computing the ime parent, {@code false} to defer this operation
*/
- public static boolean isValidToComputeImeParent(@Nullable WindowState imeLayeringTarget,
+ public static boolean canComputeImeParent(@Nullable WindowState imeLayeringTarget,
@Nullable InputTarget imeInputTarget) {
if (imeLayeringTarget == null) {
return false;
}
+ if (shouldComputeImeParentForEmbeddedActivity(imeLayeringTarget, imeInputTarget)) {
+ return true;
+ }
// Ensure changing the IME parent when the layering target that may use IME has
// became to the input target for preventing IME flickers.
// Note that:
@@ -72,9 +75,6 @@ public abstract class ImeTargetVisibilityPolicy {
boolean imeLayeringTargetMayUseIme =
WindowManager.LayoutParams.mayUseInputMethod(imeLayeringTarget.mAttrs.flags)
|| imeLayeringTarget.mAttrs.type == TYPE_APPLICATION_STARTING;
- if (isImeTargetMismatchOnEmbedding(imeLayeringTarget, imeInputTarget)) {
- return true;
- }
// Do not change parent if the window hasn't requested IME.
var inputAndLayeringTargetsDisagree = (imeInputTarget == null
|| imeLayeringTarget.mActivityRecord != imeInputTarget.getActivityRecord());
@@ -83,26 +83,45 @@ public abstract class ImeTargetVisibilityPolicy {
return !inputTargetStale;
}
- private static boolean isImeTargetMismatchOnEmbedding(
+
+ /**
+ * Called from {@link DisplayContent#computeImeParent()} to check the given IME targets if the
+ * IME surface parent should be updated in ActivityEmbeddings.
+ *
+ * As the IME layering target is calculated according to the window hierarchy by
+ * {@link DisplayContent#computeImeTarget}, the layering target and input target may be
+ * different when the window hasn't started input connection, WindowManagerService hasn't yet
+ * received the input target which reported from InputMethodManagerService. To make the IME
+ * surface will be shown on the best fit IME layering target, we basically won't update IME
+ * parent until both IME input and layering target updated for better IME transition.
+ *
+ * However, in activity embedding, tapping a window won't update it to the top window so the
+ * calculated IME layering target may higher than input target. Update IME parent for this case.
+ *
+ * @return {@code true} means the layer of IME layering target is higher than the input target
+ * and {@link DisplayContent#computeImeParent()} should keep progressing to update the IME
+ * surface parent on the display in case the IME surface left behind.
+ */
+ private static boolean shouldComputeImeParentForEmbeddedActivity(
@Nullable WindowState imeLayeringTarget, @Nullable InputTarget imeInputTarget) {
if (imeInputTarget == null || imeLayeringTarget == null) {
return false;
}
+ final WindowState inputTargetWindow = imeInputTarget.getWindowState();
+ if (inputTargetWindow == null || !imeLayeringTarget.isAttached()
+ || !inputTargetWindow.isAttached()) {
+ return false;
+ }
+
final ActivityRecord inputTargetRecord = imeInputTarget.getActivityRecord();
final ActivityRecord layeringTargetRecord = imeLayeringTarget.getActivityRecord();
- final WindowState inputTargetWindow = imeInputTarget.getWindowState();
if (inputTargetRecord == null || layeringTargetRecord == null
- || inputTargetWindow == null) {
+ || inputTargetRecord == layeringTargetRecord
+ || (inputTargetRecord.getTask() != layeringTargetRecord.getTask())
+ || !inputTargetRecord.isEmbedded() || !layeringTargetRecord.isEmbedded()) {
+ // Check whether the input target and layering target are embedded in the same Task.
return false;
}
- final boolean isImeTargetEmbedded = inputTargetRecord.isEmbedded()
- && layeringTargetRecord.isEmbedded();
- // The IME layering target is calculated by the window hierarchy in DisplayContent.
- // The layering target and input target may be different when the window hasn't started
- // input connection, WMS hasn't received the target which reported from IMMS. We basically
- // won't update IME parent for better IME transition.
- // But in activity embedding, tapping a window won't update it to the top window so the IME
- // layering target may higher than input target. Update IME parent for this case.
- return isImeTargetEmbedded && imeLayeringTarget.compareTo(inputTargetWindow) > 0;
+ return imeLayeringTarget.compareTo(inputTargetWindow) > 0;
}
}
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index 25ce5699ab71..c1f2b2be3ea7 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -344,6 +344,19 @@ class InsetsPolicy {
}
}
+ if (!attrs.isFullscreen() || attrs.getFitInsetsTypes() != 0) {
+ if (state == originalState) {
+ state = new InsetsState(originalState);
+ }
+ // Explicitly exclude floating windows from receiving caption insets. This is because we
+ // hard code caption insets for windows due to a synchronization issue that leads to
+ // flickering that bypasses insets frame calculation, which consequently needs us to
+ // remove caption insets from floating windows.
+ // TODO(b/254128050): Remove this workaround after we find a way to update window frames
+ // and caption insets frames simultaneously.
+ state.removeSource(InsetsState.ITYPE_CAPTION_BAR);
+ }
+
final SparseArray<WindowContainerInsetsSourceProvider> providers =
mStateController.getSourceProviders();
final int windowType = attrs.type;
@@ -567,6 +580,13 @@ class InsetsPolicy {
// Notification shade has control anyways, no reason to force anything.
return focusedWin;
}
+ if (focusedWin != null) {
+ final InsetsSourceProvider provider = focusedWin.getControllableInsetProvider();
+ if (provider != null && provider.getSource().getType() == Type.navigationBars()) {
+ // Navigation bar has control if it is focused.
+ return focusedWin;
+ }
+ }
if (mPolicy.isForceShowNavigationBarEnabled() && focusedWin != null
&& focusedWin.getActivityType() == ACTIVITY_TYPE_STANDARD) {
// When "force show navigation bar" is enabled, it means both force visible is true, and
diff --git a/services/core/java/com/android/server/wm/LetterboxConfiguration.java b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
index 513667024caa..fa49a6ba6c2b 100644
--- a/services/core/java/com/android/server/wm/LetterboxConfiguration.java
+++ b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
@@ -22,6 +22,7 @@ import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ALLOW
import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ENABLE_CAMERA_COMPAT_TREATMENT;
import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ENABLE_COMPAT_FAKE_FOCUS;
import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY;
+import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -296,7 +297,6 @@ final class LetterboxConfiguration {
R.bool.config_isCompatFakeFocusEnabled);
mIsPolicyForIgnoringRequestedOrientationEnabled = mContext.getResources().getBoolean(
R.bool.config_letterboxIsPolicyForIgnoringRequestedOrientationEnabled);
-
mIsDisplayRotationImmersiveAppCompatPolicyEnabled = mContext.getResources().getBoolean(
R.bool.config_letterboxIsDisplayRotationImmersiveAppCompatPolicyEnabled);
mDeviceConfig.updateFlagActiveStatus(
@@ -311,7 +311,9 @@ final class LetterboxConfiguration {
mDeviceConfig.updateFlagActiveStatus(
/* isActive */ mIsCompatFakeFocusEnabled,
/* key */ KEY_ENABLE_COMPAT_FAKE_FOCUS);
-
+ mDeviceConfig.updateFlagActiveStatus(
+ /* isActive */ mTranslucentLetterboxingEnabled,
+ /* key */ KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY);
mLetterboxConfigurationPersister = letterboxConfigurationPersister;
mLetterboxConfigurationPersister.start();
}
@@ -1003,7 +1005,7 @@ final class LetterboxConfiguration {
boolean isTranslucentLetterboxingEnabled() {
return mTranslucentLetterboxingOverrideEnabled || (mTranslucentLetterboxingEnabled
- && isTranslucentLetterboxingAllowed());
+ && mDeviceConfig.getFlag(KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY));
}
void setTranslucentLetterboxingEnabled(boolean translucentLetterboxingEnabled) {
@@ -1051,13 +1053,6 @@ final class LetterboxConfiguration {
isDeviceInTabletopMode, nextVerticalPosition);
}
- // TODO(b/262378106): Cache a runtime flag and implement
- // DeviceConfig.OnPropertiesChangedListener
- static boolean isTranslucentLetterboxingAllowed() {
- return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
- "enable_translucent_activity_letterbox", false);
- }
-
/** Whether fake sending focus is enabled for unfocused apps in splitscreen */
boolean isCompatFakeFocusEnabled() {
return mIsCompatFakeFocusEnabled && mDeviceConfig.getFlag(KEY_ENABLE_COMPAT_FAKE_FOCUS);
diff --git a/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java b/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java
index b364872e56e7..df3c8f0fdccc 100644
--- a/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java
+++ b/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java
@@ -48,6 +48,11 @@ final class LetterboxConfigurationDeviceConfig
static final String KEY_ENABLE_COMPAT_FAKE_FOCUS = "enable_compat_fake_focus";
private static final boolean DEFAULT_VALUE_ENABLE_COMPAT_FAKE_FOCUS = true;
+ static final String KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY =
+ "enable_letterbox_translucent_activity";
+
+ private static final boolean DEFAULT_VALUE_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY = true;
+
@VisibleForTesting
static final Map<String, Boolean> sKeyToDefaultValueMap = Map.of(
KEY_ENABLE_CAMERA_COMPAT_TREATMENT,
@@ -57,7 +62,9 @@ final class LetterboxConfigurationDeviceConfig
KEY_ALLOW_IGNORE_ORIENTATION_REQUEST,
DEFAULT_VALUE_ALLOW_IGNORE_ORIENTATION_REQUEST,
KEY_ENABLE_COMPAT_FAKE_FOCUS,
- DEFAULT_VALUE_ENABLE_COMPAT_FAKE_FOCUS
+ DEFAULT_VALUE_ENABLE_COMPAT_FAKE_FOCUS,
+ KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY,
+ DEFAULT_VALUE_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY
);
// Whether camera compatibility treatment is enabled.
@@ -82,6 +89,10 @@ final class LetterboxConfigurationDeviceConfig
// which isn't guaranteed by default in multi-window modes.
private boolean mIsCompatFakeFocusAllowed = DEFAULT_VALUE_ENABLE_COMPAT_FAKE_FOCUS;
+ // Whether the letterbox strategy for transparent activities is allowed
+ private boolean mIsTranslucentLetterboxingAllowed =
+ DEFAULT_VALUE_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY;
+
// Set of active device configs that need to be updated in
// DeviceConfig.OnPropertiesChangedListener#onPropertiesChanged.
private final ArraySet<String> mActiveDeviceConfigsSet = new ArraySet<>();
@@ -129,6 +140,8 @@ final class LetterboxConfigurationDeviceConfig
return mIsAllowIgnoreOrientationRequest;
case KEY_ENABLE_COMPAT_FAKE_FOCUS:
return mIsCompatFakeFocusAllowed;
+ case KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY:
+ return mIsTranslucentLetterboxingAllowed;
default:
throw new AssertionError("Unexpected flag name: " + key);
}
@@ -141,20 +154,20 @@ final class LetterboxConfigurationDeviceConfig
}
switch (key) {
case KEY_ENABLE_CAMERA_COMPAT_TREATMENT:
- mIsCameraCompatTreatmentEnabled =
- getDeviceConfig(key, defaultValue);
+ mIsCameraCompatTreatmentEnabled = getDeviceConfig(key, defaultValue);
break;
case KEY_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY:
mIsDisplayRotationImmersiveAppCompatPolicyEnabled =
getDeviceConfig(key, defaultValue);
break;
case KEY_ALLOW_IGNORE_ORIENTATION_REQUEST:
- mIsAllowIgnoreOrientationRequest =
- getDeviceConfig(key, defaultValue);
+ mIsAllowIgnoreOrientationRequest = getDeviceConfig(key, defaultValue);
break;
case KEY_ENABLE_COMPAT_FAKE_FOCUS:
- mIsCompatFakeFocusAllowed =
- getDeviceConfig(key, defaultValue);
+ mIsCompatFakeFocusAllowed = getDeviceConfig(key, defaultValue);
+ break;
+ case KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY:
+ mIsTranslucentLetterboxingAllowed = getDeviceConfig(key, defaultValue);
break;
default:
throw new AssertionError("Unexpected flag name: " + key);
diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java
index e3437683e957..44b1cc88c0a4 100644
--- a/services/core/java/com/android/server/wm/LetterboxUiController.java
+++ b/services/core/java/com/android/server/wm/LetterboxUiController.java
@@ -97,6 +97,7 @@ import android.view.InsetsState;
import android.view.RoundedCorner;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
+import android.view.WindowInsets;
import android.view.WindowManager;
import com.android.internal.R;
@@ -131,12 +132,6 @@ final class LetterboxUiController {
private final ActivityRecord mActivityRecord;
- /**
- * Taskbar expanded height. Used to determine when to crop an app window to display the
- * rounded corners above the expanded taskbar.
- */
- private final float mExpandedTaskBarHeight;
-
// TODO(b/265576778): Cache other overrides as well.
// Corresponds to OVERRIDE_ANY_ORIENTATION
@@ -193,12 +188,6 @@ final class LetterboxUiController {
// The app compat state for the opaque activity if any
private int mInheritedAppCompatState = APP_COMPAT_STATE_CHANGED__STATE__UNKNOWN;
- // If true it means that the opaque activity beneath a translucent one is in SizeCompatMode.
- private boolean mIsInheritedInSizeCompatMode;
-
- // This is the SizeCompatScale of the opaque activity beneath a translucent one
- private float mInheritedSizeCompatScale;
-
// The CompatDisplayInsets of the opaque activity beneath the translucent one.
private ActivityRecord.CompatDisplayInsets mInheritedCompatDisplayInsets;
@@ -259,9 +248,6 @@ final class LetterboxUiController {
/* checkDeviceConfig */ true),
PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE);
- mExpandedTaskBarHeight =
- getResources().getDimensionPixelSize(R.dimen.taskbar_frame_height);
-
mBooleanPropertyAllowOrientationOverride =
readComponentProperty(packageManager, mActivityRecord.packageName,
/* gatingCondition */ null,
@@ -735,8 +721,21 @@ final class LetterboxUiController {
: mActivityRecord.inMultiWindowMode()
? mActivityRecord.getTask().getBounds()
: mActivityRecord.getRootTask().getParent().getBounds();
+ // In case of translucent activities an option is to use the WindowState#getFrame() of
+ // the first opaque activity beneath. In some cases (e.g. an opaque activity is using
+ // non MATCH_PARENT layouts or a Dialog theme) this might not provide the correct
+ // information and in particular it might provide a value for a smaller area making
+ // the letterbox overlap with the translucent activity's frame.
+ // If we use WindowState#getFrame() for the translucent activity's letterbox inner
+ // frame, the letterbox will then be overlapped with the translucent activity's frame.
+ // Because the surface layer of letterbox is lower than an activity window, this
+ // won't crop the content, but it may affect other features that rely on values stored
+ // in mLetterbox, e.g. transitions, a status bar scrim and recents preview in Launcher
+ // For this reason we use ActivityRecord#getBounds() that the translucent activity
+ // inherits from the first opaque activity beneath and also takes care of the scaling
+ // in case of activities in size compat mode.
final Rect innerFrame = hasInheritedLetterboxBehavior()
- ? mActivityRecord.getWindowConfiguration().getBounds() : w.getFrame();
+ ? mActivityRecord.getBounds() : w.getFrame();
mLetterbox.layout(spaceToFill, innerFrame, mTmpPoint);
} else if (mLetterbox != null) {
mLetterbox.hide();
@@ -863,10 +862,9 @@ final class LetterboxUiController {
return mActivityRecord.mWmService.mContext.getResources();
}
- private void handleHorizontalDoubleTap(int x) {
- // TODO(b/260857308): Investigate if enabling reachability for translucent activity
- if (hasInheritedLetterboxBehavior() || !isHorizontalReachabilityEnabled()
- || mActivityRecord.isInTransition()) {
+ @VisibleForTesting
+ void handleHorizontalDoubleTap(int x) {
+ if (!isHorizontalReachabilityEnabled() || mActivityRecord.isInTransition()) {
return;
}
@@ -904,10 +902,9 @@ final class LetterboxUiController {
mActivityRecord.recomputeConfiguration();
}
- private void handleVerticalDoubleTap(int y) {
- // TODO(b/260857308): Investigate if enabling reachability for translucent activity
- if (hasInheritedLetterboxBehavior() || !isVerticalReachabilityEnabled()
- || mActivityRecord.isInTransition()) {
+ @VisibleForTesting
+ void handleVerticalDoubleTap(int y) {
+ if (!isVerticalReachabilityEnabled() || mActivityRecord.isInTransition()) {
return;
}
@@ -1131,11 +1128,13 @@ final class LetterboxUiController {
@VisibleForTesting
@Nullable
InsetsSource getExpandedTaskbarOrNull(final WindowState mainWindow) {
- final InsetsSource taskbar = mainWindow.getInsetsState().peekSource(
- InsetsState.ITYPE_EXTRA_NAVIGATION_BAR);
- if (taskbar != null && taskbar.isVisible()
- && taskbar.getFrame().height() >= mExpandedTaskBarHeight) {
- return taskbar;
+ final InsetsState state = mainWindow.getInsetsState();
+ for (int i = state.sourceSize() - 1; i >= 0; i--) {
+ final InsetsSource source = state.sourceAt(i);
+ if (source.getType() == WindowInsets.Type.navigationBars()
+ && source.insetsRoundedCornerFrame() && source.isVisible()) {
+ return source;
+ }
}
return null;
}
@@ -1386,10 +1385,10 @@ final class LetterboxUiController {
mLetterboxConfigListener.onRemoved();
clearInheritedConfig();
}
- // In case mActivityRecord.getCompatDisplayInsets() is not null we don't apply the
+ // In case mActivityRecord.hasCompatDisplayInsetsWithoutOverride() we don't apply the
// opaque activity constraints because we're expecting the activity is already letterboxed.
- if (mActivityRecord.getTask() == null || mActivityRecord.getCompatDisplayInsets() != null
- || mActivityRecord.fillsParent()) {
+ if (mActivityRecord.getTask() == null || mActivityRecord.fillsParent()
+ || mActivityRecord.hasCompatDisplayInsetsWithoutInheritance()) {
return;
}
final ActivityRecord firstOpaqueActivityBeneath = mActivityRecord.getTask().getActivity(
@@ -1417,6 +1416,7 @@ final class LetterboxUiController {
// We need to initialize appBounds to avoid NPE. The actual value will
// be set ahead when resolving the Configuration for the activity.
mutatedConfiguration.windowConfiguration.setAppBounds(new Rect());
+ inheritConfiguration(firstOpaqueActivityBeneath);
return mutatedConfiguration;
});
}
@@ -1457,16 +1457,12 @@ final class LetterboxUiController {
return mInheritedAppCompatState;
}
- float getInheritedSizeCompatScale() {
- return mInheritedSizeCompatScale;
- }
-
@Configuration.Orientation
int getInheritedOrientation() {
return mInheritedOrientation;
}
- public ActivityRecord.CompatDisplayInsets getInheritedCompatDisplayInsets() {
+ ActivityRecord.CompatDisplayInsets getInheritedCompatDisplayInsets() {
return mInheritedCompatDisplayInsets;
}
@@ -1486,7 +1482,7 @@ final class LetterboxUiController {
* @return The first not finishing opaque activity beneath the current translucent activity
* if it exists and the strategy is enabled.
*/
- private Optional<ActivityRecord> findOpaqueNotFinishingActivityBelow() {
+ Optional<ActivityRecord> findOpaqueNotFinishingActivityBelow() {
if (!hasInheritedLetterboxBehavior() || mActivityRecord.getTask() == null) {
return Optional.empty();
}
@@ -1508,8 +1504,6 @@ final class LetterboxUiController {
}
mInheritedOrientation = firstOpaque.getRequestedConfigurationOrientation();
mInheritedAppCompatState = firstOpaque.getAppCompatState();
- mIsInheritedInSizeCompatMode = firstOpaque.inSizeCompatMode();
- mInheritedSizeCompatScale = firstOpaque.getCompatScale();
mInheritedCompatDisplayInsets = firstOpaque.getCompatDisplayInsets();
}
@@ -1519,8 +1513,6 @@ final class LetterboxUiController {
mInheritedMaxAspectRatio = UNDEFINED_ASPECT_RATIO;
mInheritedOrientation = Configuration.ORIENTATION_UNDEFINED;
mInheritedAppCompatState = APP_COMPAT_STATE_CHANGED__STATE__UNKNOWN;
- mIsInheritedInSizeCompatMode = false;
- mInheritedSizeCompatScale = 1f;
mInheritedCompatDisplayInsets = null;
}
}
diff --git a/services/core/java/com/android/server/wm/OWNERS b/services/core/java/com/android/server/wm/OWNERS
index 4f506a5dd945..07f3bc6a53f3 100644
--- a/services/core/java/com/android/server/wm/OWNERS
+++ b/services/core/java/com/android/server/wm/OWNERS
@@ -14,6 +14,7 @@ winsonc@google.com
tigerhuang@google.com
lihongyu@google.com
mariiasand@google.com
+rgl@google.com
per-file BackgroundActivityStartController.java = set noparent
per-file BackgroundActivityStartController.java = brufino@google.com, ogunwale@google.com, louischang@google.com, lus@google.com, rickywai@google.com
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 8c0b5b9865fc..e147219de4c6 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -33,6 +33,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
import static android.view.WindowManager.TRANSIT_NONE;
import static android.view.WindowManager.TRANSIT_PIP;
+import static android.view.WindowManager.TRANSIT_SLEEP;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_WAKE;
@@ -1997,6 +1998,14 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
// of the activity entering PIP
r.getDisplayContent().prepareAppTransition(TRANSIT_NONE);
+ transitionController.collect(task);
+
+ // Defer the windowing mode change until after the transition to prevent the activity
+ // from doing work and changing the activity visuals while animating
+ // TODO(task-org): Figure-out more structured way to do this long term.
+ r.setWindowingMode(r.getWindowingMode());
+ r.mWaitForEnteringPinnedMode = true;
+
final TaskFragment organizedTf = r.getOrganizedTaskFragment();
final boolean singleActivity = task.getNonFinishingActivityCount() == 1;
if (singleActivity) {
@@ -2004,6 +2013,30 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
// Apply the last recents animation leash transform to the task entering PIP
rootTask.maybeApplyLastRecentsAnimationTransaction();
+
+ if (rootTask.getParent() != taskDisplayArea) {
+ // root task is nested, but pinned tasks need to be direct children of their
+ // display area, so reparent.
+ rootTask.reparent(taskDisplayArea, true /* onTop */);
+ }
+
+ rootTask.forAllTaskFragments(tf -> {
+ if (!tf.isOrganizedTaskFragment()) {
+ return;
+ }
+ tf.resetAdjacentTaskFragment();
+ tf.setCompanionTaskFragment(null /* companionTaskFragment */);
+ tf.setAnimationParams(TaskFragmentAnimationParams.DEFAULT);
+ if (tf.getTopNonFinishingActivity() != null) {
+ // When the Task is entering picture-in-picture, we should clear all
+ // override from the client organizer, so the PIP activity can get the
+ // correct config from the Task, and prevent conflict with the
+ // PipTaskOrganizer. TaskFragmentOrganizer may have requested relative
+ // bounds, so reset the relative bounds before update configuration.
+ tf.setRelativeEmbeddedBounds(new Rect());
+ tf.updateRequestedOverrideConfiguration(EMPTY);
+ }
+ });
} else {
// In the case of multiple activities, we will create a new task for it and then
// move the PIP activity into the task. Note that we explicitly defer the task
@@ -2016,6 +2049,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
.setIntent(r.intent)
.setDeferTaskAppear(true)
.setHasBeenVisible(true)
+ .setWindowingMode(task.getRequestedOverrideWindowingMode())
.build();
// Establish bi-directional link between the original and pinned task.
r.setLastParentBeforePip(launchIntoPipHostActivity);
@@ -2049,6 +2083,16 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
organizedTf.mClearedTaskFragmentForPip = true;
}
+ transitionController.collect(rootTask);
+
+ if (transitionController.isShellTransitionsEnabled()) {
+ // set mode NOW so that when we reparent the activity, it won't be resumed.
+ // During recents animations, the original task is "occluded" by launcher but
+ // it wasn't paused (due to transient-launch). If we reparent to the (top) task
+ // now, it will take focus briefly which confuses the RecentTasks tracker.
+ rootTask.setWindowingMode(WINDOWING_MODE_PINNED);
+ }
+
// There are multiple activities in the task and moving the top activity should
// reveal/leave the other activities in their original task.
// On the other hand, ActivityRecord#onParentChanged takes care of setting the
@@ -2073,40 +2117,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
}
}
- transitionController.collect(rootTask);
-
- // The intermediate windowing mode to be set on the ActivityRecord later.
- // This needs to happen before the re-parenting, otherwise we will always set the
- // ActivityRecord to be fullscreen.
- final int intermediateWindowingMode = rootTask.getWindowingMode();
- if (rootTask.getParent() != taskDisplayArea) {
- // root task is nested, but pinned tasks need to be direct children of their
- // display area, so reparent.
- rootTask.reparent(taskDisplayArea, true /* onTop */);
- }
-
- // Defer the windowing mode change until after the transition to prevent the activity
- // from doing work and changing the activity visuals while animating
- // TODO(task-org): Figure-out more structured way to do this long term.
- r.setWindowingMode(intermediateWindowingMode);
- r.mWaitForEnteringPinnedMode = true;
- rootTask.forAllTaskFragments(tf -> {
- if (!tf.isOrganizedTaskFragment()) {
- return;
- }
- tf.resetAdjacentTaskFragment();
- tf.setCompanionTaskFragment(null /* companionTaskFragment */);
- tf.setAnimationParams(TaskFragmentAnimationParams.DEFAULT);
- if (tf.getTopNonFinishingActivity() != null) {
- // When the Task is entering picture-in-picture, we should clear all override
- // from the client organizer, so the PIP activity can get the correct config
- // from the Task, and prevent conflict with the PipTaskOrganizer.
- // TaskFragmentOrganizer may have requested relative bounds, so reset the
- // relative bounds before update configuration.
- tf.setRelativeEmbeddedBounds(new Rect());
- tf.updateRequestedOverrideConfiguration(EMPTY);
- }
- });
+ // TODO(remove-legacy-transit): Move this to the `singleActivity` case when removing
+ // legacy transit.
rootTask.setWindowingMode(WINDOWING_MODE_PINNED);
// Set the launch bounds for launch-into-pip Activity on the root task.
if (r.getOptions() != null && r.getOptions().isLaunchIntoPip()) {
@@ -2318,6 +2330,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
}
void applySleepTokens(boolean applyToRootTasks) {
+ boolean builtSleepTransition = false;
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
// Set the sleeping state of the display.
final DisplayContent display = getChildAt(displayNdx);
@@ -2327,6 +2340,30 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
}
display.setIsSleeping(displayShouldSleep);
+ if (display.mTransitionController.isShellTransitionsEnabled() && !builtSleepTransition
+ // Only care if there are actual sleep tokens.
+ && displayShouldSleep && !display.mAllSleepTokens.isEmpty()) {
+ builtSleepTransition = true;
+ // We don't actually care about collecting anything here. We really just want
+ // this as a signal to the transition-player.
+ final Transition transition = new Transition(TRANSIT_SLEEP, 0 /* flags */,
+ display.mTransitionController, mWmService.mSyncEngine);
+ final Runnable sendSleepTransition = () -> {
+ display.mTransitionController.requestStartTransition(transition,
+ null /* trigger */, null /* remote */, null /* display */);
+ // Force playing immediately so that unrelated ops can't be collected.
+ transition.playNow();
+ };
+ if (display.mTransitionController.isCollecting()) {
+ mWmService.mSyncEngine.queueSyncSet(
+ () -> display.mTransitionController.moveToCollecting(transition),
+ sendSleepTransition);
+ } else {
+ display.mTransitionController.moveToCollecting(transition);
+ sendSleepTransition.run();
+ }
+ }
+
if (!applyToRootTasks) {
continue;
}
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 97e0b1e0de2c..ce9bff8521e6 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -948,7 +948,7 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
synchronized (mService.mGlobalLock) {
WindowState windowState = mService.windowForClientLocked(this, window, false);
if (windowState == null) {
- Slog.e(TAG_WM,
+ Slog.i(TAG_WM,
"setOnBackInvokedCallback(): No window state for package:" + mPackageName);
} else {
windowState.setOnBackInvokedCallbackInfo(callbackInfo);
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index c7d855360df9..7433c7e58392 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -2035,6 +2035,10 @@ class Task extends TaskFragment {
Rect outOverrideBounds = getResolvedOverrideConfiguration().windowConfiguration.getBounds();
if (windowingMode == WINDOWING_MODE_FULLSCREEN) {
+ if (!mCreatedByOrganizer) {
+ // Use empty bounds to indicate "fill parent".
+ outOverrideBounds.setEmpty();
+ }
// The bounds for fullscreen mode shouldn't be adjusted by minimal size. Otherwise if
// the parent or display is smaller than the size, the content may be cropped.
return;
@@ -2825,19 +2829,23 @@ class Task extends TaskFragment {
* Account for specified insets to crop the animation bounds by to avoid the animation
* occurring over "out of bounds" regions
*
- * For example this is used to make sure the tasks are cropped to be fully above the
+ * For example this is used to make sure the tasks are cropped to be fully above the expanded
* taskbar when animating.
*
- * @param animationBounds The animations bounds to adjust to account for the custom spec insets.
+ * TEMPORARY FIELD (b/202383002)
+ * TODO: Remove once we use surfaceflinger rounded corners on tasks rather than taskbar overlays
+ * or when shell transitions are fully enabled
+ *
+ * @param animationBounds The animation bounds to adjust to account for the custom spec insets.
*/
void adjustAnimationBoundsForTransition(Rect animationBounds) {
TaskTransitionSpec spec = mWmService.mTaskTransitionSpec;
if (spec != null) {
final InsetsState state =
getDisplayContent().getInsetsStateController().getRawInsetsState();
- for (int id : spec.animationBoundInsets) {
- final InsetsSource source = state.peekSource(id);
- if (source != null) {
+ for (int i = state.sourceSize() - 1; i >= 0; i--) {
+ final InsetsSource source = state.sourceAt(i);
+ if (source.insetsRoundedCornerFrame()) {
animationBounds.inset(source.calculateVisibleInsets(animationBounds));
}
}
@@ -3389,6 +3397,11 @@ class Task extends TaskFragment {
&& top.getOrganizedTask() == this && top.isState(RESUMED);
// Whether the direct top activity is in size compat mode on foreground.
info.topActivityInSizeCompat = isTopActivityResumed && top.inSizeCompatMode();
+ if (info.topActivityInSizeCompat
+ && mWmService.mLetterboxConfiguration.isTranslucentLetterboxingEnabled()) {
+ // We hide the restart button in case of transparent activities.
+ info.topActivityInSizeCompat = top.fillsParent();
+ }
// Whether the direct top activity is eligible for letterbox education.
info.topActivityEligibleForLetterboxEducation = isTopActivityResumed
&& top.isEligibleForLetterboxEducation();
@@ -3503,10 +3516,7 @@ class Task extends TaskFragment {
info.isKeyguardOccluded =
mAtmService.mKeyguardController.isDisplayOccluded(DEFAULT_DISPLAY);
- info.startingWindowTypeParameter = activity.mStartingData != null
- ? activity.mStartingData.mTypeParams
- : (StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_CREATED
- | StartingWindowInfo.TYPE_PARAMETER_WINDOWLESS);
+ info.startingWindowTypeParameter = activity.mStartingData.mTypeParams;
if ((info.startingWindowTypeParameter
& StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_CREATED) != 0) {
final WindowState topMainWin = getWindow(w -> w.mAttrs.type == TYPE_BASE_APPLICATION);
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index 8cbd553fbebd..76759ba53f5a 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -49,6 +49,7 @@ import android.util.IntArray;
import android.util.Slog;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
+import android.view.WindowManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
@@ -1225,7 +1226,7 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> {
// Clear last paused activity if focused root task changed while sleeping, so that the
// top activity of current focused task can be resumed.
- if (mDisplayContent.isSleeping()) {
+ if (mDisplayContent.isSleeping() && currentFocusedTask != null) {
currentFocusedTask.clearLastPausedActivity();
}
@@ -1486,7 +1487,7 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> {
*/
private boolean isLargeEnoughForMultiWindow() {
return getConfiguration().smallestScreenWidthDp
- >= mAtmService.mLargeScreenSmallestScreenWidthDp;
+ >= WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP;
}
boolean isTopRootTask(Task rootTask) {
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index c2afeaf8990e..035859e4b87f 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -1933,7 +1933,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
1f);
mBackScreenshots.put(r.mActivityComponent.flattenToString(), backBuffer);
}
- child.asActivityRecord().inHistory = true;
+ addingActivity.inHistory = true;
task.onDescendantActivityAdded(taskHadActivity, activityType, addingActivity);
}
}
@@ -2574,6 +2574,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
*/
TaskFragmentInfo getTaskFragmentInfo() {
List<IBinder> childActivities = new ArrayList<>();
+ List<IBinder> inRequestedTaskFragmentActivities = new ArrayList<>();
for (int i = 0; i < getChildCount(); i++) {
final WindowContainer<?> wc = getChildAt(i);
final ActivityRecord ar = wc.asActivityRecord();
@@ -2582,6 +2583,9 @@ class TaskFragment extends WindowContainer<WindowContainer> {
&& ar.getUid() == mTaskFragmentOrganizerUid && !ar.finishing) {
// Only includes Activities that belong to the organizer process for security.
childActivities.add(ar.token);
+ if (ar.mRequestedLaunchingTaskFragmentToken == mFragmentToken) {
+ inRequestedTaskFragmentActivities.add(ar.token);
+ }
}
}
final Point positionInParent = new Point();
@@ -2593,6 +2597,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
getNonFinishingActivityCount(),
shouldBeVisible(null /* starting */),
childActivities,
+ inRequestedTaskFragmentActivities,
positionInParent,
mClearedTaskForReuse,
mClearedTaskFragmentForPip,
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index b13136534de3..3a30e4b0cf1f 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -16,7 +16,6 @@
package com.android.server.wm;
-import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.TaskInfo.cameraCompatControlStateToString;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER;
@@ -44,7 +43,6 @@ import android.view.Display;
import android.view.SurfaceControl;
import android.window.ITaskOrganizer;
import android.window.ITaskOrganizerController;
-import android.window.IWindowlessStartingSurfaceCallback;
import android.window.SplashScreenView;
import android.window.StartingWindowInfo;
import android.window.StartingWindowRemovalInfo;
@@ -658,10 +656,9 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
info.splashScreenThemeResId = launchTheme;
}
info.taskSnapshot = taskSnapshot;
- info.appToken = activity.token;
// make this happen prior than prepare surface
try {
- lastOrganizer.addStartingWindow(info);
+ lastOrganizer.addStartingWindow(info, activity.token);
} catch (RemoteException e) {
Slog.e(TAG, "Exception sending onTaskStart callback", e);
return false;
@@ -707,55 +704,6 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
}
}
- /**
- * Create a starting surface which attach on a given surface.
- * @param activity Target activity, this isn't necessary to be the top activity.
- * @param root The root surface which the created surface will attach on.
- * @param taskSnapshot Whether to draw snapshot.
- * @param callback Called when surface is drawn and attached to the root surface.
- * @return The taskId, this is a token and should be used to remove the surface, even if
- * the task was removed from hierarchy.
- */
- int addWindowlessStartingSurface(Task task, ActivityRecord activity, SurfaceControl root,
- TaskSnapshot taskSnapshot, IWindowlessStartingSurfaceCallback callback) {
- final Task rootTask = task.getRootTask();
- if (rootTask == null) {
- return INVALID_TASK_ID;
- }
- final ITaskOrganizer lastOrganizer = mTaskOrganizers.peekLast();
- if (lastOrganizer == null) {
- return INVALID_TASK_ID;
- }
- final StartingWindowInfo info = task.getStartingWindowInfo(activity);
- info.taskInfo.taskDescription = activity.taskDescription;
- info.taskSnapshot = taskSnapshot;
- info.windowlessStartingSurfaceCallback = callback;
- info.rootSurface = root;
- try {
- lastOrganizer.addStartingWindow(info);
- } catch (RemoteException e) {
- Slog.e(TAG, "Exception sending addWindowlessStartingSurface ", e);
- return INVALID_TASK_ID;
- }
- return task.mTaskId;
- }
-
- void removeWindowlessStartingSurface(int taskId, boolean immediately) {
- final ITaskOrganizer lastOrganizer = mTaskOrganizers.peekLast();
- if (lastOrganizer == null || taskId == 0) {
- return;
- }
- final StartingWindowRemovalInfo removalInfo = new StartingWindowRemovalInfo();
- removalInfo.taskId = taskId;
- removalInfo.windowlessSurface = true;
- removalInfo.removeImmediately = immediately;
- try {
- lastOrganizer.removeStartingWindow(removalInfo);
- } catch (RemoteException e) {
- Slog.e(TAG, "Exception sending removeWindowlessStartingSurface ", e);
- }
- }
-
boolean copySplashScreenView(Task task) {
final Task rootTask = task.getRootTask();
if (rootTask == null) {
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index a68b3cb2a2ea..879323e16ed3 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -218,6 +218,9 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
final TransitionController.Logger mLogger = new TransitionController.Logger();
+ /** Whether this transition was forced to play early (eg for a SLEEP signal). */
+ private boolean mForcePlaying = false;
+
/**
* {@code false} if this transition runs purely in WMCore (meaning Shell is completely unaware
* of it). Currently, this happens before the display is ready since nothing can be seen yet.
@@ -813,7 +816,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
}
boolean hasParticipatedDisplay = false;
- boolean reportTaskStackChanged = false;
+ boolean hasVisibleTransientLaunch = false;
// Commit all going-invisible containers
for (int i = 0; i < mParticipants.size(); ++i) {
final WindowContainer<?> participant = mParticipants.valueAt(i);
@@ -856,7 +859,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
&& ar.isVisible()) {
// Transient launch was committed, so report enteringAnimation
ar.mEnteringAnimation = true;
- reportTaskStackChanged = true;
+ hasVisibleTransientLaunch = true;
// Since transient launches don't automatically take focus, make sure we
// synchronize focus since we committed to the launch.
@@ -900,8 +903,14 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
}
}
- if (reportTaskStackChanged) {
+ if (hasVisibleTransientLaunch) {
+ // Notify the change about the transient-below task that becomes invisible.
mController.mAtm.getTaskChangeNotificationController().notifyTaskStackChanged();
+ // Prevent spurious background app switches.
+ mController.mAtm.stopAppSwitches();
+ // The end of transient launch may not reorder task, so make sure to compute the latest
+ // task rank according to the current visibility.
+ mController.mAtm.mRootWindowContainer.rankTaskLayers();
}
// dispatch legacy callback in a different loop. This is because multiple legacy handlers
@@ -983,6 +992,9 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
cleanUpInternal();
mController.updateAnimatingState(mTmpTransaction);
mTmpTransaction.apply();
+
+ // Handle back animation if it's already started.
+ mController.mAtm.mBackNavigationController.handleDeferredBackAnimation(mTargets);
}
void abort() {
@@ -998,6 +1010,25 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
mController.dispatchLegacyAppTransitionCancelled();
}
+ /** Immediately moves this to playing even if it isn't started yet. */
+ void playNow() {
+ if (mState == STATE_PLAYING) return;
+ ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Force Playing Transition: %d",
+ mSyncId);
+ mForcePlaying = true;
+ setAllReady();
+ if (mState == STATE_COLLECTING) {
+ start();
+ }
+ // Don't wait for actual surface-placement. We don't want anything else collected in this
+ // transition.
+ mSyncEngine.onSurfacePlacement();
+ }
+
+ boolean isForcePlaying() {
+ return mForcePlaying;
+ }
+
void setRemoteTransition(RemoteTransition remoteTransition) {
mRemoteTransition = remoteTransition;
}
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index bb706ecafa64..da7400c64b40 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -123,7 +123,6 @@ import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
-import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiFunction;
import java.util.function.Consumer;
@@ -3193,8 +3192,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
animationRunnerBuilder.setTaskBackgroundColor(getTaskAnimationBackgroundColor());
// TODO: Remove when we migrate to shell (b/202383002)
if (mWmService.mTaskTransitionSpec != null) {
- animationRunnerBuilder.hideInsetSourceViewOverflows(
- mWmService.mTaskTransitionSpec.animationBoundInsets);
+ animationRunnerBuilder.hideInsetSourceViewOverflows();
}
}
@@ -4115,11 +4113,12 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
}
}
- private void hideInsetSourceViewOverflows(Set<Integer> sourceIds) {
- final InsetsStateController controller = getDisplayContent().getInsetsStateController();
- for (int id : sourceIds) {
- final InsetsSourceProvider insetProvider = controller.peekSourceProvider(id);
- if (insetProvider == null) {
+ private void hideInsetSourceViewOverflows() {
+ final SparseArray<WindowContainerInsetsSourceProvider> providers =
+ getDisplayContent().getInsetsStateController().getSourceProviders();
+ for (int i = providers.size(); i >= 0; i--) {
+ final InsetsSourceProvider insetProvider = providers.valueAt(i);
+ if (!insetProvider.getSource().insetsRoundedCornerFrame()) {
return;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 41c112526787..98563f6e73fc 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -7357,7 +7357,8 @@ public class WindowManagerService extends IWindowManager.Stub
ProtoLog.w(WM_ERROR, "unable to restore pointer icon");
}
} else {
- InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_DEFAULT);
+ mContext.getSystemService(InputManager.class)
+ .setPointerIconType(PointerIcon.TYPE_DEFAULT);
}
}
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 8e22821820a1..495d7ce4e90b 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -74,7 +74,9 @@ import android.graphics.Point;
import android.graphics.Rect;
import android.os.Binder;
import android.os.Bundle;
+import android.os.Handler;
import android.os.IBinder;
+import android.os.Looper;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.AndroidRuntimeException;
@@ -315,7 +317,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
}
transition = mTransitionController.createTransition(type);
}
- if (!transition.isCollecting()) {
+ if (!transition.isCollecting() && !transition.isForcePlaying()) {
Slog.e(TAG, "Trying to start a transition that isn't collecting. This probably"
+ " means Shell took too long to respond to a request. WM State may be"
+ " incorrect now, please file a bug");
@@ -998,11 +1000,14 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
activityOptions.setCallerDisplayId(DEFAULT_DISPLAY);
}
final Bundle options = activityOptions != null ? activityOptions.toBundle() : null;
- waitAsyncStart(() -> mService.mAmInternal.sendIntentSender(
+ int res = waitAsyncStart(() -> mService.mAmInternal.sendIntentSender(
hop.getPendingIntent().getTarget(),
hop.getPendingIntent().getWhitelistToken(), 0 /* code */,
hop.getActivityIntent(), resolvedType, null /* finishReceiver */,
null /* requiredPermission */, options));
+ if (ActivityManager.isStartResultSuccessful(res)) {
+ effects |= TRANSACT_EFFECTS_LIFECYCLE;
+ }
break;
}
case HIERARCHY_OP_TYPE_START_SHORTCUT: {
@@ -1353,9 +1358,16 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
* Post and wait for the result of the activity start to prevent potential deadlock against
* {@link WindowManagerGlobalLock}.
*/
- private void waitAsyncStart(IntSupplier startActivity) {
+ private int waitAsyncStart(IntSupplier startActivity) {
final Integer[] starterResult = {null};
- mService.mH.post(() -> {
+ final Handler handler = (Looper.myLooper() == mService.mH.getLooper())
+ // uncommon case where a queued transaction is trying to start an activity. We can't
+ // post to our own thread and wait (otherwise we deadlock), so use anim thread
+ // instead (which is 1 higher priority).
+ ? mService.mWindowManager.mAnimationHandler
+ // Otherwise just put it on main handler
+ : mService.mH;
+ handler.post(() -> {
try {
starterResult[0] = startActivity.getAsInt();
} catch (Throwable t) {
@@ -1372,6 +1384,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
} catch (InterruptedException ignored) {
}
}
+ return starterResult[0];
}
private int sanitizeAndApplyHierarchyOp(WindowContainer container,
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index e56b6792f491..694f1be67d1a 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -54,7 +54,6 @@ import android.app.BackgroundStartPrivileges;
import android.app.IApplicationThread;
import android.app.ProfilerInfo;
import android.app.servertransaction.ConfigurationChangeItem;
-import android.companion.virtual.VirtualDeviceManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -211,7 +210,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
/** Whether {@link #mLastReportedConfiguration} is deferred by the cached state. */
private volatile boolean mHasCachedConfiguration;
- private int mTopActivityDeviceId = VirtualDeviceManager.DEVICE_ID_DEFAULT;
+ private int mLastTopActivityDeviceId = Context.DEVICE_ID_DEFAULT;
/**
* Registered {@link DisplayArea} as a listener to override config changes. {@code null} if not
* registered.
@@ -1412,8 +1411,9 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
// If deviceId for the top-activity changed, schedule passing it to the app process.
boolean topActivityDeviceChanged = false;
int deviceId = getTopActivityDeviceId();
- if (deviceId != mTopActivityDeviceId) {
+ if (deviceId != mLastTopActivityDeviceId) {
topActivityDeviceChanged = true;
+ mLastTopActivityDeviceId = deviceId;
}
final Configuration config = getConfiguration();
@@ -1432,15 +1432,12 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
return;
}
- // TODO(b/263402938): Add tests that capture the deviceId dispatch to the client.
- mTopActivityDeviceId = deviceId;
- dispatchConfiguration(config, topActivityDeviceChanged ? mTopActivityDeviceId
- : VirtualDeviceManager.DEVICE_ID_INVALID);
+ dispatchConfiguration(config);
}
private int getTopActivityDeviceId() {
ActivityRecord topActivity = getTopNonFinishingActivity();
- int updatedDeviceId = mTopActivityDeviceId;
+ int updatedDeviceId = Context.DEVICE_ID_DEFAULT;
if (topActivity != null && topActivity.mDisplayContent != null) {
updatedDeviceId = mAtm.mTaskSupervisor.getDeviceIdForDisplayId(
topActivity.mDisplayContent.mDisplayId);
@@ -1485,10 +1482,6 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
}
void dispatchConfiguration(Configuration config) {
- dispatchConfiguration(config, getTopActivityDeviceId());
- }
-
- void dispatchConfiguration(Configuration config, int deviceId) {
mHasPendingConfigurationChange = false;
if (mThread == null) {
if (Build.IS_DEBUGGABLE && mHasImeService) {
@@ -1515,16 +1508,10 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
}
}
- scheduleConfigurationChange(mThread, config, deviceId);
+ scheduleConfigurationChange(mThread, config);
}
private void scheduleConfigurationChange(IApplicationThread thread, Configuration config) {
- // By default send invalid deviceId as no-op signal so it's not updated on the client side.
- scheduleConfigurationChange(thread, config, VirtualDeviceManager.DEVICE_ID_INVALID);
- }
-
- private void scheduleConfigurationChange(IApplicationThread thread, Configuration config,
- int deviceId) {
ProtoLog.v(WM_DEBUG_CONFIGURATION, "Sending to proc %s new config %s", mName,
config);
if (Build.IS_DEBUGGABLE && mHasImeService) {
@@ -1534,7 +1521,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
mHasCachedConfiguration = false;
try {
mAtm.getLifecycleManager().scheduleTransaction(thread,
- ConfigurationChangeItem.obtain(config, deviceId));
+ ConfigurationChangeItem.obtain(config, mLastTopActivityDeviceId));
} catch (Exception e) {
Slog.e(TAG_CONFIGURATION, "Failed to schedule configuration change: " + mOwner, e);
}
@@ -1839,6 +1826,9 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
pw.print("F|");
}
}
+ if ((stateFlags & ACTIVITY_STATE_FLAG_HAS_ACTIVITY_IN_VISIBLE_TASK) != 0) {
+ pw.print("VT|");
+ }
final int taskLayer = stateFlags & ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER;
if (taskLayer != ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER) {
pw.print("taskLayer=" + taskLayer);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 87e87b95fdfd..09f7fb6c794e 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2342,9 +2342,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
@Override
public void onConfigurationChanged(Configuration newParentConfig) {
- mTempConfiguration.setTo(getConfiguration());
+ // Get from super to avoid using the updated global config from the override method.
+ final Configuration selfConfiguration = super.getConfiguration();
+ mTempConfiguration.setTo(selfConfiguration);
super.onConfigurationChanged(newParentConfig);
- final int diff = getConfiguration().diff(mTempConfiguration);
+ final int diff = selfConfiguration.diff(mTempConfiguration);
if (diff != 0) {
mLastConfigReportedToClient = false;
}
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index a102986832fe..e8625bc3d64b 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -32,7 +32,6 @@ import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;
-import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
@@ -424,7 +423,7 @@ class WindowStateAnimator {
computeShownFrameLocked();
- if (w.isParentWindowHidden() || !w.isOnScreen()) {
+ if (!w.isOnScreen()) {
hide(t, "prepareSurfaceLocked");
mWallpaperControllerLocked.hideWallpapers(w);
@@ -449,30 +448,23 @@ class WindowStateAnimator {
if (prepared && mDrawState == HAS_DRAWN) {
if (mLastHidden) {
- if (showSurfaceRobustlyLocked(t)) {
- mAnimator.requestRemovalOfReplacedWindows(w);
- mLastHidden = false;
- final DisplayContent displayContent = w.getDisplayContent();
- if (!displayContent.getLastHasContent()) {
- // This draw means the difference between unique content and mirroring.
- // Run another pass through performLayout to set mHasContent in the
- // LogicalDisplay.
- displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
- if (DEBUG_LAYOUT_REPEATS) {
- mService.mWindowPlacerLocked.debugLayoutRepeats(
- "showSurfaceRobustlyLocked " + w,
- displayContent.pendingLayoutChanges);
- }
+ mSurfaceController.showRobustly(t);
+ mAnimator.requestRemovalOfReplacedWindows(w);
+ mLastHidden = false;
+ final DisplayContent displayContent = w.getDisplayContent();
+ if (!displayContent.getLastHasContent()) {
+ // This draw means the difference between unique content and mirroring.
+ // Run another pass through performLayout to set mHasContent in the
+ // LogicalDisplay.
+ displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
+ if (DEBUG_LAYOUT_REPEATS) {
+ mService.mWindowPlacerLocked.debugLayoutRepeats(
+ "showSurfaceRobustlyLocked " + w,
+ displayContent.pendingLayoutChanges);
}
- } else {
- w.setOrientationChanging(false);
}
}
}
- } else {
- if (mWin.isAnimating(TRANSITION | PARENTS)) {
- ProtoLog.v(WM_DEBUG_ANIM, "prepareSurface: No changes in animation for %s", this);
- }
}
if (w.getOrientationChanging()) {
@@ -511,22 +503,6 @@ class WindowStateAnimator {
mSurfaceController.setColorSpaceAgnostic(mWin.getPendingTransaction(), agnostic);
}
- /**
- * Have the surface flinger show a surface, robustly dealing with
- * error conditions. In particular, if there is not enough memory
- * to show the surface, then we will try to get rid of other surfaces
- * in order to succeed.
- *
- * @return Returns true if the surface was successfully shown.
- */
- private boolean showSurfaceRobustlyLocked(SurfaceControl.Transaction t) {
- boolean shown = mSurfaceController.showRobustly(t);
- if (!shown)
- return false;
-
- return true;
- }
-
void applyEnterAnimationLocked() {
// If we are the new part of a window replacement transition and we have requested
// not to animate, we instead want to make it seamless, so we don't want to apply
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index 607ce251c4d1..33751b9f16a0 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -245,13 +245,13 @@ class WindowSurfaceController {
t.setColorSpaceAgnostic(mSurfaceControl, agnostic);
}
- boolean showRobustly(SurfaceControl.Transaction t) {
+ void showRobustly(SurfaceControl.Transaction t) {
ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE SHOW (performLayout): %s", title);
if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this
+ " during relayout");
if (mSurfaceShown) {
- return true;
+ return;
}
setShown(true);
@@ -262,7 +262,6 @@ class WindowSurfaceController {
dc.mDisplayId, 1 /* request shown */,
String.valueOf(dc.mWallpaperController.getWallpaperTarget()));
}
- return true;
}
boolean clearWindowContentFrameStats() {
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index e2bdcdd518d5..2ce86add4e58 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -179,6 +179,7 @@ cc_defaults {
"android.hardware.power.stats@1.0",
"android.hardware.power.stats-V1-ndk",
"android.hardware.thermal@1.0",
+ "android.hardware.thermal-V1-ndk",
"android.hardware.tv.input@1.0",
"android.hardware.tv.input-V1-ndk",
"android.hardware.vibrator-V2-cpp",
diff --git a/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp b/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp
index ed79352bba21..7e0bb68c6168 100644
--- a/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp
+++ b/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp
@@ -16,27 +16,28 @@
#define LOG_TAG "HardwarePropertiesManagerService-JNI"
-#include <nativehelper/JNIHelp.h>
-#include "jni.h"
-
-#include <math.h>
-#include <stdlib.h>
-
+#include <aidl/android/hardware/thermal/IThermal.h>
+#include <android/binder_manager.h>
#include <android/hardware/thermal/1.0/IThermal.h>
+#include <math.h>
+#include <nativehelper/JNIHelp.h>
#include <utils/Log.h>
#include <utils/String8.h>
#include "core_jni_helpers.h"
+#include "jni.h"
namespace android {
+using ::aidl::android::hardware::thermal::CoolingDevice;
+using ::aidl::android::hardware::thermal::IThermal;
+using ::aidl::android::hardware::thermal::Temperature;
+using ::aidl::android::hardware::thermal::TemperatureThreshold;
+using ::aidl::android::hardware::thermal::TemperatureType;
+using ::aidl::android::hardware::thermal::ThrottlingSeverity;
using android::hidl::base::V1_0::IBase;
using hardware::hidl_death_recipient;
using hardware::hidl_vec;
-using hardware::thermal::V1_0::CoolingDevice;
-using hardware::thermal::V1_0::CpuUsage;
-using hardware::thermal::V1_0::IThermal;
-using hardware::thermal::V1_0::Temperature;
using hardware::thermal::V1_0::ThermalStatus;
using hardware::thermal::V1_0::ThermalStatusCode;
template<typename T>
@@ -62,20 +63,28 @@ jfloat gUndefinedTemperature;
static void getThermalHalLocked();
static std::mutex gThermalHalMutex;
-static sp<IThermal> gThermalHal = nullptr;
-
-// struct ThermalHalDeathRecipient;
-struct ThermalHalDeathRecipient : virtual public hidl_death_recipient {
- // hidl_death_recipient interface
- virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override {
- std::lock_guard<std::mutex> lock(gThermalHalMutex);
- ALOGE("ThermalHAL just died");
- gThermalHal = nullptr;
- getThermalHalLocked();
- }
+static sp<hardware::thermal::V1_0::IThermal> gThermalHidlHal = nullptr;
+static std::shared_ptr<IThermal> gThermalAidlHal = nullptr;
+
+struct ThermalHidlHalDeathRecipient : virtual public hidl_death_recipient {
+ // hidl_death_recipient interface
+ virtual void serviceDied(uint64_t cookie, const wp<IBase> &who) override {
+ std::lock_guard<std::mutex> lock(gThermalHalMutex);
+ ALOGE("Thermal HAL just died");
+ gThermalHidlHal = nullptr;
+ getThermalHalLocked();
+ }
};
-sp<ThermalHalDeathRecipient> gThermalHalDeathRecipient = nullptr;
+static void onThermalAidlBinderDied(void *cookie) {
+ std::lock_guard<std::mutex> lock(gThermalHalMutex);
+ ALOGE("Thermal AIDL HAL just died");
+ gThermalAidlHal = nullptr;
+ getThermalHalLocked();
+}
+
+sp<ThermalHidlHalDeathRecipient> gThermalHidlHalDeathRecipient = nullptr;
+ndk::ScopedAIBinder_DeathRecipient gThermalAidlDeathRecipient;
// ----------------------------------------------------------------------------
@@ -85,27 +94,49 @@ float finalizeTemperature(float temperature) {
// The caller must be holding gThermalHalMutex.
static void getThermalHalLocked() {
- if (gThermalHal != nullptr) {
+ if (gThermalAidlHal || gThermalHidlHal) {
+ return;
+ }
+ const std::string thermalInstanceName = std::string(IThermal::descriptor) + "/default";
+ if (AServiceManager_isDeclared(thermalInstanceName.c_str())) {
+ auto binder = AServiceManager_waitForService(thermalInstanceName.c_str());
+ auto thermalAidlService = IThermal::fromBinder(ndk::SpAIBinder(binder));
+ if (thermalAidlService) {
+ gThermalAidlHal = thermalAidlService;
+ if (gThermalAidlDeathRecipient.get() == nullptr) {
+ gThermalAidlDeathRecipient = ndk::ScopedAIBinder_DeathRecipient(
+ AIBinder_DeathRecipient_new(onThermalAidlBinderDied));
+ }
+ auto linked = AIBinder_linkToDeath(thermalAidlService->asBinder().get(),
+ gThermalAidlDeathRecipient.get(), nullptr);
+ if (linked != STATUS_OK) {
+ ALOGW("Failed to link to death (AIDL): %d", linked);
+ gThermalAidlHal = nullptr;
+ }
+ } else {
+ ALOGE("Unable to get Thermal AIDL service");
+ }
return;
}
- gThermalHal = IThermal::getService();
+ ALOGI("Thermal AIDL service is not declared, trying HIDL");
+ gThermalHidlHal = hardware::thermal::V1_0::IThermal::getService();
- if (gThermalHal == nullptr) {
+ if (gThermalHidlHal == nullptr) {
ALOGE("Unable to get Thermal service.");
} else {
- if (gThermalHalDeathRecipient == nullptr) {
- gThermalHalDeathRecipient = new ThermalHalDeathRecipient();
+ if (gThermalHidlHalDeathRecipient == nullptr) {
+ gThermalHidlHalDeathRecipient = new ThermalHidlHalDeathRecipient();
}
- hardware::Return<bool> linked = gThermalHal->linkToDeath(
- gThermalHalDeathRecipient, 0x451F /* cookie */);
+ hardware::Return<bool> linked =
+ gThermalHidlHal->linkToDeath(gThermalHidlHalDeathRecipient, 0x451F /* cookie */);
if (!linked.isOk()) {
ALOGE("Transaction error in linking to ThermalHAL death: %s",
- linked.description().c_str());
- gThermalHal = nullptr;
+ linked.description().c_str());
+ gThermalHidlHal = nullptr;
} else if (!linked) {
ALOGW("Unable to link to ThermalHal death notifications");
- gThermalHal = nullptr;
+ gThermalHidlHal = nullptr;
} else {
ALOGD("Link to death notification successful");
}
@@ -117,17 +148,27 @@ static void nativeInit(JNIEnv* env, jobject obj) {
getThermalHalLocked();
}
-static jfloatArray nativeGetFanSpeeds(JNIEnv *env, jclass /* clazz */) {
- std::lock_guard<std::mutex> lock(gThermalHalMutex);
- getThermalHalLocked();
- if (gThermalHal == nullptr) {
- ALOGE("Couldn't get fan speeds because of HAL error.");
+static jfloatArray getFanSpeedsAidl(JNIEnv *env) {
+ std::vector<CoolingDevice> list;
+ auto status = gThermalAidlHal->getCoolingDevices(&list);
+ if (!status.isOk()) {
+ ALOGE("getFanSpeeds failed status: %s", status.getMessage());
return env->NewFloatArray(0);
}
+ float values[list.size()];
+ for (size_t i = 0; i < list.size(); ++i) {
+ values[i] = list[i].value;
+ }
+ jfloatArray fanSpeeds = env->NewFloatArray(list.size());
+ env->SetFloatArrayRegion(fanSpeeds, 0, list.size(), values);
+ return fanSpeeds;
+}
- hidl_vec<CoolingDevice> list;
- Return<void> ret = gThermalHal->getCoolingDevices(
- [&list](ThermalStatus status, hidl_vec<CoolingDevice> devices) {
+static jfloatArray getFanSpeedsHidl(JNIEnv *env) {
+ hidl_vec<hardware::thermal::V1_0::CoolingDevice> list;
+ Return<void> ret = gThermalHidlHal->getCoolingDevices(
+ [&list](ThermalStatus status,
+ hidl_vec<hardware::thermal::V1_0::CoolingDevice> devices) {
if (status.code == ThermalStatusCode::SUCCESS) {
list = std::move(devices);
} else {
@@ -137,9 +178,9 @@ static jfloatArray nativeGetFanSpeeds(JNIEnv *env, jclass /* clazz */) {
});
if (!ret.isOk()) {
- ALOGE("getCoolingDevices failed status: %s", ret.description().c_str());
+ ALOGE("getFanSpeeds failed status: %s", ret.description().c_str());
+ return env->NewFloatArray(0);
}
-
float values[list.size()];
for (size_t i = 0; i < list.size(); ++i) {
values[i] = list[i].currentValue;
@@ -149,17 +190,79 @@ static jfloatArray nativeGetFanSpeeds(JNIEnv *env, jclass /* clazz */) {
return fanSpeeds;
}
-static jfloatArray nativeGetDeviceTemperatures(JNIEnv *env, jclass /* clazz */, int type,
- int source) {
+static jfloatArray nativeGetFanSpeeds(JNIEnv *env, jclass /* clazz */) {
std::lock_guard<std::mutex> lock(gThermalHalMutex);
getThermalHalLocked();
- if (gThermalHal == nullptr) {
- ALOGE("Couldn't get device temperatures because of HAL error.");
+ if (!gThermalHidlHal && !gThermalAidlHal) {
+ ALOGE("Couldn't get fan speeds because of HAL error.");
return env->NewFloatArray(0);
}
- hidl_vec<Temperature> list;
- Return<void> ret = gThermalHal->getTemperatures(
- [&list](ThermalStatus status, hidl_vec<Temperature> temperatures) {
+ if (gThermalAidlHal) {
+ return getFanSpeedsAidl(env);
+ }
+ return getFanSpeedsHidl(env);
+}
+
+static jfloatArray getDeviceTemperaturesAidl(JNIEnv *env, int type, int source) {
+ jfloat *values;
+ size_t length = 0;
+ if (source == TEMPERATURE_CURRENT) {
+ std::vector<Temperature> list;
+ auto status =
+ gThermalAidlHal->getTemperaturesWithType(static_cast<TemperatureType>(type), &list);
+
+ if (!status.isOk()) {
+ ALOGE("getDeviceTemperatures failed status: %s", status.getMessage());
+ return env->NewFloatArray(0);
+ }
+ values = new jfloat[list.size()];
+ for (const auto &temp : list) {
+ if (static_cast<int>(temp.type) == type) {
+ values[length++] = finalizeTemperature(temp.value);
+ }
+ }
+ } else if (source == TEMPERATURE_THROTTLING_BELOW_VR_MIN) {
+ values = new jfloat[1];
+ values[length++] = gUndefinedTemperature;
+ } else {
+ std::vector<TemperatureThreshold> list;
+ auto status =
+ gThermalAidlHal->getTemperatureThresholdsWithType(static_cast<TemperatureType>(
+ type),
+ &list);
+
+ if (!status.isOk()) {
+ ALOGE("getDeviceTemperatures failed status: %s", status.getMessage());
+ return env->NewFloatArray(0);
+ }
+ values = new jfloat[list.size()];
+ for (auto &t : list) {
+ if (static_cast<int>(t.type) == type) {
+ switch (source) {
+ case TEMPERATURE_THROTTLING:
+ values[length++] =
+ finalizeTemperature(t.hotThrottlingThresholds[static_cast<int>(
+ ThrottlingSeverity::SEVERE)]);
+ break;
+ case TEMPERATURE_SHUTDOWN:
+ values[length++] =
+ finalizeTemperature(t.hotThrottlingThresholds[static_cast<int>(
+ ThrottlingSeverity::SHUTDOWN)]);
+ break;
+ }
+ }
+ }
+ }
+ jfloatArray deviceTemps = env->NewFloatArray(length);
+ env->SetFloatArrayRegion(deviceTemps, 0, length, values);
+ return deviceTemps;
+}
+
+static jfloatArray getDeviceTemperaturesHidl(JNIEnv *env, int type, int source) {
+ hidl_vec<hardware::thermal::V1_0::Temperature> list;
+ Return<void> ret = gThermalHidlHal->getTemperatures(
+ [&list](ThermalStatus status,
+ hidl_vec<hardware::thermal::V1_0::Temperature> temperatures) {
if (status.code == ThermalStatusCode::SUCCESS) {
list = std::move(temperatures);
} else {
@@ -170,9 +273,9 @@ static jfloatArray nativeGetDeviceTemperatures(JNIEnv *env, jclass /* clazz */,
if (!ret.isOk()) {
ALOGE("getDeviceTemperatures failed status: %s", ret.description().c_str());
+ return env->NewFloatArray(0);
}
-
- jfloat values[list.size()];
+ float values[list.size()];
size_t length = 0;
for (size_t i = 0; i < list.size(); ++i) {
if (static_cast<int>(list[i].type) == type) {
@@ -197,16 +300,34 @@ static jfloatArray nativeGetDeviceTemperatures(JNIEnv *env, jclass /* clazz */,
return deviceTemps;
}
+static jfloatArray nativeGetDeviceTemperatures(JNIEnv *env, jclass /* clazz */, int type,
+ int source) {
+ std::lock_guard<std::mutex> lock(gThermalHalMutex);
+ getThermalHalLocked();
+ if (!gThermalHidlHal && !gThermalAidlHal) {
+ ALOGE("Couldn't get device temperatures because of HAL error.");
+ return env->NewFloatArray(0);
+ }
+ if (gThermalAidlHal) {
+ return getDeviceTemperaturesAidl(env, type, source);
+ }
+ return getDeviceTemperaturesHidl(env, type, source);
+}
+
static jobjectArray nativeGetCpuUsages(JNIEnv *env, jclass /* clazz */) {
std::lock_guard<std::mutex> lock(gThermalHalMutex);
getThermalHalLocked();
- if (gThermalHal == nullptr || !gCpuUsageInfoClassInfo.initMethod) {
+ if (gThermalAidlHal) {
+ ALOGW("getCpuUsages is not supported");
+ return env->NewObjectArray(0, gCpuUsageInfoClassInfo.clazz, nullptr);
+ }
+ if (gThermalHidlHal == nullptr || !gCpuUsageInfoClassInfo.initMethod) {
ALOGE("Couldn't get CPU usages because of HAL error.");
return env->NewObjectArray(0, gCpuUsageInfoClassInfo.clazz, nullptr);
}
- hidl_vec<CpuUsage> list;
- Return<void> ret = gThermalHal->getCpuUsages(
- [&list](ThermalStatus status, hidl_vec<CpuUsage> cpuUsages) {
+ hidl_vec<hardware::thermal::V1_0::CpuUsage> list;
+ Return<void> ret = gThermalHidlHal->getCpuUsages(
+ [&list](ThermalStatus status, hidl_vec<hardware::thermal::V1_0::CpuUsage> cpuUsages) {
if (status.code == ThermalStatusCode::SUCCESS) {
list = std::move(cpuUsages);
} else {
@@ -217,6 +338,7 @@ static jobjectArray nativeGetCpuUsages(JNIEnv *env, jclass /* clazz */) {
if (!ret.isOk()) {
ALOGE("getCpuUsages failed status: %s", ret.description().c_str());
+ return env->NewObjectArray(0, gCpuUsageInfoClassInfo.clazz, nullptr);
}
jobjectArray cpuUsages = env->NewObjectArray(list.size(), gCpuUsageInfoClassInfo.clazz,
diff --git a/services/core/jni/com_android_server_sensor_SensorService.cpp b/services/core/jni/com_android_server_sensor_SensorService.cpp
index 356e9a95e311..a916b64fc0bd 100644
--- a/services/core/jni/com_android_server_sensor_SensorService.cpp
+++ b/services/core/jni/com_android_server_sensor_SensorService.cpp
@@ -17,10 +17,13 @@
#define LOG_TAG "NativeSensorService"
#include <android-base/properties.h>
+#include <android_os_NativeHandle.h>
#include <android_runtime/AndroidRuntime.h>
#include <core_jni_helpers.h>
+#include <cutils/native_handle.h>
#include <cutils/properties.h>
#include <jni.h>
+#include <nativehelper/JNIPlatformHelp.h>
#include <sensorservice/SensorService.h>
#include <string.h>
#include <utils/Log.h>
@@ -28,6 +31,8 @@
#include <mutex>
+#include "android_util_Binder.h"
+
#define PROXIMITY_ACTIVE_CLASS \
"com/android/server/sensors/SensorManagerInternal$ProximityActiveListener"
@@ -38,7 +43,10 @@ namespace android {
static JavaVM* sJvm = nullptr;
static jmethodID sMethodIdOnProximityActive;
-static jmethodID sMethodIdOnConfigurationChanged;
+static jmethodID sMethodIdRuntimeSensorOnConfigurationChanged;
+static jmethodID sMethodIdRuntimeSensorOnDirectChannelCreated;
+static jmethodID sMethodIdRuntimeSensorOnDirectChannelDestroyed;
+static jmethodID sMethodIdRuntimeSensorOnDirectChannelConfigured;
class NativeSensorService {
public:
@@ -47,7 +55,7 @@ public:
void registerProximityActiveListener();
void unregisterProximityActiveListener();
jint registerRuntimeSensor(JNIEnv* env, jint deviceId, jint type, jstring name, jstring vendor,
- jobject callback);
+ jint flags, jobject callback);
void unregisterRuntimeSensor(jint handle);
jboolean sendRuntimeSensorEvent(JNIEnv* env, jint handle, jint type, jlong timestamp,
jfloatArray values);
@@ -74,6 +82,9 @@ private:
status_t onConfigurationChanged(int32_t handle, bool enabled, int64_t samplingPeriodNs,
int64_t batchReportLatencyNs) override;
+ int onDirectChannelCreated(int fd) override;
+ void onDirectChannelDestroyed(int channelHandle) override;
+ int onDirectChannelConfigured(int channelHandle, int sensorHandle, int rateLevel) override;
private:
jobject mCallback;
@@ -108,7 +119,7 @@ void NativeSensorService::unregisterProximityActiveListener() {
}
jint NativeSensorService::registerRuntimeSensor(JNIEnv* env, jint deviceId, jint type, jstring name,
- jstring vendor, jobject callback) {
+ jstring vendor, jint flags, jobject callback) {
if (mService == nullptr) {
ALOGD("Dropping registerRuntimeSensor, sensor service not available.");
return -1;
@@ -119,6 +130,11 @@ jint NativeSensorService::registerRuntimeSensor(JNIEnv* env, jint deviceId, jint
.vendor = env->GetStringUTFChars(vendor, 0),
.version = sizeof(sensor_t),
.type = type,
+#ifdef __LP64__
+ .flags = static_cast<uint64_t>(flags),
+#else
+ .flags = static_cast<uint32_t>(flags),
+#endif
};
sp<RuntimeSensorCallbackDelegate> callbackDelegate(
@@ -234,12 +250,39 @@ NativeSensorService::RuntimeSensorCallbackDelegate::~RuntimeSensorCallbackDelega
status_t NativeSensorService::RuntimeSensorCallbackDelegate::onConfigurationChanged(
int32_t handle, bool enabled, int64_t samplingPeriodNs, int64_t batchReportLatencyNs) {
auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
- return jniEnv->CallIntMethod(mCallback, sMethodIdOnConfigurationChanged,
+ return jniEnv->CallIntMethod(mCallback, sMethodIdRuntimeSensorOnConfigurationChanged,
static_cast<jint>(handle), static_cast<jboolean>(enabled),
static_cast<jint>(ns2us(samplingPeriodNs)),
static_cast<jint>(ns2us(batchReportLatencyNs)));
}
+int NativeSensorService::RuntimeSensorCallbackDelegate::onDirectChannelCreated(int fd) {
+ if (fd <= 0) {
+ return 0;
+ }
+ auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
+ jobject jfd = jniCreateFileDescriptor(jniEnv, fd);
+ jobject parcelFileDescriptor = newParcelFileDescriptor(jniEnv, jfd);
+ return jniEnv->CallIntMethod(mCallback, sMethodIdRuntimeSensorOnDirectChannelCreated,
+ parcelFileDescriptor);
+}
+
+void NativeSensorService::RuntimeSensorCallbackDelegate::onDirectChannelDestroyed(
+ int channelHandle) {
+ auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
+ return jniEnv->CallVoidMethod(mCallback, sMethodIdRuntimeSensorOnDirectChannelDestroyed,
+ static_cast<jint>(channelHandle));
+}
+
+int NativeSensorService::RuntimeSensorCallbackDelegate::onDirectChannelConfigured(int channelHandle,
+ int sensorHandle,
+ int rateLevel) {
+ auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
+ return jniEnv->CallIntMethod(mCallback, sMethodIdRuntimeSensorOnDirectChannelConfigured,
+ static_cast<jint>(channelHandle), static_cast<jint>(sensorHandle),
+ static_cast<jint>(rateLevel));
+}
+
static jlong startSensorServiceNative(JNIEnv* env, jclass, jobject listener) {
NativeSensorService* service = new NativeSensorService(env, listener);
return reinterpret_cast<jlong>(service);
@@ -256,9 +299,10 @@ static void unregisterProximityActiveListenerNative(JNIEnv* env, jclass, jlong p
}
static jint registerRuntimeSensorNative(JNIEnv* env, jclass, jlong ptr, jint deviceId, jint type,
- jstring name, jstring vendor, jobject callback) {
+ jstring name, jstring vendor, jint flags,
+ jobject callback) {
auto* service = reinterpret_cast<NativeSensorService*>(ptr);
- return service->registerRuntimeSensor(env, deviceId, type, name, vendor, callback);
+ return service->registerRuntimeSensor(env, deviceId, type, name, vendor, flags, callback);
}
static void unregisterRuntimeSensorNative(JNIEnv* env, jclass, jlong ptr, jint handle) {
@@ -280,7 +324,7 @@ static const JNINativeMethod methods[] = {
{"unregisterProximityActiveListenerNative", "(J)V",
reinterpret_cast<void*>(unregisterProximityActiveListenerNative)},
{"registerRuntimeSensorNative",
- "(JIILjava/lang/String;Ljava/lang/String;L" RUNTIME_SENSOR_CALLBACK_CLASS ";)I",
+ "(JIILjava/lang/String;Ljava/lang/String;IL" RUNTIME_SENSOR_CALLBACK_CLASS ";)I",
reinterpret_cast<void*>(registerRuntimeSensorNative)},
{"unregisterRuntimeSensorNative", "(JI)V",
reinterpret_cast<void*>(unregisterRuntimeSensorNative)},
@@ -293,8 +337,17 @@ int register_android_server_sensor_SensorService(JavaVM* vm, JNIEnv* env) {
jclass listenerClass = FindClassOrDie(env, PROXIMITY_ACTIVE_CLASS);
sMethodIdOnProximityActive = GetMethodIDOrDie(env, listenerClass, "onProximityActive", "(Z)V");
jclass runtimeSensorCallbackClass = FindClassOrDie(env, RUNTIME_SENSOR_CALLBACK_CLASS);
- sMethodIdOnConfigurationChanged =
+ sMethodIdRuntimeSensorOnConfigurationChanged =
GetMethodIDOrDie(env, runtimeSensorCallbackClass, "onConfigurationChanged", "(IZII)I");
+ sMethodIdRuntimeSensorOnDirectChannelCreated =
+ GetMethodIDOrDie(env, runtimeSensorCallbackClass, "onDirectChannelCreated",
+ "(Landroid/os/ParcelFileDescriptor;)I");
+ sMethodIdRuntimeSensorOnDirectChannelDestroyed =
+ GetMethodIDOrDie(env, runtimeSensorCallbackClass, "onDirectChannelDestroyed", "(I)V");
+ sMethodIdRuntimeSensorOnDirectChannelConfigured =
+ GetMethodIDOrDie(env, runtimeSensorCallbackClass, "onDirectChannelConfigured",
+ "(III)I");
+
return jniRegisterNativeMethods(env, "com/android/server/sensors/SensorService", methods,
NELEM(methods));
}
diff --git a/services/core/xsd/display-device-config/display-device-config.xsd b/services/core/xsd/display-device-config/display-device-config.xsd
index 9260d2b4194a..981844cf9338 100644
--- a/services/core/xsd/display-device-config/display-device-config.xsd
+++ b/services/core/xsd/display-device-config/display-device-config.xsd
@@ -26,6 +26,10 @@
<xs:element name="displayConfiguration">
<xs:complexType>
<xs:sequence>
+ <xs:element type ="xs:string" name="name">
+ <xs:annotation name="nullable"/>
+ <xs:annotation name="final"/>
+ </xs:element>
<xs:element type="densityMapping" name="densityMapping" minOccurs="0" maxOccurs="1">
<xs:annotation name="nullable"/>
<xs:annotation name="final"/>
@@ -211,6 +215,32 @@
<xs:element type="brightnessThrottlingMap" name="brightnessThrottlingMap" maxOccurs="unbounded">
<xs:annotation name="final"/>
</xs:element>
+ <xs:element type="refreshRateThrottlingMap" name="refreshRateThrottlingMap" maxOccurs="unbounded">
+ <xs:annotation name="final"/>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="refreshRateThrottlingMap">
+ <xs:attribute name="id" type="xs:string" />
+ <xs:sequence>
+ <xs:element name="refreshRateThrottlingPoint" type="refreshRateThrottlingPoint" maxOccurs="unbounded">
+ <xs:annotation name="nonnull"/>
+ <xs:annotation name="final"/>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="refreshRateThrottlingPoint">
+ <xs:sequence>
+ <xs:element type="thermalStatus" name="thermalStatus">
+ <xs:annotation name="nonnull"/>
+ <xs:annotation name="final"/>
+ </xs:element>
+ <xs:element type="refreshRateRange" name="refreshRateRange">
+ <xs:annotation name="nonnull"/>
+ <xs:annotation name="final"/>
+ </xs:element>
</xs:sequence>
</xs:complexType>
diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt
index e81c27d94c88..8cb483770c85 100644
--- a/services/core/xsd/display-device-config/schema/current.txt
+++ b/services/core/xsd/display-device-config/schema/current.txt
@@ -89,6 +89,7 @@ package com.android.server.display.config {
method public final com.android.server.display.config.Thresholds getDisplayBrightnessChangeThresholdsIdle();
method public com.android.server.display.config.HighBrightnessMode getHighBrightnessMode();
method public final com.android.server.display.config.SensorDetails getLightSensor();
+ method @Nullable public final String getName();
method public final com.android.server.display.config.SensorDetails getProxSensor();
method public com.android.server.display.config.DisplayQuirks getQuirks();
method public com.android.server.display.config.RefreshRateConfigs getRefreshRate();
@@ -114,6 +115,7 @@ package com.android.server.display.config {
method public final void setDisplayBrightnessChangeThresholdsIdle(com.android.server.display.config.Thresholds);
method public void setHighBrightnessMode(com.android.server.display.config.HighBrightnessMode);
method public final void setLightSensor(com.android.server.display.config.SensorDetails);
+ method public final void setName(@Nullable String);
method public final void setProxSensor(com.android.server.display.config.SensorDetails);
method public void setQuirks(com.android.server.display.config.DisplayQuirks);
method public void setRefreshRate(com.android.server.display.config.RefreshRateConfigs);
@@ -214,6 +216,21 @@ package com.android.server.display.config {
method public final void setMinimum(java.math.BigInteger);
}
+ public class RefreshRateThrottlingMap {
+ ctor public RefreshRateThrottlingMap();
+ method public String getId();
+ method @NonNull public final java.util.List<com.android.server.display.config.RefreshRateThrottlingPoint> getRefreshRateThrottlingPoint();
+ method public void setId(String);
+ }
+
+ public class RefreshRateThrottlingPoint {
+ ctor public RefreshRateThrottlingPoint();
+ method @NonNull public final com.android.server.display.config.RefreshRateRange getRefreshRateRange();
+ method @NonNull public final com.android.server.display.config.ThermalStatus getThermalStatus();
+ method public final void setRefreshRateRange(@NonNull com.android.server.display.config.RefreshRateRange);
+ method public final void setThermalStatus(@NonNull com.android.server.display.config.ThermalStatus);
+ }
+
public class RefreshRateZone {
ctor public RefreshRateZone();
method public String getId();
@@ -264,6 +281,7 @@ package com.android.server.display.config {
public class ThermalThrottling {
ctor public ThermalThrottling();
method public final java.util.List<com.android.server.display.config.BrightnessThrottlingMap> getBrightnessThrottlingMap();
+ method public final java.util.List<com.android.server.display.config.RefreshRateThrottlingMap> getRefreshRateThrottlingMap();
}
public class ThresholdPoint {
diff --git a/services/core/xsd/display-layout-config/display-layout-config.xsd b/services/core/xsd/display-layout-config/display-layout-config.xsd
index d4556d710429..ce022e9cb78d 100644
--- a/services/core/xsd/display-layout-config/display-layout-config.xsd
+++ b/services/core/xsd/display-layout-config/display-layout-config.xsd
@@ -52,6 +52,7 @@
<xs:element name="address" type="xs:nonNegativeInteger"/>
<xs:element name="position" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="brightnessThrottlingMapId" type="xs:string" minOccurs="0" maxOccurs="1" />
+ <xs:element name="refreshRateThermalThrottlingMapId" type="xs:string" minOccurs="0" />
</xs:sequence>
<xs:attribute name="enabled" type="xs:boolean" use="optional" />
<xs:attribute name="defaultDisplay" type="xs:boolean" use="optional" />
diff --git a/services/core/xsd/display-layout-config/schema/current.txt b/services/core/xsd/display-layout-config/schema/current.txt
index 52133ab76086..42a800db1474 100644
--- a/services/core/xsd/display-layout-config/schema/current.txt
+++ b/services/core/xsd/display-layout-config/schema/current.txt
@@ -7,6 +7,7 @@ package com.android.server.display.config.layout {
method public String getBrightnessThrottlingMapId();
method public String getDisplayGroup();
method public String getPosition();
+ method public String getRefreshRateThermalThrottlingMapId();
method public String getRefreshRateZoneId();
method public boolean isDefaultDisplay();
method public boolean isEnabled();
@@ -16,6 +17,7 @@ package com.android.server.display.config.layout {
method public void setDisplayGroup(String);
method public void setEnabled(boolean);
method public void setPosition(String);
+ method public void setRefreshRateThermalThrottlingMapId(String);
method public void setRefreshRateZoneId(String);
}
diff --git a/services/credentials/java/com/android/server/credentials/ClearRequestSession.java b/services/credentials/java/com/android/server/credentials/ClearRequestSession.java
index f8b1e6fc927c..6bf18c27ee05 100644
--- a/services/credentials/java/com/android/server/credentials/ClearRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/ClearRequestSession.java
@@ -29,6 +29,9 @@ import android.service.credentials.CallingAppInfo;
import android.service.credentials.CredentialProviderInfo;
import android.util.Log;
+import com.android.server.credentials.metrics.ApiName;
+import com.android.server.credentials.metrics.ApiStatus;
+
import java.util.ArrayList;
/**
@@ -119,18 +122,21 @@ public final class ClearRequestSession extends RequestSession<ClearCredentialSta
// TODO: Differentiate btw cancelled and false
mChosenProviderMetric.setChosenProviderStatus(
MetricUtilities.METRICS_PROVIDER_STATUS_FINAL_SUCCESS);
- logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ true);
+ logApiCall(ApiName.CLEAR_CREDENTIAL, /* apiStatus */
+ ApiStatus.METRICS_API_STATUS_CLIENT_CANCELED);
finishSession(/*propagateCancellation=*/true);
return;
}
try {
mClientCallback.onSuccess();
- logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ true);
+ logApiCall(ApiName.CLEAR_CREDENTIAL, /* apiStatus */
+ ApiStatus.METRICS_API_STATUS_SUCCESS);
} catch (RemoteException e) {
mChosenProviderMetric.setChosenProviderStatus(
MetricUtilities.METRICS_PROVIDER_STATUS_FINAL_FAILURE);
Log.i(TAG, "Issue while propagating the response to the client");
- logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ false);
+ logApiCall(ApiName.CLEAR_CREDENTIAL, /* apiStatus */
+ ApiStatus.METRICS_API_STATUS_FAILURE);
}
finishSession(/*propagateCancellation=*/false);
}
@@ -139,7 +145,8 @@ public final class ClearRequestSession extends RequestSession<ClearCredentialSta
Log.i(TAG, "respondToClientWithErrorAndFinish");
if (isSessionCancelled()) {
// TODO: Differentiate btw cancelled and false
- logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ true);
+ logApiCall(ApiName.CLEAR_CREDENTIAL, /* apiStatus */
+ ApiStatus.METRICS_API_STATUS_CLIENT_CANCELED);
finishSession(/*propagateCancellation=*/true);
return;
}
@@ -148,7 +155,8 @@ public final class ClearRequestSession extends RequestSession<ClearCredentialSta
} catch (RemoteException e) {
e.printStackTrace();
}
- logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ false);
+ logApiCall(ApiName.CLEAR_CREDENTIAL, /* apiStatus */
+ ApiStatus.METRICS_API_STATUS_FAILURE);
finishSession(/*propagateCancellation=*/false);
}
diff --git a/services/credentials/java/com/android/server/credentials/CreateRequestSession.java b/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
index 4dd0c84d64f6..656e44c4bff2 100644
--- a/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
@@ -36,6 +36,9 @@ import android.service.credentials.CallingAppInfo;
import android.service.credentials.CredentialProviderInfo;
import android.util.Log;
+import com.android.server.credentials.metrics.ApiName;
+import com.android.server.credentials.metrics.ApiStatus;
+
import java.util.ArrayList;
/**
@@ -141,16 +144,19 @@ public final class CreateRequestSession extends RequestSession<CreateCredentialR
}
if (isSessionCancelled()) {
// TODO: Differentiate btw cancelled and false
- logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ true);
+ logApiCall(ApiName.CREATE_CREDENTIAL, /* apiStatus */
+ ApiStatus.METRICS_API_STATUS_CLIENT_CANCELED);
finishSession(/*propagateCancellation=*/true);
return;
}
try {
mClientCallback.onResponse(response);
- logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ true);
+ logApiCall(ApiName.CREATE_CREDENTIAL, /* apiStatus */
+ ApiStatus.METRICS_API_STATUS_SUCCESS);
} catch (RemoteException e) {
Log.i(TAG, "Issue while responding to client: " + e.getMessage());
- logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ false);
+ logApiCall(ApiName.CREATE_CREDENTIAL, /* apiStatus */
+ ApiStatus.METRICS_API_STATUS_FAILURE);
}
finishSession(/*propagateCancellation=*/false);
}
@@ -163,7 +169,8 @@ public final class CreateRequestSession extends RequestSession<CreateCredentialR
}
if (isSessionCancelled()) {
// TODO: Differentiate btw cancelled and false
- logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ true);
+ logApiCall(ApiName.CREATE_CREDENTIAL, /* apiStatus */
+ ApiStatus.METRICS_API_STATUS_CLIENT_CANCELED);
finishSession(/*propagateCancellation=*/true);
return;
}
@@ -172,10 +179,20 @@ public final class CreateRequestSession extends RequestSession<CreateCredentialR
} catch (RemoteException e) {
Log.i(TAG, "Issue while responding to client: " + e.getMessage());
}
- logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ false);
+ logFailureOrUserCancel(errorType);
finishSession(/*propagateCancellation=*/false);
}
+ private void logFailureOrUserCancel(String errorType) {
+ if (CreateCredentialException.TYPE_USER_CANCELED.equals(errorType)) {
+ logApiCall(ApiName.CREATE_CREDENTIAL,
+ /* apiStatus */ ApiStatus.METRICS_API_STATUS_USER_CANCELED);
+ } else {
+ logApiCall(ApiName.CREATE_CREDENTIAL,
+ /* apiStatus */ ApiStatus.METRICS_API_STATUS_FAILURE);
+ }
+ }
+
@Override
public void onProviderStatusChanged(ProviderSession.Status status,
ComponentName componentName) {
diff --git a/services/credentials/java/com/android/server/credentials/CredentialDescriptionRegistry.java b/services/credentials/java/com/android/server/credentials/CredentialDescriptionRegistry.java
index 3d504efd1797..d768d234cd20 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialDescriptionRegistry.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialDescriptionRegistry.java
@@ -23,6 +23,8 @@ import android.service.credentials.CredentialEntry;
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.util.HashMap;
import java.util.HashSet;
@@ -49,11 +51,14 @@ public final class CredentialDescriptionRegistry {
/** Represents the results of a given query into the registry. */
public static final class FilterResult {
final String mPackageName;
+ final String mFlattenedRequest;
final List<CredentialEntry> mCredentialEntries;
private FilterResult(String packageName,
+ String flattenedRequest,
List<CredentialEntry> credentialEntries) {
mPackageName = packageName;
+ mFlattenedRequest = flattenedRequest;
mCredentialEntries = credentialEntries;
}
}
@@ -87,6 +92,18 @@ public final class CredentialDescriptionRegistry {
}
}
+ /** Clears an existing session for a given user identifier. */
+ @GuardedBy("sLock")
+ @VisibleForTesting
+ public static void clearAllSessions() {
+ sLock.lock();
+ try {
+ sCredentialDescriptionSessionPerUser.clear();
+ } finally {
+ sLock.unlock();
+ }
+ }
+
private Map<String, Set<CredentialDescription>> mCredentialDescriptions;
private int mTotalDescriptionCount;
@@ -133,12 +150,16 @@ public final class CredentialDescriptionRegistry {
/** Returns package names and entries of a CredentialProviders that can satisfy a given
* {@link CredentialDescription}. */
public Set<FilterResult> getFilteredResultForProvider(String packageName,
- List<String> flatRequestStrings) {
+ String flatRequestStrings) {
Set<FilterResult> result = new HashSet<>();
+ if (!mCredentialDescriptions.containsKey(packageName)) {
+ return result;
+ }
Set<CredentialDescription> currentSet = mCredentialDescriptions.get(packageName);
for (CredentialDescription containedDescription: currentSet) {
- if (flatRequestStrings.contains(containedDescription.getFlattenedRequestString())) {
- result.add(new FilterResult(packageName, containedDescription
+ if (flatRequestStrings.equals(containedDescription.getFlattenedRequestString())) {
+ result.add(new FilterResult(packageName,
+ containedDescription.getFlattenedRequestString(), containedDescription
.getCredentialEntries()));
}
}
@@ -147,13 +168,15 @@ public final class CredentialDescriptionRegistry {
/** Returns package names of CredentialProviders that can satisfy a given
* {@link CredentialDescription}. */
- public Set<String> getMatchingProviders(Set<String> flatRequestString) {
- Set<String> result = new HashSet<>();
+ public Set<FilterResult> getMatchingProviders(Set<String> flatRequestString) {
+ Set<FilterResult> result = new HashSet<>();
for (String packageName: mCredentialDescriptions.keySet()) {
Set<CredentialDescription> currentSet = mCredentialDescriptions.get(packageName);
for (CredentialDescription containedDescription : currentSet) {
if (flatRequestString.contains(containedDescription.getFlattenedRequestString())) {
- result.add(packageName);
+ result.add(new FilterResult(packageName,
+ containedDescription.getFlattenedRequestString(), containedDescription
+ .getCredentialEntries()));
}
}
}
diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
index cce12a252e78..41ae9118d965 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
@@ -17,6 +17,7 @@
package com.android.server.credentials;
import static android.Manifest.permission.CREDENTIAL_MANAGER_SET_ORIGIN;
+import static android.Manifest.permission.LAUNCH_CREDENTIAL_SELECTOR;
import static android.content.Context.CREDENTIAL_SERVICE;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -58,14 +59,18 @@ import android.service.credentials.CallingAppInfo;
import android.service.credentials.CredentialProviderInfo;
import android.text.TextUtils;
import android.util.Log;
+import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
+import com.android.server.credentials.metrics.ApiName;
+import com.android.server.credentials.metrics.ApiStatus;
import com.android.server.infra.AbstractMasterSystemService;
import com.android.server.infra.SecureSettingsServiceNameResolver;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
@@ -81,7 +86,7 @@ import java.util.stream.Collectors;
*/
public final class CredentialManagerService
extends AbstractMasterSystemService<
- CredentialManagerService, CredentialManagerServiceImpl> {
+ CredentialManagerService, CredentialManagerServiceImpl> {
private static final String TAG = "CredManSysService";
private static final String DEVICE_CONFIG_ENABLE_CREDENTIAL_DESC_API =
@@ -264,7 +269,8 @@ public final class CredentialManagerService
final long origId = Binder.clearCallingIdentity();
try {
return DeviceConfig.getBoolean(
- DeviceConfig.NAMESPACE_CREDENTIAL, DEVICE_CONFIG_ENABLE_CREDENTIAL_DESC_API, false);
+ DeviceConfig.NAMESPACE_CREDENTIAL, DEVICE_CONFIG_ENABLE_CREDENTIAL_DESC_API,
+ false);
} finally {
Binder.restoreCallingIdentity(origId);
}
@@ -274,24 +280,25 @@ public final class CredentialManagerService
// to be guarded by 'service.mLock', which is the same as mLock.
private List<ProviderSession> initiateProviderSessionsWithActiveContainers(
GetRequestSession session,
- List<String> requestOptions,
- Set<String> activeCredentialContainers) {
+ Set<Pair<CredentialOption, CredentialDescriptionRegistry.FilterResult>>
+ activeCredentialContainers) {
List<ProviderSession> providerSessions = new ArrayList<>();
- // Invoke all services of a user to initiate a provider session
- for (String packageName : activeCredentialContainers) {
+ for (Pair<CredentialOption, CredentialDescriptionRegistry.FilterResult> result :
+ activeCredentialContainers) {
providerSessions.add(
ProviderRegistryGetSession.createNewSession(
mContext,
UserHandle.getCallingUserId(),
session,
- packageName,
- requestOptions));
+ result.second.mPackageName,
+ result.first));
}
return providerSessions;
}
@NonNull
- private Set<String> getFilteredResultFromRegistry(List<CredentialOption> options) {
+ private Set<Pair<CredentialOption, CredentialDescriptionRegistry.FilterResult>>
+ getFilteredResultFromRegistry(List<CredentialOption> options) {
// Session for active/provisioned credential descriptions;
CredentialDescriptionRegistry registry =
CredentialDescriptionRegistry.forUser(UserHandle.getCallingUserId());
@@ -307,7 +314,22 @@ public final class CredentialManagerService
.collect(Collectors.toSet());
// All requested credential descriptions based on the given request.
- return registry.getMatchingProviders(requestedCredentialDescriptions);
+ Set<CredentialDescriptionRegistry.FilterResult> filterResults =
+ registry.getMatchingProviders(requestedCredentialDescriptions);
+
+ Set<Pair<CredentialOption, CredentialDescriptionRegistry.FilterResult>> result =
+ new HashSet<>();
+
+ for (CredentialDescriptionRegistry.FilterResult filterResult : filterResults) {
+ for (CredentialOption credentialOption : options) {
+ if (filterResult.mFlattenedRequest.equals(credentialOption
+ .getCredentialRetrievalData()
+ .getString(CredentialOption.FLATTENED_REQUEST))) {
+ result.add(new Pair<>(credentialOption, filterResult));
+ }
+ }
+ }
+ return result;
}
@SuppressWarnings("GuardedBy") // ErrorProne requires initiateProviderSessionForRequestLocked
@@ -342,21 +364,22 @@ public final class CredentialManagerService
int userId,
@Nullable String origin) {
final PackageInfo packageInfo;
- String actualPackageName = origin == null ? realPackageName : origin;
+ CallingAppInfo callingAppInfo;
try {
packageInfo =
- getContext()
- .getPackageManager()
- .getPackageInfoAsUser(
- actualPackageName,
- PackageManager.PackageInfoFlags.of(
- PackageManager.GET_SIGNING_CERTIFICATES),
- userId);
+ getContext()
+ .getPackageManager()
+ .getPackageInfoAsUser(
+ realPackageName,
+ PackageManager.PackageInfoFlags.of(
+ PackageManager.GET_SIGNING_CERTIFICATES),
+ userId);
+ callingAppInfo = new CallingAppInfo(realPackageName, packageInfo.signingInfo, origin);
} catch (PackageManager.NameNotFoundException e) {
Log.i(TAG, "Issue while retrieving signatureInfo : " + e.getMessage());
- return new CallingAppInfo(actualPackageName, null);
+ callingAppInfo = new CallingAppInfo(realPackageName, null, origin);
}
- return new CallingAppInfo(actualPackageName, packageInfo.signingInfo);
+ return callingAppInfo;
}
final class CredentialManagerServiceStub extends ICredentialManager.Stub {
@@ -368,9 +391,15 @@ public final class CredentialManagerService
Log.i(TAG, "starting executeGetCredential with callingPackage: " + callingPackage);
ICancellationSignal cancelTransport = CancellationSignal.createTransport();
+ if (request.getOrigin() != null) {
+ // Check privileged permissions
+ mContext.enforceCallingPermission(CREDENTIAL_MANAGER_SET_ORIGIN, null);
+ }
+
final int userId = UserHandle.getCallingUserId();
final int callingUid = Binder.getCallingUid();
enforceCallingPackage(callingPackage, callingUid);
+
// New request session, scoped for this request only.
final GetRequestSession session =
new GetRequestSession(
@@ -379,97 +408,57 @@ public final class CredentialManagerService
callingUid,
callback,
request,
- constructCallingAppInfo(callingPackage, userId, null),
+ constructCallingAppInfo(callingPackage, userId, request.getOrigin()),
CancellationSignal.fromTransport(cancelTransport));
processGetCredential(request, callback, session);
return cancelTransport;
}
- public ICancellationSignal executeGetCredentialWithOrigin(
- GetCredentialRequest request,
- IGetCredentialCallback callback,
- final String callingPackage,
- final String origin) {
- Log.i(TAG, "starting executeGetCredential with callingPackage: " + callingPackage);
- ICancellationSignal cancelTransport = CancellationSignal.createTransport();
-
- // Check privileged permissions
- mContext.enforceCallingPermission(CREDENTIAL_MANAGER_SET_ORIGIN, null);
-
- final int userId = UserHandle.getCallingUserId();
- final int callingUid = Binder.getCallingUid();
- enforceCallingPackage(callingPackage, callingUid);
-
- // New request session, scoped for this request only.
- final GetRequestSession session =
- new GetRequestSession(
- getContext(),
- userId,
- callingUid,
- callback,
- request,
- constructCallingAppInfo(callingPackage, userId, origin),
- CancellationSignal.fromTransport(cancelTransport));
-
- processGetCredential(request, callback, session);
- return cancelTransport;
- }
-
private void processGetCredential(
GetCredentialRequest request,
IGetCredentialCallback callback,
GetRequestSession session) {
List<ProviderSession> providerSessions;
- // TODO(b/268143699): temporarily disable the flag due to bug.
- if (false) {
+ if (isCredentialDescriptionApiEnabled()) {
List<CredentialOption> optionsThatRequireActiveCredentials =
request.getCredentialOptions().stream()
- .filter(
- getCredentialOption ->
- !TextUtils.isEmpty(
- getCredentialOption
- .getCredentialRetrievalData()
- .getString(
- CredentialOption
- .FLATTENED_REQUEST,
- null)))
- .toList();
+ .filter(
+ getCredentialOption ->
+ !TextUtils.isEmpty(
+ getCredentialOption
+ .getCredentialRetrievalData()
+ .getString(
+ CredentialOption
+ .FLATTENED_REQUEST,
+ null)))
+ .toList();
List<CredentialOption> optionsThatDoNotRequireActiveCredentials =
request.getCredentialOptions().stream()
- .filter(
- getCredentialOption ->
- TextUtils.isEmpty(
- getCredentialOption
- .getCredentialRetrievalData()
- .getString(
- CredentialOption
- .FLATTENED_REQUEST,
- null)))
- .toList();
+ .filter(
+ getCredentialOption ->
+ TextUtils.isEmpty(
+ getCredentialOption
+ .getCredentialRetrievalData()
+ .getString(
+ CredentialOption
+ .FLATTENED_REQUEST,
+ null)))
+ .toList();
List<ProviderSession> sessionsWithoutRemoteService =
initiateProviderSessionsWithActiveContainers(
- session,
- optionsThatRequireActiveCredentials.stream()
- .map(
- getCredentialOption ->
- getCredentialOption
- .getCredentialRetrievalData()
- .getString(
- CredentialOption
- .FLATTENED_REQUEST))
- .collect(Collectors.toList()),
- getFilteredResultFromRegistry(optionsThatRequireActiveCredentials));
+ session,
+ getFilteredResultFromRegistry(optionsThatRequireActiveCredentials));
List<ProviderSession> sessionsWithRemoteService =
initiateProviderSessions(
- session,
- optionsThatDoNotRequireActiveCredentials.stream()
- .map(CredentialOption::getType)
- .collect(Collectors.toList()));
+ session,
+ optionsThatDoNotRequireActiveCredentials.stream()
+ .map(CredentialOption::getType)
+ .collect(Collectors.toList()));
Set<ProviderSession> all = new LinkedHashSet<>();
all.addAll(sessionsWithRemoteService);
@@ -479,11 +468,11 @@ public final class CredentialManagerService
} else {
// Initiate all provider sessions
providerSessions =
- initiateProviderSessions(
- session,
- request.getCredentialOptions().stream()
- .map(CredentialOption::getType)
- .collect(Collectors.toList()));
+ initiateProviderSessions(
+ session,
+ request.getCredentialOptions().stream()
+ .map(CredentialOption::getType)
+ .collect(Collectors.toList()));
}
if (providerSessions.isEmpty()) {
@@ -495,8 +484,8 @@ public final class CredentialManagerService
Log.i(
TAG,
"Issue invoking onError on IGetCredentialCallback "
- + "callback: "
- + e.getMessage());
+ + "callback: "
+ + e.getMessage());
}
}
providerSessions.forEach(ProviderSession::invokeSession);
@@ -511,6 +500,11 @@ public final class CredentialManagerService
+ callingPackage);
ICancellationSignal cancelTransport = CancellationSignal.createTransport();
+ if (request.getOrigin() != null) {
+ // Check privileged permissions
+ mContext.enforceCallingPermission(CREDENTIAL_MANAGER_SET_ORIGIN, null);
+ }
+
final int userId = UserHandle.getCallingUserId();
final int callingUid = Binder.getCallingUid();
enforceCallingPackage(callingPackage, callingUid);
@@ -523,43 +517,13 @@ public final class CredentialManagerService
callingUid,
request,
callback,
- constructCallingAppInfo(callingPackage, userId, null),
+ constructCallingAppInfo(callingPackage, userId, request.getOrigin()),
CancellationSignal.fromTransport(cancelTransport));
processCreateCredential(request, callback, session);
return cancelTransport;
}
- public ICancellationSignal executeCreateCredentialWithOrigin(
- CreateCredentialRequest request,
- ICreateCredentialCallback callback,
- String callingPackage,
- String origin) {
- Log.i(TAG, "starting executeCreateCredential with callingPackage: " + callingPackage);
- ICancellationSignal cancelTransport = CancellationSignal.createTransport();
-
- // Check privileged permissions
- mContext.enforceCallingPermission(CREDENTIAL_MANAGER_SET_ORIGIN, null);
-
- final int userId = UserHandle.getCallingUserId();
- final int callingUid = Binder.getCallingUid();
- enforceCallingPackage(callingPackage, callingUid);
-
- // New request session, scoped for this request only.
- final CreateRequestSession session =
- new CreateRequestSession(
- getContext(),
- userId,
- callingUid,
- request,
- callback,
- constructCallingAppInfo(callingPackage, userId, origin),
- CancellationSignal.fromTransport(cancelTransport));
-
- processCreateCredential(request, callback, session);
- return cancelTransport;
- }
-
private void processCreateCredential(
CreateCredentialRequest request,
ICreateCredentialCallback callback,
@@ -577,8 +541,8 @@ public final class CredentialManagerService
Log.i(
TAG,
"Issue invoking onError on ICreateCredentialCallback "
- + "callback: "
- + e.getMessage());
+ + "callback: "
+ + e.getMessage());
}
}
@@ -671,7 +635,8 @@ public final class CredentialManagerService
}
// Send an intent to the UI that we have new enabled providers.
- getContext().sendBroadcast(IntentFactory.createProviderUpdateIntent());
+ getContext().sendBroadcast(IntentFactory.createProviderUpdateIntent(),
+ LAUNCH_CREDENTIAL_SELECTOR);
}
@Override
@@ -692,13 +657,17 @@ public final class CredentialManagerService
if (serviceComponentName.equals(componentName)) {
if (!s.getServicePackageName().equals(callingPackage)) {
// The component name and the package name do not match.
+ MetricUtilities.logApiCalled(
+ ApiName.IS_ENABLED_CREDENTIAL_PROVIDER_SERVICE,
+ ApiStatus.METRICS_API_STATUS_FAILURE, callingUid);
Log.w(
TAG,
"isEnabledCredentialProviderService: Component name does not"
+ " match package name.");
return false;
}
-
+ MetricUtilities.logApiCalled(ApiName.IS_ENABLED_CREDENTIAL_PROVIDER_SERVICE,
+ ApiStatus.METRICS_API_STATUS_SUCCESS, callingUid);
return true;
}
}
@@ -776,10 +745,14 @@ public final class CredentialManagerService
throws IllegalArgumentException, NonCredentialProviderCallerException {
Log.i(TAG, "registerCredentialDescription");
+ if (!isCredentialDescriptionApiEnabled()) {
+ throw new UnsupportedOperationException();
+ }
+
enforceCallingPackage(callingPackage, Binder.getCallingUid());
List<CredentialProviderInfo> services =
- getServicesForCredentialDescription(UserHandle.getCallingUserId());
+ getServicesForCredentialDescription(UserHandle.getCallingUserId());
List<String> providers =
services.stream()
@@ -828,10 +801,14 @@ public final class CredentialManagerService
throws IllegalArgumentException {
Log.i(TAG, "registerCredentialDescription");
+ if (!isCredentialDescriptionApiEnabled()) {
+ throw new UnsupportedOperationException();
+ }
+
enforceCallingPackage(callingPackage, Binder.getCallingUid());
List<CredentialProviderInfo> services =
- getServicesForCredentialDescription(UserHandle.getCallingUserId());
+ getServicesForCredentialDescription(UserHandle.getCallingUserId());
List<String> providers =
services.stream()
diff --git a/services/credentials/java/com/android/server/credentials/GetRequestSession.java b/services/credentials/java/com/android/server/credentials/GetRequestSession.java
index 5e167712a8e8..ce26c885d55f 100644
--- a/services/credentials/java/com/android/server/credentials/GetRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/GetRequestSession.java
@@ -34,6 +34,9 @@ import android.service.credentials.CallingAppInfo;
import android.service.credentials.CredentialProviderInfo;
import android.util.Log;
+import com.android.server.credentials.metrics.ApiName;
+import com.android.server.credentials.metrics.ApiStatus;
+
import java.util.ArrayList;
/**
@@ -44,7 +47,6 @@ public final class GetRequestSession extends RequestSession<GetCredentialRequest
IGetCredentialCallback>
implements ProviderSession.ProviderInternalCallback<GetCredentialResponse> {
private static final String TAG = "GetRequestSession";
-
public GetRequestSession(Context context, int userId, int callingUid,
IGetCredentialCallback callback, GetCredentialRequest request,
CallingAppInfo callingAppInfo, CancellationSignal cancellationSignal) {
@@ -118,16 +120,19 @@ public final class GetRequestSession extends RequestSession<GetCredentialRequest
}
if (isSessionCancelled()) {
// TODO: Differentiate btw cancelled and false
- logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ false);
+ logApiCall(ApiName.GET_CREDENTIAL, /* apiStatus */
+ ApiStatus.METRICS_API_STATUS_CLIENT_CANCELED);
finishSession(/*propagateCancellation=*/true);
return;
}
try {
mClientCallback.onResponse(response);
- logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ true);
+ logApiCall(ApiName.GET_CREDENTIAL, /* apiStatus */
+ ApiStatus.METRICS_API_STATUS_SUCCESS);
} catch (RemoteException e) {
Log.i(TAG, "Issue while responding to client with a response : " + e.getMessage());
- logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ false);
+ logApiCall(ApiName.GET_CREDENTIAL, /* apiStatus */
+ ApiStatus.METRICS_API_STATUS_FAILURE);
}
finishSession(/*propagateCancellation=*/false);
}
@@ -138,7 +143,8 @@ public final class GetRequestSession extends RequestSession<GetCredentialRequest
return;
}
if (isSessionCancelled()) {
- logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ false);
+ logApiCall(ApiName.GET_CREDENTIAL, /* apiStatus */
+ ApiStatus.METRICS_API_STATUS_CLIENT_CANCELED);
finishSession(/*propagateCancellation=*/true);
return;
}
@@ -148,10 +154,20 @@ public final class GetRequestSession extends RequestSession<GetCredentialRequest
} catch (RemoteException e) {
Log.i(TAG, "Issue while responding to client with error : " + e.getMessage());
}
- logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ false);
+ logFailureOrUserCancel(errorType);
finishSession(/*propagateCancellation=*/false);
}
+ private void logFailureOrUserCancel(String errorType) {
+ if (GetCredentialException.TYPE_USER_CANCELED.equals(errorType)) {
+ logApiCall(ApiName.GET_CREDENTIAL,
+ /* apiStatus */ ApiStatus.METRICS_API_STATUS_USER_CANCELED);
+ } else {
+ logApiCall(ApiName.GET_CREDENTIAL,
+ /* apiStatus */ ApiStatus.METRICS_API_STATUS_FAILURE);
+ }
+ }
+
@Override
public void onUiCancellation(boolean isUserCancellation) {
if (isUserCancellation) {
@@ -173,6 +189,12 @@ public final class GetRequestSession extends RequestSession<GetCredentialRequest
public void onProviderStatusChanged(ProviderSession.Status status,
ComponentName componentName) {
Log.i(TAG, "in onStatusChanged with status: " + status);
+ // Auth entry was selected, and it did not have any underlying credentials
+ if (status == ProviderSession.Status.NO_CREDENTIALS_FROM_AUTH_ENTRY) {
+ handleEmptyAuthenticationSelection(componentName);
+ return;
+ }
+ // For any other status, we check if all providers are done and then invoke UI if needed
if (!isAnyProviderPending()) {
// If all provider responses have been received, we can either need the UI,
// or we need to respond with error. The only other case is the entry being
@@ -186,4 +208,34 @@ public final class GetRequestSession extends RequestSession<GetCredentialRequest
}
}
}
+
+ private void handleEmptyAuthenticationSelection(ComponentName componentName) {
+ // Update auth entry statuses across different provider sessions
+ mProviders.keySet().forEach(key -> {
+ ProviderGetSession session = (ProviderGetSession) mProviders.get(key);
+ if (!session.mComponentName.equals(componentName)) {
+ session.updateAuthEntriesStatusFromAnotherSession();
+ }
+ });
+
+ // Invoke UI since it needs to show a snackbar if last auth entry, or a status on each
+ // auth entries along with other valid entries
+ getProviderDataAndInitiateUi();
+
+ // Respond to client if all auth entries are empty and nothing else to show on the UI
+ if (providerDataContainsEmptyAuthEntriesOnly()) {
+ respondToClientWithErrorAndFinish(GetCredentialException.TYPE_NO_CREDENTIAL,
+ "No credentials available");
+ }
+ }
+
+ private boolean providerDataContainsEmptyAuthEntriesOnly() {
+ for (String key : mProviders.keySet()) {
+ ProviderGetSession session = (ProviderGetSession) mProviders.get(key);
+ if (!session.containsEmptyAuthEntriesOnly()) {
+ return false;
+ }
+ }
+ return true;
+ }
}
diff --git a/services/credentials/java/com/android/server/credentials/MetricUtilities.java b/services/credentials/java/com/android/server/credentials/MetricUtilities.java
index 27d9836d9b66..f75a9b685d10 100644
--- a/services/credentials/java/com/android/server/credentials/MetricUtilities.java
+++ b/services/credentials/java/com/android/server/credentials/MetricUtilities.java
@@ -16,14 +16,6 @@
package com.android.server.credentials;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CLEAR_CREDENTIAL;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CREATE_CREDENTIAL;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_GET_CREDENTIAL;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_UNKNOWN;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_CLIENT_CANCELED;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_FAILURE;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_SUCCESS;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_USER_CANCELED;
import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__CANDIDATE_PROVIDER_STATUS__PROVIDER_FINAL_FAILURE;
import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__CANDIDATE_PROVIDER_STATUS__PROVIDER_FINAL_SUCCESS;
import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__CANDIDATE_PROVIDER_STATUS__PROVIDER_QUERY_FAILURE;
@@ -35,6 +27,14 @@ import android.content.Context;
import android.content.pm.PackageManager;
import android.util.Log;
+import com.android.internal.util.FrameworkStatsLog;
+import com.android.server.credentials.metrics.ApiName;
+import com.android.server.credentials.metrics.ApiStatus;
+import com.android.server.credentials.metrics.CandidateProviderMetric;
+import com.android.server.credentials.metrics.ChosenProviderMetric;
+
+import java.util.Map;
+
/**
* For all future metric additions, this will contain their names for local usage after importing
* from {@link com.android.internal.util.FrameworkStatsLog}.
@@ -43,24 +43,10 @@ public class MetricUtilities {
private static final String TAG = "MetricUtilities";
- // Metrics constants
- protected static final int METRICS_API_NAME_UNKNOWN =
- CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_UNKNOWN;
- protected static final int METRICS_API_NAME_GET_CREDENTIAL =
- CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_GET_CREDENTIAL;
- protected static final int METRICS_API_NAME_CREATE_CREDENTIAL =
- CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CREATE_CREDENTIAL;
- protected static final int METRICS_API_NAME_CLEAR_CREDENTIAL =
- CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CLEAR_CREDENTIAL;
- // TODO add isEnabled
- protected static final int METRICS_API_STATUS_SUCCESS =
- CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_SUCCESS;
- protected static final int METRICS_API_STATUS_FAILURE =
- CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_FAILURE;
- protected static final int METRICS_API_STATUS_CLIENT_CANCEL =
- CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_CLIENT_CANCELED;
- protected static final int METRICS_API_STATUS_USER_CANCEL =
- CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_USER_CANCELED;
+ private static final int DEFAULT_INT_32 = -1;
+ private static final int[] DEFAULT_REPEATED_INT_32 = new int[0];
+
+ // Metrics constants TODO(b/269290341) migrate to enums eventually to improve
protected static final int METRICS_PROVIDER_STATUS_FINAL_FAILURE =
CREDENTIAL_MANAGER_API_CALLED__CANDIDATE_PROVIDER_STATUS__PROVIDER_FINAL_FAILURE;
protected static final int METRICS_PROVIDER_STATUS_QUERY_FAILURE =
@@ -77,6 +63,7 @@ public class MetricUtilities {
* This retrieves the uid of any package name, given a context and a component name for the
* package. By default, if the desired package uid cannot be found, it will fall back to a
* bogus uid.
+ *
* @return the uid of a given package
*/
protected static int getPackageUid(Context context, ComponentName componentName) {
@@ -92,4 +79,75 @@ public class MetricUtilities {
return sessUid;
}
+ /**
+ * The most common logging helper, handles the overall status of the API request with the
+ * provider status and latencies. Other versions of this method may be more useful depending
+ * on the situation, as this is geared towards the logging of {@link ProviderSession} types.
+ *
+ * @param apiName the api type to log
+ * @param apiStatus the api status to log
+ * @param providers a map with known providers
+ * @param callingUid the calling UID of the client app
+ * @param chosenProviderMetric the metric data type of the final chosen provider
+ */
+ protected static void logApiCalled(ApiName apiName, ApiStatus apiStatus,
+ Map<String, ProviderSession> providers, int callingUid,
+ ChosenProviderMetric chosenProviderMetric) {
+ var providerSessions = providers.values();
+ int providerSize = providerSessions.size();
+ int[] candidateUidList = new int[providerSize];
+ int[] candidateQueryRoundTripTimeList = new int[providerSize];
+ int[] candidateStatusList = new int[providerSize];
+ int index = 0;
+ for (var session : providerSessions) {
+ CandidateProviderMetric metric = session.mCandidateProviderMetric;
+ candidateUidList[index] = metric.getCandidateUid();
+ candidateQueryRoundTripTimeList[index] = metric.getQueryLatencyMs();
+ candidateStatusList[index] = metric.getProviderQueryStatus();
+ index++;
+ }
+ FrameworkStatsLog.write(FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED,
+ /* api_name */apiName.getMetricCode(),
+ /* caller_uid */ callingUid,
+ /* api_status */ apiStatus.getMetricCode(),
+ /* repeated_candidate_provider_uid */ candidateUidList,
+ /* repeated_candidate_provider_round_trip_time_query_microseconds */
+ candidateQueryRoundTripTimeList,
+ /* repeated_candidate_provider_status */ candidateStatusList,
+ /* chosen_provider_uid */ chosenProviderMetric.getChosenUid(),
+ /* chosen_provider_round_trip_time_overall_microseconds */
+ chosenProviderMetric.getEntireProviderLatencyMs(),
+ /* chosen_provider_final_phase_microseconds */
+ chosenProviderMetric.getFinalPhaseLatencyMs(),
+ /* chosen_provider_status */ chosenProviderMetric.getChosenProviderStatus());
+ }
+
+ /**
+ * This is useful just to record an API calls' final event, and for no other purpose. It will
+ * contain default values for all other optional parameters.
+ *
+ * TODO(b/271135048) - given space requirements, this may be a good candidate for another atom
+ *
+ * @param apiName the api name to log
+ * @param apiStatus the status to log
+ * @param callingUid the calling uid
+ */
+ protected static void logApiCalled(ApiName apiName, ApiStatus apiStatus,
+ int callingUid) {
+ FrameworkStatsLog.write(FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED,
+ /* api_name */apiName.getMetricCode(),
+ /* caller_uid */ callingUid,
+ /* api_status */ apiStatus.getMetricCode(),
+ /* repeated_candidate_provider_uid */ DEFAULT_REPEATED_INT_32,
+ /* repeated_candidate_provider_round_trip_time_query_microseconds */
+ DEFAULT_REPEATED_INT_32,
+ /* repeated_candidate_provider_status */ DEFAULT_REPEATED_INT_32,
+ /* chosen_provider_uid */ DEFAULT_INT_32,
+ /* chosen_provider_round_trip_time_overall_microseconds */
+ DEFAULT_INT_32,
+ /* chosen_provider_final_phase_microseconds */
+ DEFAULT_INT_32,
+ /* chosen_provider_status */ DEFAULT_INT_32);
+ }
+
}
diff --git a/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java b/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java
index 3245c914b2b8..97b78116bbfa 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java
@@ -35,6 +35,7 @@ import android.service.credentials.CreateCredentialRequest;
import android.service.credentials.CreateEntry;
import android.service.credentials.CredentialProviderInfo;
import android.service.credentials.CredentialProviderService;
+import android.service.credentials.RemoteEntry;
import android.util.Log;
import android.util.Pair;
import android.util.Slog;
@@ -301,14 +302,14 @@ public final class ProviderCreateSession extends ProviderSession<
@NonNull
private final Map<String, Pair<CreateEntry, Entry>> mUiCreateEntries = new HashMap<>();
- @Nullable private Pair<String, Pair<CreateEntry, Entry>> mUiRemoteEntry = null;
+ @Nullable private Pair<String, Pair<RemoteEntry, Entry>> mUiRemoteEntry = null;
ProviderResponseDataHandler(String hybridService) {
mExpectedRemoteEntryProviderService = ComponentName.unflattenFromString(hybridService);
}
public void addResponseContent(List<CreateEntry> createEntries,
- CreateEntry remoteEntry) {
+ RemoteEntry remoteEntry) {
createEntries.forEach(this::addCreateEntry);
setRemoteEntry(remoteEntry);
}
@@ -319,7 +320,7 @@ public final class ProviderCreateSession extends ProviderSession<
mUiCreateEntries.put(id, new Pair<>(createEntry, entry));
}
- public void setRemoteEntry(@Nullable CreateEntry remoteEntry) {
+ public void setRemoteEntry(@Nullable RemoteEntry remoteEntry) {
if (remoteEntry == null) {
mUiRemoteEntry = null;
return;
@@ -363,7 +364,7 @@ public final class ProviderCreateSession extends ProviderSession<
return mUiCreateEntries.isEmpty() && mUiRemoteEntry == null;
}
@Nullable
- public CreateEntry getRemoteEntry(String entryKey) {
+ public RemoteEntry getRemoteEntry(String entryKey) {
return mUiRemoteEntry == null || mUiRemoteEntry
.first == null || !mUiRemoteEntry.first.equals(entryKey)
|| mUiRemoteEntry.second == null
diff --git a/services/credentials/java/com/android/server/credentials/ProviderGetSession.java b/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
index 12074c7494bf..ee813e90ddfe 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
@@ -38,6 +38,7 @@ import android.service.credentials.CredentialEntry;
import android.service.credentials.CredentialProviderInfo;
import android.service.credentials.CredentialProviderService;
import android.service.credentials.GetCredentialRequest;
+import android.service.credentials.RemoteEntry;
import android.util.Log;
import android.util.Pair;
import android.util.Slog;
@@ -241,13 +242,14 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
if (additionalContentReceived) {
Log.i(TAG, "Additional content received - removing authentication entry");
mProviderResponseDataHandler.removeAuthenticationAction(entryKey);
+ if (!mProviderResponseDataHandler.isEmptyResponse()) {
+ updateStatusAndInvokeCallback(Status.CREDENTIALS_RECEIVED);
+ }
} else {
Log.i(TAG, "Additional content not received");
mProviderResponseDataHandler
.updateAuthEntryWithNoCredentialsReceived(entryKey);
- }
- if (!mProviderResponseDataHandler.isEmptyResponse()) {
- updateStatusAndInvokeCallback(Status.CREDENTIALS_RECEIVED);
+ updateStatusAndInvokeCallback(Status.NO_CREDENTIALS_FROM_AUTH_ENTRY);
}
break;
case REMOTE_ENTRY_KEY:
@@ -298,7 +300,7 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
}
return new Intent().putExtra(CredentialProviderService.EXTRA_GET_CREDENTIAL_REQUEST,
new GetCredentialRequest(
- mCallingAppInfo, mBeginGetOptionToCredentialOptionMap.get(id)));
+ mCallingAppInfo, List.of(mBeginGetOptionToCredentialOptionMap.get(id))));
}
private Intent setUpFillInIntentWithQueryRequest() {
@@ -414,25 +416,8 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
/** Returns true if either an exception or a response is found. */
private void onActionEntrySelected(ProviderPendingIntentResponse
providerPendingIntentResponse) {
- // Action entry is expected to either contain the final GetCredentialResponse, or it is
- // also acceptable if it does not contain anything. In the second case, we re-show this
- // action on the UI.
- if (providerPendingIntentResponse == null) {
- Log.i(TAG, "providerPendingIntentResponse is null");
- return;
- }
-
- GetCredentialException exception = maybeGetPendingIntentException(
- providerPendingIntentResponse);
- if (exception != null) {
- invokeCallbackWithError(exception.getType(), exception.getMessage());
- }
- GetCredentialResponse response = PendingIntentResultHandler
- .extractGetCredentialResponse(
- providerPendingIntentResponse.getResultData());
- if (response != null) {
- mCallbacks.onFinalResponseReceived(mComponentName, response);
- }
+ Log.i(TAG, "onActionEntrySelected");
+ onCredentialEntrySelected(providerPendingIntentResponse);
}
@@ -449,11 +434,32 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
/**
* When an invalid state occurs, e.g. entry mismatch or no response from provider,
- * we send back a TYPE_UNKNOWN error as to the developer.
+ * we send back a TYPE_NO_CREDENTIAL error as to the developer.
*/
private void invokeCallbackOnInternalInvalidState() {
mCallbacks.onFinalErrorReceived(mComponentName,
- GetCredentialException.TYPE_UNKNOWN, null);
+ GetCredentialException.TYPE_NO_CREDENTIAL, null);
+ }
+
+ /** Update auth entries status based on an auth entry selected from a different session. */
+ public void updateAuthEntriesStatusFromAnotherSession() {
+ // Pass null for entryKey if the auth entry selected belongs to a different session
+ mProviderResponseDataHandler.updateAuthEntryWithNoCredentialsReceived(/*entryKey=*/null);
+ }
+
+ /** Returns true if the provider response contains empty auth entries only, false otherwise. **/
+ public boolean containsEmptyAuthEntriesOnly() {
+ // We do not consider action entries here because if actions are the only entries,
+ // we don't show the UI
+ return mProviderResponseDataHandler.mUiCredentialEntries.isEmpty()
+ && mProviderResponseDataHandler.mUiRemoteEntry == null
+ && mProviderResponseDataHandler.mUiAuthenticationEntries
+ .values().stream().allMatch(
+ e -> e.second.getStatus() == AuthenticationEntry
+ .STATUS_UNLOCKED_BUT_EMPTY_LESS_RECENT
+ || e.second.getStatus()
+ == AuthenticationEntry.STATUS_UNLOCKED_BUT_EMPTY_MOST_RECENT
+ );
}
private class ProviderResponseDataHandler {
@@ -467,7 +473,7 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
private final Map<String, Pair<Action, AuthenticationEntry>> mUiAuthenticationEntries =
new HashMap<>();
- @Nullable private Pair<String, Pair<CredentialEntry, Entry>> mUiRemoteEntry = null;
+ @Nullable private Pair<String, Pair<RemoteEntry, Entry>> mUiRemoteEntry = null;
ProviderResponseDataHandler(ComponentName expectedRemoteEntryProviderService) {
mExpectedRemoteEntryProviderService = expectedRemoteEntryProviderService;
@@ -475,7 +481,7 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
public void addResponseContent(List<CredentialEntry> credentialEntries,
List<Action> actions, List<Action> authenticationActions,
- CredentialEntry remoteEntry) {
+ RemoteEntry remoteEntry) {
credentialEntries.forEach(this::addCredentialEntry);
actions.forEach(this::addAction);
authenticationActions.forEach(
@@ -517,7 +523,7 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
mUiAuthenticationEntries.remove(id);
}
- public void setRemoteEntry(@Nullable CredentialEntry remoteEntry) {
+ public void setRemoteEntry(@Nullable RemoteEntry remoteEntry) {
if (remoteEntry == null) {
return;
}
@@ -528,8 +534,7 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
}
String id = generateUniqueId();
Entry entry = new Entry(REMOTE_ENTRY_KEY,
- id, remoteEntry.getSlice(), setUpFillInIntent(
- remoteEntry.getBeginGetCredentialOption().getId()));
+ id, remoteEntry.getSlice(), setUpFillInIntentForRemoteEntry());
mUiRemoteEntry = new Pair<>(generateUniqueId(), new Pair<>(remoteEntry, entry));
}
@@ -599,7 +604,7 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
}
@Nullable
- public CredentialEntry getRemoteEntry(String entryKey) {
+ public RemoteEntry getRemoteEntry(String entryKey) {
return mUiRemoteEntry.first.equals(entryKey) && mUiRemoteEntry.second != null
? mUiRemoteEntry.second.first : null;
}
@@ -610,7 +615,12 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
? null : mUiCredentialEntries.get(entryKey).first;
}
- public void updateAuthEntryWithNoCredentialsReceived(String entryKey) {
+ public void updateAuthEntryWithNoCredentialsReceived(@Nullable String entryKey) {
+ if (entryKey == null) {
+ // Auth entry from a different provider was selected by the user.
+ updatePreviousMostRecentAuthEntry();
+ return;
+ }
updatePreviousMostRecentAuthEntry();
updateMostRecentAuthEntry(entryKey);
}
@@ -652,4 +662,10 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
from.getFrameworkExtrasIntent());
}
}
+
+ private Intent setUpFillInIntentForRemoteEntry() {
+ return new Intent().putExtra(CredentialProviderService.EXTRA_GET_CREDENTIAL_REQUEST,
+ new GetCredentialRequest(
+ mCallingAppInfo, mCompleteRequest.getCredentialOptions()));
+ }
}
diff --git a/services/credentials/java/com/android/server/credentials/ProviderRegistryGetSession.java b/services/credentials/java/com/android/server/credentials/ProviderRegistryGetSession.java
index 5af8080df5c1..36d6b3dc7636 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderRegistryGetSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderRegistryGetSession.java
@@ -23,7 +23,6 @@ import android.content.Context;
import android.content.Intent;
import android.credentials.CredentialOption;
import android.credentials.GetCredentialException;
-import android.credentials.GetCredentialRequest;
import android.credentials.GetCredentialResponse;
import android.credentials.ui.Entry;
import android.credentials.ui.GetCredentialProviderData;
@@ -49,7 +48,7 @@ import java.util.stream.Stream;
*
* @hide
*/
-public class ProviderRegistryGetSession extends ProviderSession<GetCredentialRequest,
+public class ProviderRegistryGetSession extends ProviderSession<CredentialOption,
Set<CredentialDescriptionRegistry.FilterResult>> {
private static final String TAG = "ProviderRegistryGetSession";
@@ -62,15 +61,14 @@ public class ProviderRegistryGetSession extends ProviderSession<GetCredentialReq
@UserIdInt int userId,
@NonNull GetRequestSession getRequestSession,
@NonNull String credentialProviderPackageName,
- @NonNull List<String> requestOptions) {
+ @NonNull CredentialOption requestOption) {
return new ProviderRegistryGetSession(
context,
userId,
getRequestSession,
- getRequestSession.mClientRequest,
getRequestSession.mClientAppInfo,
credentialProviderPackageName,
- requestOptions);
+ requestOption);
}
@NonNull
@@ -82,24 +80,22 @@ public class ProviderRegistryGetSession extends ProviderSession<GetCredentialReq
@NonNull
private final String mCredentialProviderPackageName;
@NonNull
- private final GetRequestSession mGetRequestSession;
- @NonNull
- private final List<String> mRequestOptions;
+ private final String mFlattenedRequestOptionString;
private List<CredentialEntry> mCredentialEntries;
protected ProviderRegistryGetSession(@NonNull Context context,
@NonNull int userId,
@NonNull GetRequestSession session,
- @NonNull GetCredentialRequest request,
@NonNull CallingAppInfo callingAppInfo,
@NonNull String servicePackageName,
- @NonNull List<String> requestOptions) {
- super(context, null, request, session, userId, null);
- mGetRequestSession = session;
+ @NonNull CredentialOption requestOption) {
+ super(context, null, requestOption, session, userId, null);
mCredentialDescriptionRegistry = CredentialDescriptionRegistry.forUser(userId);
mCallingAppInfo = callingAppInfo;
mCredentialProviderPackageName = servicePackageName;
- mRequestOptions = requestOptions;
+ mFlattenedRequestOptionString = requestOption
+ .getCredentialRetrievalData()
+ .getString(CredentialOption.FLATTENED_REQUEST);
}
private List<Entry> prepareUiCredentialEntries(
@@ -114,23 +110,18 @@ public class ProviderRegistryGetSession extends ProviderSession<GetCredentialReq
Log.i(TAG, "in prepareUiProviderData creating ui entry with id " + entryId);
credentialUiEntries.add(new Entry(CREDENTIAL_ENTRY_KEY, entryId,
credentialEntry.getSlice(),
- setUpFillInIntent(credentialEntry.getType())));
+ setUpFillInIntent()));
}
return credentialUiEntries;
}
- private Intent setUpFillInIntent(String type) {
+ private Intent setUpFillInIntent() {
Intent intent = new Intent();
- for (CredentialOption option : mProviderRequest.getCredentialOptions()) {
- if (option.getType().equals(type)) {
- intent.putExtra(
- CredentialProviderService
- .EXTRA_GET_CREDENTIAL_REQUEST,
- new android.service.credentials.GetCredentialRequest(
- mCallingAppInfo, option));
- return intent;
- }
- }
+ intent.putExtra(
+ CredentialProviderService
+ .EXTRA_GET_CREDENTIAL_REQUEST,
+ new android.service.credentials.GetCredentialRequest(
+ mCallingAppInfo, List.of(mProviderRequest)));
return intent;
}
@@ -176,11 +167,6 @@ public class ProviderRegistryGetSession extends ProviderSession<GetCredentialReq
private void onCredentialEntrySelected(CredentialEntry credentialEntry,
ProviderPendingIntentResponse providerPendingIntentResponse) {
- if (!mCredentialEntries.contains(credentialEntry)) {
- invokeCallbackWithError("",
- "");
- }
-
if (providerPendingIntentResponse != null) {
// Check if pending intent has an error
GetCredentialException exception = maybeGetPendingIntentException(
@@ -228,13 +214,13 @@ public class ProviderRegistryGetSession extends ProviderSession<GetCredentialReq
protected void invokeSession() {
mProviderResponse = mCredentialDescriptionRegistry
.getFilteredResultForProvider(mCredentialProviderPackageName,
- mRequestOptions);
+ mFlattenedRequestOptionString);
mCredentialEntries = mProviderResponse.stream().flatMap(
(Function<CredentialDescriptionRegistry.FilterResult,
Stream<CredentialEntry>>) filterResult
-> filterResult.mCredentialEntries.stream())
.collect(Collectors.toList());
- setStatus(Status.CREDENTIALS_RECEIVED);
+ updateStatusAndInvokeCallback(Status.CREDENTIALS_RECEIVED);
// TODO(use metric later)
}
diff --git a/services/credentials/java/com/android/server/credentials/ProviderSession.java b/services/credentials/java/com/android/server/credentials/ProviderSession.java
index 2f9d57872c3c..ecddcf30f88d 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderSession.java
@@ -66,7 +66,8 @@ public abstract class ProviderSession<T, R>
* on the credMan UI.
*/
public static boolean isUiInvokingStatus(Status status) {
- return status == Status.CREDENTIALS_RECEIVED || status == Status.SAVE_ENTRIES_RECEIVED;
+ return status == Status.CREDENTIALS_RECEIVED || status == Status.SAVE_ENTRIES_RECEIVED
+ || status == Status.NO_CREDENTIALS_FROM_AUTH_ENTRY;
}
/**
@@ -140,7 +141,7 @@ public abstract class ProviderSession<T, R>
PENDING_INTENT_INVOKED,
CREDENTIAL_RECEIVED_FROM_SELECTION,
SAVE_ENTRIES_RECEIVED, CANCELED,
- NO_CREDENTIALS, EMPTY_RESPONSE, COMPLETE
+ NO_CREDENTIALS, EMPTY_RESPONSE, NO_CREDENTIALS_FROM_AUTH_ENTRY, COMPLETE
}
/** Converts exception to a provider session status. */
diff --git a/services/credentials/java/com/android/server/credentials/RequestSession.java b/services/credentials/java/com/android/server/credentials/RequestSession.java
index f0d05c5dfd05..86e05cf62f5f 100644
--- a/services/credentials/java/com/android/server/credentials/RequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/RequestSession.java
@@ -16,12 +16,7 @@
package com.android.server.credentials;
-import static com.android.server.credentials.MetricUtilities.METRICS_API_NAME_CLEAR_CREDENTIAL;
-import static com.android.server.credentials.MetricUtilities.METRICS_API_NAME_CREATE_CREDENTIAL;
-import static com.android.server.credentials.MetricUtilities.METRICS_API_NAME_GET_CREDENTIAL;
-import static com.android.server.credentials.MetricUtilities.METRICS_API_NAME_UNKNOWN;
-import static com.android.server.credentials.MetricUtilities.METRICS_API_STATUS_FAILURE;
-import static com.android.server.credentials.MetricUtilities.METRICS_API_STATUS_SUCCESS;
+import static com.android.server.credentials.MetricUtilities.logApiCalled;
import android.annotation.NonNull;
import android.annotation.UserIdInt;
@@ -39,7 +34,8 @@ import android.service.credentials.CredentialProviderInfo;
import android.util.Log;
import com.android.internal.R;
-import com.android.internal.util.FrameworkStatsLog;
+import com.android.server.credentials.metrics.ApiName;
+import com.android.server.credentials.metrics.ApiStatus;
import com.android.server.credentials.metrics.CandidateProviderMetric;
import com.android.server.credentials.metrics.ChosenProviderMetric;
@@ -162,50 +158,10 @@ abstract class RequestSession<T, U> implements CredentialManagerUi.CredentialMan
}
return false;
}
- // TODO: move these definitions to a separate logging focused class.
- enum RequestType {
- GET_CREDENTIALS,
- CREATE_CREDENTIALS,
- CLEAR_CREDENTIALS,
- }
- private static int getApiNameFromRequestType(RequestType requestType) {
- switch (requestType) {
- case GET_CREDENTIALS:
- return METRICS_API_NAME_GET_CREDENTIAL;
- case CREATE_CREDENTIALS:
- return METRICS_API_NAME_CREATE_CREDENTIAL;
- case CLEAR_CREDENTIALS:
- return METRICS_API_NAME_CLEAR_CREDENTIAL;
- default:
- return METRICS_API_NAME_UNKNOWN;
- }
- }
-
- protected void logApiCalled(RequestType requestType, boolean isSuccessfulOverall) {
- var providerSessions = mProviders.values();
- int providerSize = providerSessions.size();
- int[] candidateUidList = new int[providerSize];
- int[] candidateQueryRoundTripTimeList = new int[providerSize];
- int[] candidateStatusList = new int[providerSize];
- int index = 0;
- for (var session : providerSessions) {
- CandidateProviderMetric metric = session.mCandidateProviderMetric;
- candidateUidList[index] = metric.getCandidateUid();
- candidateQueryRoundTripTimeList[index] = metric.getQueryLatencyMs();
- candidateStatusList[index] = metric.getProviderQueryStatus();
- index++;
- }
- FrameworkStatsLog.write(FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED,
- /* api_name */getApiNameFromRequestType(requestType), /* caller_uid */
- mCallingUid, /* api_status */
- isSuccessfulOverall ? METRICS_API_STATUS_SUCCESS : METRICS_API_STATUS_FAILURE,
- candidateUidList,
- candidateQueryRoundTripTimeList,
- candidateStatusList, mChosenProviderMetric.getChosenUid(),
- mChosenProviderMetric.getEntireProviderLatencyMs(),
- mChosenProviderMetric.getFinalPhaseLatencyMs(),
- mChosenProviderMetric.getChosenProviderStatus());
+ protected void logApiCall(ApiName apiName, ApiStatus apiStatus) {
+ logApiCalled(apiName, apiStatus, mProviders, mCallingUid,
+ mChosenProviderMetric);
}
protected boolean isSessionCancelled() {
@@ -216,7 +172,7 @@ abstract class RequestSession<T, U> implements CredentialManagerUi.CredentialMan
* Returns true if at least one provider is ready for UI invocation, and no
* provider is pending a response.
*/
- boolean isUiInvocationNeeded() {
+ protected boolean isUiInvocationNeeded() {
for (ProviderSession session : mProviders.values()) {
if (ProviderSession.isUiInvokingStatus(session.getStatus())) {
return true;
diff --git a/services/credentials/java/com/android/server/credentials/metrics/ApiName.java b/services/credentials/java/com/android/server/credentials/metrics/ApiName.java
new file mode 100644
index 000000000000..d4b51dfcc299
--- /dev/null
+++ b/services/credentials/java/com/android/server/credentials/metrics/ApiName.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2023 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.credentials.metrics;
+
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CLEAR_CREDENTIAL;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CREATE_CREDENTIAL;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_GET_CREDENTIAL;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_IS_ENABLED_CREDENTIAL_PROVIDER_SERVICE;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_UNKNOWN;
+
+public enum ApiName {
+ UNKNOWN(CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_UNKNOWN),
+ GET_CREDENTIAL(CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_GET_CREDENTIAL),
+ CREATE_CREDENTIAL(CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CREATE_CREDENTIAL),
+ CLEAR_CREDENTIAL(CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CLEAR_CREDENTIAL),
+ IS_ENABLED_CREDENTIAL_PROVIDER_SERVICE(
+ CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_IS_ENABLED_CREDENTIAL_PROVIDER_SERVICE
+ );
+
+ private final int mInnerMetricCode;
+
+ ApiName(int innerMetricCode) {
+ this.mInnerMetricCode = innerMetricCode;
+ }
+
+ /**
+ * Gives the West-world version of the metric name.
+ *
+ * @return a code corresponding to the west world metric name
+ */
+ public int getMetricCode() {
+ return this.mInnerMetricCode;
+ }
+}
diff --git a/services/credentials/java/com/android/server/credentials/metrics/ApiStatus.java b/services/credentials/java/com/android/server/credentials/metrics/ApiStatus.java
new file mode 100644
index 000000000000..36a1f2df6d24
--- /dev/null
+++ b/services/credentials/java/com/android/server/credentials/metrics/ApiStatus.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2023 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.credentials.metrics;
+
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_CLIENT_CANCELED;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_FAILURE;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_SUCCESS;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_USER_CANCELED;
+
+public enum ApiStatus {
+ METRICS_API_STATUS_SUCCESS(CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_SUCCESS),
+ METRICS_API_STATUS_FAILURE(CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_FAILURE),
+ METRICS_API_STATUS_CLIENT_CANCELED(
+ CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_CLIENT_CANCELED),
+ METRICS_API_STATUS_USER_CANCELED(
+ CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_USER_CANCELED);
+
+ private final int mInnerMetricCode;
+
+ ApiStatus(int innerMetricCode) {
+ this.mInnerMetricCode = innerMetricCode;
+ }
+
+ /**
+ * Gives the West-world version of the metric name.
+ *
+ * @return a code corresponding to the west world metric name
+ */
+ public int getMetricCode() {
+ return this.mInnerMetricCode;
+ }
+}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index bfcb4c7b6bc0..e9c23a052422 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -11337,7 +11337,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_APPLICATION_RESTRICTIONS)
.setAdmin(caller.getPackageName())
- .setBoolean(/* isDelegate */ who == null)
+ .setBoolean(/* isDelegate */ isCallerDelegate(caller))
.setStrings(packageName)
.write();
}
@@ -13378,7 +13378,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_APPLICATION_HIDDEN)
.setAdmin(caller.getPackageName())
- .setBoolean(/* isDelegate */ who == null)
+ .setBoolean(/* isDelegate */ isCallerDelegate(caller))
.setStrings(packageName, hidden ? "hidden" : "not_hidden",
parent ? CALLED_FROM_PARENT : NOT_CALLED_FROM_PARENT)
.write();
@@ -13730,7 +13730,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_UNINSTALL_BLOCKED)
.setAdmin(caller.getPackageName())
- .setBoolean(/* isDelegate */ who == null)
+ .setBoolean(/* isDelegate */ isCallerDelegate(caller))
.setStrings(packageName)
.write();
}
@@ -16280,7 +16280,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
.setAdmin(caller.getPackageName())
.setStrings(permission)
.setInt(grantState)
- .setBoolean(/* isDelegate */ admin == null)
+ .setBoolean(
+ /* isDelegate */ isCallerDelegate(caller))
.write();
callback.sendResult(Bundle.EMPTY);
@@ -16405,12 +16406,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
mInjector.getPackageManager().getPackagesForUid(caller.getUid()));
Preconditions.checkArgument(callerUidPackageNames.contains(packageName),
"Caller uid doesn't match the one for the provided package.");
+
+ return checkProvisioningPreconditionSkipPermission(action, packageName, caller.getUserId())
+ == STATUS_OK;
} finally {
mInjector.binderRestoreCallingIdentity(ident);
}
-
- return checkProvisioningPreconditionSkipPermission(action, packageName, caller.getUserId())
- == STATUS_OK;
}
@Override
@@ -22183,6 +22184,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
private static final HashMap<String, String> DELEGATE_SCOPES = new HashMap<>();
{
DELEGATE_SCOPES.put(MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS, DELEGATION_PERMISSION_GRANT);
+ DELEGATE_SCOPES.put(MANAGE_DEVICE_POLICY_APP_RESTRICTIONS, DELEGATION_APP_RESTRICTIONS);
+ DELEGATE_SCOPES.put(MANAGE_DEVICE_POLICY_APPS_CONTROL, DELEGATION_BLOCK_UNINSTALL);
+ DELEGATE_SCOPES.put(MANAGE_DEVICE_POLICY_SECURITY_LOGGING, DELEGATION_SECURITY_LOGGING);
+ DELEGATE_SCOPES.put(MANAGE_DEVICE_POLICY_PACKAGE_STATE, DELEGATION_PACKAGE_ACCESS);
}
private static final HashMap<String, String> CROSS_USER_PERMISSIONS =
@@ -22371,6 +22376,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
+ permission
+ ", "
+ CROSS_USER_PERMISSIONS.get(permission)
+ + "(if calling cross-user)"
+ "}");
}
}
diff --git a/services/incremental/TEST_MAPPING b/services/incremental/TEST_MAPPING
index 3976a70a28e5..be7feb5c9bf7 100644
--- a/services/incremental/TEST_MAPPING
+++ b/services/incremental/TEST_MAPPING
@@ -16,13 +16,13 @@
},
{
"name": "service.incremental_test"
+ },
+ {
+ "name": "CtsInstalledLoadingProgressHostTests"
}
],
"presubmit-large": [
{
- "name": "CtsInstalledLoadingProgressHostTests"
- },
- {
"name": "CtsContentTestCases",
"options": [
{
diff --git a/services/robotests/src/com/android/server/media/AudioPoliciesBluetoothRouteControllerTest.java b/services/robotests/src/com/android/server/media/AudioPoliciesBluetoothRouteControllerTest.java
new file mode 100644
index 000000000000..0ad418427183
--- /dev/null
+++ b/services/robotests/src/com/android/server/media/AudioPoliciesBluetoothRouteControllerTest.java
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2023 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.media;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.when;
+
+import android.app.Application;
+import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.content.Intent;
+import android.media.AudioManager;
+import android.media.MediaRoute2Info;
+import android.os.UserHandle;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.Shadows;
+import org.robolectric.shadows.ShadowBluetoothAdapter;
+import org.robolectric.shadows.ShadowBluetoothDevice;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+@RunWith(RobolectricTestRunner.class)
+public class AudioPoliciesBluetoothRouteControllerTest {
+
+ private static final String DEVICE_ADDRESS_UNKNOWN = ":unknown:ip:address:";
+ private static final String DEVICE_ADDRESS_SAMPLE_1 = "30:59:8B:E4:C6:35";
+ private static final String DEVICE_ADDRESS_SAMPLE_2 = "0D:0D:A6:FF:8D:B6";
+ private static final String DEVICE_ADDRESS_SAMPLE_3 = "2D:9B:0C:C2:6F:78";
+ private static final String DEVICE_ADDRESS_SAMPLE_4 = "66:88:F9:2D:A8:1E";
+
+ private Context mContext;
+
+ private ShadowBluetoothAdapter mShadowBluetoothAdapter;
+
+ @Mock
+ private BluetoothRouteController.BluetoothRoutesUpdatedListener mListener;
+
+ @Mock
+ private BluetoothProfileMonitor mBluetoothProfileMonitor;
+
+ private AudioPoliciesBluetoothRouteController mAudioPoliciesBluetoothRouteController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ Application application = ApplicationProvider.getApplicationContext();
+ mContext = application;
+
+ BluetoothManager bluetoothManager = (BluetoothManager)
+ mContext.getSystemService(Context.BLUETOOTH_SERVICE);
+
+ BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
+ mShadowBluetoothAdapter = Shadows.shadowOf(bluetoothAdapter);
+
+ mAudioPoliciesBluetoothRouteController =
+ new AudioPoliciesBluetoothRouteController(mContext, bluetoothAdapter,
+ mBluetoothProfileMonitor, mListener) {
+ @Override
+ boolean isDeviceConnected(BluetoothDevice device) {
+ return true;
+ }
+ };
+
+ // Enable A2DP profile.
+ when(mBluetoothProfileMonitor.isProfileSupported(eq(BluetoothProfile.A2DP), any()))
+ .thenReturn(true);
+ mShadowBluetoothAdapter.setProfileConnectionState(BluetoothProfile.A2DP,
+ BluetoothProfile.STATE_CONNECTED);
+
+ mAudioPoliciesBluetoothRouteController.start(UserHandle.of(0));
+ }
+
+ @Test
+ public void getSelectedRoute_noBluetoothRoutesAvailable_returnsNull() {
+ assertThat(mAudioPoliciesBluetoothRouteController.getSelectedRoute()).isNull();
+ }
+
+ @Test
+ public void selectRoute_noBluetoothRoutesAvailable_returnsFalse() {
+ assertThat(mAudioPoliciesBluetoothRouteController
+ .selectRoute(DEVICE_ADDRESS_UNKNOWN)).isFalse();
+ }
+
+ @Test
+ public void selectRoute_noDeviceWithGivenAddress_returnsFalse() {
+ Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(
+ DEVICE_ADDRESS_SAMPLE_1, DEVICE_ADDRESS_SAMPLE_3);
+
+ mShadowBluetoothAdapter.setBondedDevices(devices);
+
+ assertThat(mAudioPoliciesBluetoothRouteController
+ .selectRoute(DEVICE_ADDRESS_SAMPLE_2)).isFalse();
+ }
+
+ @Test
+ public void selectRoute_deviceIsInDevicesSet_returnsTrue() {
+ Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(
+ DEVICE_ADDRESS_SAMPLE_1, DEVICE_ADDRESS_SAMPLE_2);
+
+ mShadowBluetoothAdapter.setBondedDevices(devices);
+
+ assertThat(mAudioPoliciesBluetoothRouteController
+ .selectRoute(DEVICE_ADDRESS_SAMPLE_1)).isTrue();
+ }
+
+ @Test
+ public void selectRoute_resetSelectedDevice_returnsTrue() {
+ Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(
+ DEVICE_ADDRESS_SAMPLE_1, DEVICE_ADDRESS_SAMPLE_2);
+
+ mShadowBluetoothAdapter.setBondedDevices(devices);
+
+ mAudioPoliciesBluetoothRouteController.selectRoute(DEVICE_ADDRESS_SAMPLE_1);
+ assertThat(mAudioPoliciesBluetoothRouteController.selectRoute(null)).isTrue();
+ }
+
+ @Test
+ public void selectRoute_noSelectedDevice_returnsTrue() {
+ Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(
+ DEVICE_ADDRESS_SAMPLE_1, DEVICE_ADDRESS_SAMPLE_2);
+
+ mShadowBluetoothAdapter.setBondedDevices(devices);
+
+ assertThat(mAudioPoliciesBluetoothRouteController.selectRoute(null)).isTrue();
+ }
+
+ @Test
+ public void getSelectedRoute_updateRouteFailed_returnsNull() {
+ Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(
+ DEVICE_ADDRESS_SAMPLE_1, DEVICE_ADDRESS_SAMPLE_2);
+
+ mShadowBluetoothAdapter.setBondedDevices(devices);
+ mAudioPoliciesBluetoothRouteController
+ .selectRoute(DEVICE_ADDRESS_SAMPLE_3);
+
+ assertThat(mAudioPoliciesBluetoothRouteController.getSelectedRoute()).isNull();
+ }
+
+ @Test
+ public void getSelectedRoute_updateRouteSuccessful_returnsUpdateDevice() {
+ Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(
+ DEVICE_ADDRESS_SAMPLE_1, DEVICE_ADDRESS_SAMPLE_2, DEVICE_ADDRESS_SAMPLE_4);
+
+ assertThat(mAudioPoliciesBluetoothRouteController.getSelectedRoute()).isNull();
+
+ mShadowBluetoothAdapter.setBondedDevices(devices);
+
+ assertThat(mAudioPoliciesBluetoothRouteController
+ .selectRoute(DEVICE_ADDRESS_SAMPLE_4)).isTrue();
+
+ MediaRoute2Info selectedRoute = mAudioPoliciesBluetoothRouteController.getSelectedRoute();
+ assertThat(selectedRoute.getAddress()).isEqualTo(DEVICE_ADDRESS_SAMPLE_4);
+ }
+
+ @Test
+ public void getSelectedRoute_resetSelectedRoute_returnsNull() {
+ Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(
+ DEVICE_ADDRESS_SAMPLE_1, DEVICE_ADDRESS_SAMPLE_2, DEVICE_ADDRESS_SAMPLE_4);
+
+ mShadowBluetoothAdapter.setBondedDevices(devices);
+
+ // Device is not null now.
+ mAudioPoliciesBluetoothRouteController.selectRoute(DEVICE_ADDRESS_SAMPLE_4);
+ // Rest the device.
+ mAudioPoliciesBluetoothRouteController.selectRoute(null);
+
+ assertThat(mAudioPoliciesBluetoothRouteController.getSelectedRoute())
+ .isNull();
+ }
+
+ @Test
+ public void getTransferableRoutes_noSelectedRoute_returnsAllBluetoothDevices() {
+ String[] addresses = new String[] { DEVICE_ADDRESS_SAMPLE_1,
+ DEVICE_ADDRESS_SAMPLE_2, DEVICE_ADDRESS_SAMPLE_4 };
+ Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(addresses);
+ mShadowBluetoothAdapter.setBondedDevices(devices);
+
+ // Force route controller to update bluetooth devices list.
+ sendBluetoothDevicesChangedBroadcast();
+
+ Set<String> transferableDevices = extractAddressesListFrom(
+ mAudioPoliciesBluetoothRouteController.getTransferableRoutes());
+ assertThat(transferableDevices).containsExactlyElementsIn(addresses);
+ }
+
+ @Test
+ public void getTransferableRoutes_hasSelectedRoute_returnsRoutesWithoutSelectedDevice() {
+ String[] addresses = new String[] { DEVICE_ADDRESS_SAMPLE_1,
+ DEVICE_ADDRESS_SAMPLE_2, DEVICE_ADDRESS_SAMPLE_4 };
+ Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(addresses);
+ mShadowBluetoothAdapter.setBondedDevices(devices);
+
+ // Force route controller to update bluetooth devices list.
+ sendBluetoothDevicesChangedBroadcast();
+ mAudioPoliciesBluetoothRouteController.selectRoute(DEVICE_ADDRESS_SAMPLE_4);
+
+ Set<String> transferableDevices = extractAddressesListFrom(
+ mAudioPoliciesBluetoothRouteController.getTransferableRoutes());
+ assertThat(transferableDevices).containsExactly(DEVICE_ADDRESS_SAMPLE_1,
+ DEVICE_ADDRESS_SAMPLE_2);
+ }
+
+ @Test
+ public void getAllBluetoothRoutes_hasSelectedRoute_returnsAllRoutes() {
+ String[] addresses = new String[] { DEVICE_ADDRESS_SAMPLE_1,
+ DEVICE_ADDRESS_SAMPLE_2, DEVICE_ADDRESS_SAMPLE_4 };
+ Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(addresses);
+ mShadowBluetoothAdapter.setBondedDevices(devices);
+
+ // Force route controller to update bluetooth devices list.
+ sendBluetoothDevicesChangedBroadcast();
+ mAudioPoliciesBluetoothRouteController.selectRoute(DEVICE_ADDRESS_SAMPLE_4);
+
+ Set<String> bluetoothDevices = extractAddressesListFrom(
+ mAudioPoliciesBluetoothRouteController.getAllBluetoothRoutes());
+ assertThat(bluetoothDevices).containsExactlyElementsIn(addresses);
+ }
+
+ @Test
+ public void updateVolumeForDevice_setVolumeForA2DPTo25_selectedRouteVolumeIsUpdated() {
+ String[] addresses = new String[] { DEVICE_ADDRESS_SAMPLE_1,
+ DEVICE_ADDRESS_SAMPLE_2, DEVICE_ADDRESS_SAMPLE_4 };
+ Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(addresses);
+ mShadowBluetoothAdapter.setBondedDevices(devices);
+
+ // Force route controller to update bluetooth devices list.
+ sendBluetoothDevicesChangedBroadcast();
+ mAudioPoliciesBluetoothRouteController.selectRoute(DEVICE_ADDRESS_SAMPLE_4);
+
+ mAudioPoliciesBluetoothRouteController.updateVolumeForDevices(
+ AudioManager.DEVICE_OUT_BLUETOOTH_A2DP, 25);
+
+ MediaRoute2Info selectedRoute = mAudioPoliciesBluetoothRouteController.getSelectedRoute();
+ assertThat(selectedRoute.getVolume()).isEqualTo(25);
+ }
+
+ private void sendBluetoothDevicesChangedBroadcast() {
+ Intent intent = new Intent(BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED);
+ mContext.sendBroadcast(intent);
+ }
+
+ private static Set<String> extractAddressesListFrom(Collection<MediaRoute2Info> routes) {
+ Set<String> addresses = new HashSet<>();
+
+ for (MediaRoute2Info route: routes) {
+ addresses.add(route.getAddress());
+ }
+
+ return addresses;
+ }
+
+ private static Set<BluetoothDevice> generateFakeBluetoothDevicesSet(String... addresses) {
+ Set<BluetoothDevice> devices = new HashSet<>();
+
+ for (String address: addresses) {
+ devices.add(ShadowBluetoothDevice.newInstance(address));
+ }
+
+ return devices;
+ }
+}
diff --git a/services/tests/InputMethodSystemServerTests/Android.bp b/services/tests/InputMethodSystemServerTests/Android.bp
index 05a8b11830f7..07ddda39649a 100644
--- a/services/tests/InputMethodSystemServerTests/Android.bp
+++ b/services/tests/InputMethodSystemServerTests/Android.bp
@@ -52,6 +52,10 @@ android_test {
"android.test.runner",
],
+ data: [
+ ":SimpleTestIme",
+ ],
+
certificate: "platform",
platform_apis: true,
test_suites: ["device-tests"],
diff --git a/services/tests/InputMethodSystemServerTests/AndroidTest.xml b/services/tests/InputMethodSystemServerTests/AndroidTest.xml
index 92be78060da8..13719343ac49 100644
--- a/services/tests/InputMethodSystemServerTests/AndroidTest.xml
+++ b/services/tests/InputMethodSystemServerTests/AndroidTest.xml
@@ -21,6 +21,7 @@
<option name="cleanup-apks" value="true" />
<option name="install-arg" value="-t" />
<option name="test-file-name" value="FrameworksInputMethodSystemServerTests.apk" />
+ <option name="test-file-name" value="SimpleTestIme.apk" />
</target_preparer>
<option name="test-tag" value="FrameworksInputMethodSystemServerTests" />
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceRestrictImeAmountTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceRestrictImeAmountTest.java
new file mode 100644
index 000000000000..7cbfc52c5cce
--- /dev/null
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceRestrictImeAmountTest.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2023 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.inputmethod;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.junit.Assert.assertEquals;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.util.ArrayMap;
+import android.view.inputmethod.InputMethod;
+import android.view.inputmethod.InputMethodInfo;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class InputMethodManagerServiceRestrictImeAmountTest extends
+ InputMethodManagerServiceTestBase {
+
+ @Test
+ public void testFilterInputMethodServices_loadsAllImesBelowThreshold() {
+ List<ResolveInfo> resolveInfoList = new ArrayList<>();
+ for (int i = 0; i < 5; i++) {
+ resolveInfoList.add(
+ createFakeResolveInfo("com.android.apps.inputmethod.simpleime", "IME" + i));
+ }
+
+ final List<InputMethodInfo> methodList = filterInputMethodServices(resolveInfoList,
+ List.of());
+ assertEquals(5, methodList.size());
+ }
+
+ @Test
+ public void testFilterInputMethodServices_ignoresImesBeyondThreshold() {
+ List<ResolveInfo> resolveInfoList = new ArrayList<>();
+ for (int i = 0; i < 2 * InputMethodInfo.MAX_IMES_PER_PACKAGE; i++) {
+ resolveInfoList.add(
+ createFakeResolveInfo("com.android.apps.inputmethod.simpleime", "IME" + i));
+ }
+
+ final List<InputMethodInfo> methodList = filterInputMethodServices(resolveInfoList,
+ List.of());
+ assertWithMessage("Filtered IMEs").that(methodList.size()).isEqualTo(
+ InputMethodInfo.MAX_IMES_PER_PACKAGE);
+ }
+
+ @Test
+ public void testFilterInputMethodServices_loadsSystemImesBeyondThreshold() {
+ List<ResolveInfo> resolveInfoList = new ArrayList<>();
+ for (int i = 0; i < 2 * InputMethodInfo.MAX_IMES_PER_PACKAGE; i++) {
+ resolveInfoList.add(
+ createFakeSystemResolveInfo("com.android.apps.inputmethod.systemime",
+ "SystemIME" + i));
+ }
+
+ final List<InputMethodInfo> methodList = filterInputMethodServices(resolveInfoList,
+ List.of());
+ assertWithMessage("Filtered IMEs").that(methodList.size()).isEqualTo(
+ 2 * InputMethodInfo.MAX_IMES_PER_PACKAGE);
+ }
+
+ @Test
+ public void testFilterInputMethodServices_ignoresImesBeyondThresholdFromTwoPackages() {
+ List<ResolveInfo> resolveInfoList = new ArrayList<>();
+ for (int i = 0; i < 2 * InputMethodInfo.MAX_IMES_PER_PACKAGE; i++) {
+ resolveInfoList.add(
+ createFakeResolveInfo("com.android.apps.inputmethod.simpleime1", "IME1_" + i));
+ }
+ for (int i = 0; i < 2 * InputMethodInfo.MAX_IMES_PER_PACKAGE; i++) {
+ resolveInfoList.add(
+ createFakeResolveInfo("com.android.apps.inputmethod.simpleime2", "IME2_" + i));
+ }
+
+ final List<InputMethodInfo> methodList = filterInputMethodServices(resolveInfoList,
+ List.of());
+ assertWithMessage("Filtered IMEs").that(methodList.size()).isEqualTo(
+ 2 * InputMethodInfo.MAX_IMES_PER_PACKAGE);
+ }
+
+ @Test
+ public void testFilterInputMethodServices_stillLoadsEnabledImesBeyondThreshold() {
+ final ResolveInfo enabledIme = createFakeResolveInfo(
+ "com.android.apps.inputmethod.simpleime_enabled", "EnabledIME");
+
+ List<ResolveInfo> resolveInfoList = new ArrayList<>();
+ for (int i = 0; i < 2 * InputMethodInfo.MAX_IMES_PER_PACKAGE; i++) {
+ resolveInfoList.add(
+ createFakeResolveInfo("com.android.apps.inputmethod.simpleime", "IME" + i));
+ }
+ resolveInfoList.add(enabledIme);
+
+ final List<InputMethodInfo> methodList = filterInputMethodServices(resolveInfoList,
+ List.of(new ComponentName(enabledIme.serviceInfo.packageName,
+ enabledIme.serviceInfo.name).flattenToShortString()));
+
+ assertWithMessage("Filtered IMEs").that(methodList.size()).isEqualTo(
+ 1 + InputMethodInfo.MAX_IMES_PER_PACKAGE);
+ }
+
+ private List<InputMethodInfo> filterInputMethodServices(List<ResolveInfo> resolveInfoList,
+ List<String> enabledComponents) {
+ final ArrayMap<String, InputMethodInfo> methodMap = new ArrayMap<>();
+ final ArrayList<InputMethodInfo> methodList = new ArrayList<>();
+ InputMethodManagerService.filterInputMethodServices(new ArrayMap<>(), methodMap, methodList,
+ enabledComponents, mContext, resolveInfoList);
+ return methodList;
+ }
+
+ private ResolveInfo createFakeSystemResolveInfo(String packageName, String componentName) {
+ final ResolveInfo ime = createFakeResolveInfo(packageName, componentName);
+ ime.serviceInfo.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
+ return ime;
+ }
+
+ private ResolveInfo createFakeResolveInfo(String packageName, String componentName) {
+ final ResolveInfo ime = getResolveInfo("com.android.apps.inputmethod.simpleime");
+ if (packageName != null) {
+ ime.serviceInfo.packageName = packageName;
+ }
+ if (componentName != null) {
+ ime.serviceInfo.name = componentName;
+ }
+ return ime;
+ }
+
+ private ResolveInfo getResolveInfo(String packageName) {
+ final int flags = PackageManager.GET_META_DATA
+ | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
+ final List<ResolveInfo> ime = mContext.getPackageManager().queryIntentServices(
+ new Intent(InputMethod.SERVICE_INTERFACE).setPackage(packageName),
+ PackageManager.ResolveInfoFlags.of(flags));
+ assertWithMessage("Loaded IMEs").that(ime.size()).isGreaterThan(0);
+ return ime.get(0);
+ }
+}
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
index dbdffd05714a..9501b9604fa0 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
@@ -127,7 +127,7 @@ public class InputMethodManagerServiceTestBase {
mockitoSession()
.initMocks(this)
.strictness(Strictness.LENIENT)
- .mockStatic(LocalServices.class)
+ .spyStatic(LocalServices.class)
.mockStatic(ServiceManager.class)
.mockStatic(SystemServerInitThreadPool.class)
.startMocking();
@@ -212,6 +212,7 @@ public class InputMethodManagerServiceTestBase {
new InputMethodManagerService.Lifecycle(mContext, mInputMethodManagerService);
// Public local InputMethodManagerService.
+ LocalServices.removeServiceForTest(InputMethodManagerInternal.class);
lifecycle.onStart();
try {
// After this boot phase, services can broadcast Intents.
@@ -237,6 +238,7 @@ public class InputMethodManagerServiceTestBase {
if (mMockingSession != null) {
mMockingSession.finishMocking();
}
+ LocalServices.removeServiceForTest(InputMethodManagerInternal.class);
}
protected void verifyShowSoftInput(boolean setVisible, boolean showSoftInput)
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/SwitchKeyboardLayoutTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/SwitchKeyboardLayoutTest.java
new file mode 100644
index 000000000000..111cabd298f5
--- /dev/null
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/SwitchKeyboardLayoutTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 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.inputmethod;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class SwitchKeyboardLayoutTest extends InputMethodManagerServiceTestBase {
+ @Test
+ public void testSwitchToNextKeyboardLayout() {
+ ExtendedMockito.spyOn(mInputMethodManagerService.mSwitchingController);
+ InputMethodManagerInternal.get().switchKeyboardLayout(1);
+ verify(mInputMethodManagerService.mSwitchingController)
+ .getNextInputMethodLocked(eq(true) /* onlyCurrentIme */, any(), any());
+ }
+}
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java
index a39e0216f4e5..836f8581e8eb 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -566,6 +566,22 @@ public class PackageManagerSettingsTests {
}
@Test
+ public void testWriteCorruptReadPackageRestrictions() {
+ final Settings settingsUnderTest = makeSettings();
+
+ populateDistractionFlags(settingsUnderTest);
+ settingsUnderTest.writePackageRestrictionsLPr(0, /*sync=*/true);
+
+ // Corrupt primary file.
+ writeCorruptedPackageRestrictions(0);
+
+ // now read and verify
+ populateDefaultSettings(settingsUnderTest);
+ settingsUnderTest.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
+ verifyDistractionFlags(settingsUnderTest);
+ }
+
+ @Test
public void testReadWritePackageRestrictionsAsync() {
final Settings settingsWrite = makeSettings();
final Settings settingsRead = makeSettings();
@@ -1811,6 +1827,14 @@ public class PackageManagerSettingsTests {
.getBytes());
}
+ private void writeCorruptedPackageRestrictions(final int userId) {
+ writeFile(new File(InstrumentationRegistry.getContext().getFilesDir(), "system/users/"
+ + userId + "/package-restrictions.xml"),
+ ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+ + "<package-restrictions>\n"
+ + " <pkg name=\"" + PACKAGE_NAME_1 + "\" ").getBytes());
+ }
+
private static void writeStoppedPackagesXml() {
writeFile(new File(InstrumentationRegistry.getContext().getFilesDir(), "system/packages-stopped.xml"),
( "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
diff --git a/services/tests/mockingservicestests/src/android/hardware/face/FaceManagerTest.java b/services/tests/mockingservicestests/src/android/hardware/face/FaceManagerTest.java
deleted file mode 100644
index f3feb0269598..000000000000
--- a/services/tests/mockingservicestests/src/android/hardware/face/FaceManagerTest.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.face;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.os.Looper;
-import android.os.RemoteException;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoJUnitRunner;
-import org.mockito.junit.MockitoRule;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@RunWith(MockitoJUnitRunner.class)
-public class FaceManagerTest {
- @Rule
- public final MockitoRule mockito = MockitoJUnit.rule();
-
- @Mock
- Context mContext;
- @Mock
- IFaceService mService;
-
- @Captor
- ArgumentCaptor<IFaceAuthenticatorsRegisteredCallback> mCaptor;
-
- List<FaceSensorPropertiesInternal> mProps;
- FaceManager mFaceManager;
-
- @Before
- public void setUp() throws Exception {
- when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
- mFaceManager = new FaceManager(mContext, mService);
- mProps = new ArrayList<>();
- mProps.add(new FaceSensorPropertiesInternal(
- 0 /* id */,
- FaceSensorProperties.STRENGTH_STRONG,
- 1 /* maxTemplatesAllowed */,
- new ArrayList<>() /* conponentInfo */,
- FaceSensorProperties.TYPE_UNKNOWN,
- true /* supportsFaceDetection */,
- true /* supportsSelfIllumination */,
- false /* resetLockoutRequiresChallenge */));
- }
-
- @Test
- public void getSensorPropertiesInternal_noBinderCalls() throws RemoteException {
- verify(mService).addAuthenticatorsRegisteredCallback(mCaptor.capture());
-
- mCaptor.getValue().onAllAuthenticatorsRegistered(mProps);
- List<FaceSensorPropertiesInternal> actual = mFaceManager.getSensorPropertiesInternal();
-
- assertThat(actual).isEqualTo(mProps);
- verify(mService, never()).getSensorPropertiesInternal(any());
- }
-}
diff --git a/services/tests/mockingservicestests/src/android/hardware/fingerprint/FingerprintManagerTest.java b/services/tests/mockingservicestests/src/android/hardware/fingerprint/FingerprintManagerTest.java
deleted file mode 100644
index 558202d51b27..000000000000
--- a/services/tests/mockingservicestests/src/android/hardware/fingerprint/FingerprintManagerTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.fingerprint;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.os.Looper;
-import android.os.RemoteException;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoJUnitRunner;
-import org.mockito.junit.MockitoRule;
-
-import java.util.ArrayList;
-import java.util.List;
-
-
-@RunWith(MockitoJUnitRunner.class)
-public class FingerprintManagerTest {
- @Rule
- public final MockitoRule mockito = MockitoJUnit.rule();
-
- @Mock
- Context mContext;
- @Mock
- IFingerprintService mService;
-
- @Captor
- ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mCaptor;
-
- List<FingerprintSensorPropertiesInternal> mProps;
- FingerprintManager mFingerprintManager;
-
- @Before
- public void setUp() throws Exception {
- when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
- mFingerprintManager = new FingerprintManager(mContext, mService);
- mProps = new ArrayList<>();
- mProps.add(new FingerprintSensorPropertiesInternal(
- 0 /* sensorId */,
- FingerprintSensorProperties.STRENGTH_STRONG,
- 1 /* maxEnrollmentsPerUser */,
- new ArrayList<>() /* componentInfo */,
- FingerprintSensorProperties.TYPE_UNKNOWN,
- true /* halControlsIllumination */,
- true /* resetLockoutRequiresHardwareAuthToken */,
- new ArrayList<>() /* sensorLocations */));
- }
-
- @Test
- public void getSensorPropertiesInternal_noBinderCalls() throws RemoteException {
- verify(mService).addAuthenticatorsRegisteredCallback(mCaptor.capture());
-
- mCaptor.getValue().onAllAuthenticatorsRegistered(mProps);
- List<FingerprintSensorPropertiesInternal> actual =
- mFingerprintManager.getSensorPropertiesInternal();
-
- assertThat(actual).isEqualTo(mProps);
- verify(mService, never()).getSensorPropertiesInternal(any());
- }
-}
diff --git a/services/tests/mockingservicestests/src/android/hardware/fingerprint/OWNERS b/services/tests/mockingservicestests/src/android/hardware/fingerprint/OWNERS
index 3edcf70d7e67..6a2192a2c7fb 100644
--- a/services/tests/mockingservicestests/src/android/hardware/fingerprint/OWNERS
+++ b/services/tests/mockingservicestests/src/android/hardware/fingerprint/OWNERS
@@ -1 +1 @@
-include /services/core/java/com/android/server/biometrics/OWNERS \ No newline at end of file
+include /services/core/java/com/android/server/biometrics/OWNERS
diff --git a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
index bcd69fda8c28..85820127d36c 100644
--- a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
@@ -86,6 +86,9 @@ import android.os.PowerManagerInternal;
import android.os.PowerSaveState;
import android.os.SystemClock;
import android.provider.DeviceConfig;
+import android.telephony.TelephonyCallback;
+import android.telephony.TelephonyManager;
+import android.telephony.emergency.EmergencyNumber;
import androidx.test.runner.AndroidJUnit4;
@@ -119,6 +122,8 @@ public class DeviceIdleControllerTest {
private AnyMotionDetectorForTest mAnyMotionDetector;
private AppStateTrackerForTest mAppStateTracker;
private DeviceIdleController.Constants mConstants;
+ private TelephonyCallback.OutgoingEmergencyCallListener mEmergencyCallListener;
+ private TelephonyCallback.CallStateListener mCallStateListener;
private InjectorForTest mInjector;
private MockitoSession mMockingSession;
@@ -140,6 +145,8 @@ public class DeviceIdleControllerTest {
private Sensor mMotionSensor;
@Mock
private SensorManager mSensorManager;
+ @Mock
+ private TelephonyManager mTelephonyManager;
class InjectorForTest extends DeviceIdleController.Injector {
ConnectivityManager connectivityManager;
@@ -232,6 +239,11 @@ public class DeviceIdleControllerTest {
}
@Override
+ TelephonyManager getTelephonyManager() {
+ return mTelephonyManager;
+ }
+
+ @Override
boolean useMotionSensor() {
return true;
}
@@ -343,6 +355,15 @@ public class DeviceIdleControllerTest {
// Get the same Constants object that mDeviceIdleController got.
mConstants = mInjector.getConstants(mDeviceIdleController);
+
+ final ArgumentCaptor<TelephonyCallback> telephonyCallbackCaptor =
+ ArgumentCaptor.forClass(TelephonyCallback.class);
+ verify(mTelephonyManager)
+ .registerTelephonyCallback(any(), telephonyCallbackCaptor.capture());
+ mEmergencyCallListener = (TelephonyCallback.OutgoingEmergencyCallListener)
+ telephonyCallbackCaptor.getValue();
+ mCallStateListener =
+ (TelephonyCallback.CallStateListener) telephonyCallbackCaptor.getValue();
}
@After
@@ -531,6 +552,16 @@ public class DeviceIdleControllerTest {
mDeviceIdleController.becomeInactiveIfAppropriateLocked();
verifyStateConditions(STATE_ACTIVE);
+
+ // All other conditions allow for going INACTIVE...
+ setAlarmSoon(false);
+ setChargingOn(false);
+ setScreenOn(false);
+ // ...except the emergency call.
+ setEmergencyCallActive(true);
+
+ mDeviceIdleController.becomeInactiveIfAppropriateLocked();
+ verifyStateConditions(STATE_ACTIVE);
}
@Test
@@ -559,6 +590,15 @@ public class DeviceIdleControllerTest {
mDeviceIdleController.becomeInactiveIfAppropriateLocked();
verifyLightStateConditions(LIGHT_STATE_ACTIVE);
+
+ // All other conditions allow for going INACTIVE...
+ setChargingOn(false);
+ setScreenOn(false);
+ // ...except the emergency call.
+ setEmergencyCallActive(true);
+
+ mDeviceIdleController.becomeInactiveIfAppropriateLocked();
+ verifyLightStateConditions(LIGHT_STATE_ACTIVE);
}
@Test
@@ -569,6 +609,7 @@ public class DeviceIdleControllerTest {
setAlarmSoon(false);
setChargingOn(false);
setScreenOn(false);
+ setEmergencyCallActive(false);
mDeviceIdleController.becomeInactiveIfAppropriateLocked();
verifyStateConditions(STATE_INACTIVE);
@@ -613,6 +654,7 @@ public class DeviceIdleControllerTest {
setChargingOn(false);
setScreenOn(false);
+ setEmergencyCallActive(false);
mDeviceIdleController.becomeInactiveIfAppropriateLocked();
verifyLightStateConditions(LIGHT_STATE_INACTIVE);
@@ -1147,6 +1189,22 @@ public class DeviceIdleControllerTest {
eq(true));
}
+ @Test
+ public void testEmergencyCallEndTriggersInactive() {
+ setAlarmSoon(false);
+ setChargingOn(false);
+ setScreenOn(false);
+ setEmergencyCallActive(true);
+
+ verifyStateConditions(STATE_ACTIVE);
+ verifyLightStateConditions(LIGHT_STATE_ACTIVE);
+
+ setEmergencyCallActive(false);
+
+ verifyStateConditions(STATE_INACTIVE);
+ verifyLightStateConditions(LIGHT_STATE_INACTIVE);
+ }
+
///////////////// EXIT conditions ///////////////////
@Test
@@ -2096,6 +2154,75 @@ public class DeviceIdleControllerTest {
.onDeviceStationaryChanged(eq(true));
}
+ @Test
+ public void testEmergencyEndsIdle() {
+ enterDeepState(STATE_ACTIVE);
+ setEmergencyCallActive(true);
+ verifyStateConditions(STATE_ACTIVE);
+
+ enterDeepState(STATE_INACTIVE);
+ setEmergencyCallActive(true);
+ verifyStateConditions(STATE_ACTIVE);
+
+ enterDeepState(STATE_IDLE_PENDING);
+ setEmergencyCallActive(true);
+ verifyStateConditions(STATE_ACTIVE);
+
+ enterDeepState(STATE_SENSING);
+ setEmergencyCallActive(true);
+ verifyStateConditions(STATE_ACTIVE);
+
+ enterDeepState(STATE_LOCATING);
+ setEmergencyCallActive(true);
+ verifyStateConditions(STATE_ACTIVE);
+
+ // Quick doze enabled or not shouldn't affect the end state.
+ enterDeepState(STATE_QUICK_DOZE_DELAY);
+ setQuickDozeEnabled(true);
+ setEmergencyCallActive(true);
+ verifyStateConditions(STATE_ACTIVE);
+
+ enterDeepState(STATE_QUICK_DOZE_DELAY);
+ setQuickDozeEnabled(false);
+ setEmergencyCallActive(true);
+ verifyStateConditions(STATE_ACTIVE);
+
+ enterDeepState(STATE_IDLE);
+ setEmergencyCallActive(true);
+ verifyStateConditions(STATE_ACTIVE);
+
+ enterDeepState(STATE_IDLE_MAINTENANCE);
+ setEmergencyCallActive(true);
+ verifyStateConditions(STATE_ACTIVE);
+ }
+
+ @Test
+ public void testEmergencyEndsLightIdle() {
+ enterLightState(LIGHT_STATE_ACTIVE);
+ setEmergencyCallActive(true);
+ verifyLightStateConditions(LIGHT_STATE_ACTIVE);
+
+ enterLightState(LIGHT_STATE_INACTIVE);
+ setEmergencyCallActive(true);
+ verifyLightStateConditions(LIGHT_STATE_ACTIVE);
+
+ enterLightState(LIGHT_STATE_WAITING_FOR_NETWORK);
+ setEmergencyCallActive(true);
+ verifyLightStateConditions(LIGHT_STATE_ACTIVE);
+
+ enterLightState(LIGHT_STATE_IDLE);
+ setEmergencyCallActive(true);
+ verifyLightStateConditions(LIGHT_STATE_ACTIVE);
+
+ enterLightState(LIGHT_STATE_IDLE_MAINTENANCE);
+ setEmergencyCallActive(true);
+ verifyLightStateConditions(LIGHT_STATE_ACTIVE);
+
+ enterLightState(LIGHT_STATE_OVERRIDE);
+ setEmergencyCallActive(true);
+ verifyLightStateConditions(LIGHT_STATE_ACTIVE);
+ }
+
private void enterDeepState(int state) {
switch (state) {
case STATE_ACTIVE:
@@ -2108,6 +2235,7 @@ public class DeviceIdleControllerTest {
setQuickDozeEnabled(true);
setScreenOn(false);
setChargingOn(false);
+ setEmergencyCallActive(false);
mDeviceIdleController.becomeInactiveIfAppropriateLocked();
break;
case STATE_LOCATING:
@@ -2128,6 +2256,7 @@ public class DeviceIdleControllerTest {
setQuickDozeEnabled(false);
setScreenOn(false);
setChargingOn(false);
+ setEmergencyCallActive(false);
mDeviceIdleController.becomeInactiveIfAppropriateLocked();
int count = 0;
while (mDeviceIdleController.getState() != state) {
@@ -2159,6 +2288,7 @@ public class DeviceIdleControllerTest {
enterLightState(LIGHT_STATE_ACTIVE);
setScreenOn(false);
setChargingOn(false);
+ setEmergencyCallActive(false);
int count = 0;
mDeviceIdleController.becomeInactiveIfAppropriateLocked();
while (mDeviceIdleController.getLightState() != lightState) {
@@ -2177,6 +2307,7 @@ public class DeviceIdleControllerTest {
case LIGHT_STATE_OVERRIDE:
setScreenOn(false);
setChargingOn(false);
+ setEmergencyCallActive(false);
mDeviceIdleController.setLightStateForTest(lightState);
break;
default:
@@ -2188,6 +2319,14 @@ public class DeviceIdleControllerTest {
mDeviceIdleController.updateChargingLocked(on);
}
+ private void setEmergencyCallActive(boolean active) {
+ if (active) {
+ mEmergencyCallListener.onOutgoingEmergencyCall(mock(EmergencyNumber.class), 0);
+ } else {
+ mCallStateListener.onCallStateChanged(TelephonyManager.CALL_STATE_IDLE);
+ }
+ }
+
private void setScreenLocked(boolean locked) {
mDeviceIdleController.keyguardShowingLocked(locked);
}
@@ -2235,6 +2374,7 @@ public class DeviceIdleControllerTest {
assertFalse(mDeviceIdleController.isCharging());
assertFalse(mDeviceIdleController.isScreenOn()
&& !mDeviceIdleController.isKeyguardShowing());
+ assertFalse(mDeviceIdleController.isEmergencyCallActive());
break;
case STATE_IDLE_PENDING:
assertEquals(
@@ -2244,6 +2384,7 @@ public class DeviceIdleControllerTest {
assertFalse(mDeviceIdleController.isCharging());
assertFalse(mDeviceIdleController.isScreenOn()
&& !mDeviceIdleController.isKeyguardShowing());
+ assertFalse(mDeviceIdleController.isEmergencyCallActive());
break;
case STATE_SENSING:
assertEquals(
@@ -2255,6 +2396,7 @@ public class DeviceIdleControllerTest {
assertFalse(mDeviceIdleController.isCharging());
assertFalse(mDeviceIdleController.isScreenOn()
&& !mDeviceIdleController.isKeyguardShowing());
+ assertFalse(mDeviceIdleController.isEmergencyCallActive());
break;
case STATE_LOCATING:
assertEquals(
@@ -2263,6 +2405,7 @@ public class DeviceIdleControllerTest {
assertFalse(mDeviceIdleController.isCharging());
assertFalse(mDeviceIdleController.isScreenOn()
&& !mDeviceIdleController.isKeyguardShowing());
+ assertFalse(mDeviceIdleController.isEmergencyCallActive());
break;
case STATE_IDLE:
if (mDeviceIdleController.hasMotionSensor()) {
@@ -2276,6 +2419,7 @@ public class DeviceIdleControllerTest {
&& !mDeviceIdleController.isKeyguardShowing());
// Light state should be OVERRIDE at this point.
verifyLightStateConditions(LIGHT_STATE_OVERRIDE);
+ assertFalse(mDeviceIdleController.isEmergencyCallActive());
break;
case STATE_IDLE_MAINTENANCE:
if (mDeviceIdleController.hasMotionSensor()) {
@@ -2287,6 +2431,7 @@ public class DeviceIdleControllerTest {
assertFalse(mDeviceIdleController.isCharging());
assertFalse(mDeviceIdleController.isScreenOn()
&& !mDeviceIdleController.isKeyguardShowing());
+ assertFalse(mDeviceIdleController.isEmergencyCallActive());
break;
case STATE_QUICK_DOZE_DELAY:
// If quick doze is enabled, the motion listener should NOT be active.
@@ -2295,6 +2440,7 @@ public class DeviceIdleControllerTest {
assertFalse(mDeviceIdleController.isCharging());
assertFalse(mDeviceIdleController.isScreenOn()
&& !mDeviceIdleController.isKeyguardShowing());
+ assertFalse(mDeviceIdleController.isEmergencyCallActive());
break;
default:
fail("Conditions for " + stateToString(expectedState) + " unknown.");
@@ -2312,6 +2458,7 @@ public class DeviceIdleControllerTest {
case LIGHT_STATE_ACTIVE:
assertTrue(
mDeviceIdleController.isCharging() || mDeviceIdleController.isScreenOn()
+ || mDeviceIdleController.isEmergencyCallActive()
// Or there's an alarm coming up soon.
|| SystemClock.elapsedRealtime() + mConstants.MIN_TIME_TO_ALARM
> mAlarmManager.getNextWakeFromIdleTime());
@@ -2324,6 +2471,7 @@ public class DeviceIdleControllerTest {
assertFalse(mDeviceIdleController.isCharging());
assertFalse(mDeviceIdleController.isScreenOn()
&& !mDeviceIdleController.isKeyguardShowing());
+ assertFalse(mDeviceIdleController.isEmergencyCallActive());
break;
default:
fail("Conditions for " + lightStateToString(expectedLightState) + " unknown.");
diff --git a/services/tests/mockingservicestests/src/com/android/server/ExpectableTestCase.java b/services/tests/mockingservicestests/src/com/android/server/ExpectableTestCase.java
new file mode 100644
index 000000000000..a329f5a14477
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/ExpectableTestCase.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server;
+
+import com.google.common.annotations.GwtIncompatible;
+import com.google.common.base.Optional;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Multiset;
+import com.google.common.collect.Table;
+import com.google.common.truth.BigDecimalSubject;
+import com.google.common.truth.BooleanSubject;
+import com.google.common.truth.ClassSubject;
+import com.google.common.truth.ComparableSubject;
+import com.google.common.truth.DoubleSubject;
+import com.google.common.truth.Expect;
+import com.google.common.truth.FloatSubject;
+import com.google.common.truth.GuavaOptionalSubject;
+import com.google.common.truth.IntegerSubject;
+import com.google.common.truth.IterableSubject;
+import com.google.common.truth.LongSubject;
+import com.google.common.truth.MapSubject;
+import com.google.common.truth.MultimapSubject;
+import com.google.common.truth.MultisetSubject;
+import com.google.common.truth.ObjectArraySubject;
+import com.google.common.truth.PrimitiveBooleanArraySubject;
+import com.google.common.truth.PrimitiveByteArraySubject;
+import com.google.common.truth.PrimitiveCharArraySubject;
+import com.google.common.truth.PrimitiveDoubleArraySubject;
+import com.google.common.truth.PrimitiveFloatArraySubject;
+import com.google.common.truth.PrimitiveIntArraySubject;
+import com.google.common.truth.PrimitiveLongArraySubject;
+import com.google.common.truth.PrimitiveShortArraySubject;
+import com.google.common.truth.StandardSubjectBuilder;
+import com.google.common.truth.StringSubject;
+import com.google.common.truth.Subject;
+import com.google.common.truth.TableSubject;
+import com.google.common.truth.ThrowableSubject;
+
+import org.junit.Rule;
+
+import java.math.BigDecimal;
+import java.util.Map;
+
+// NOTE: it could be a more generic AbstractTruthTestCase that provide similar methods
+// for assertThat() / assertWithMessage(), but then we'd need to remove all static import imports
+// from classes that indirectly extend it.
+/**
+ * Base class to make it easier to use {@code Truth} {@link Expect} assertions.
+ */
+public abstract class ExpectableTestCase {
+
+ @Rule
+ public final Expect mExpect = Expect.create();
+
+ protected final StandardSubjectBuilder expectWithMessage(String msg) {
+ return mExpect.withMessage(msg);
+ }
+
+ protected final StandardSubjectBuilder expectWithMessage(String format, Object...args) {
+ return mExpect.withMessage(format, args);
+ }
+
+ protected final <ComparableT extends Comparable<?>> ComparableSubject<ComparableT> expectThat(
+ ComparableT actual) {
+ return mExpect.that(actual);
+ }
+
+ protected final BigDecimalSubject expectThat(BigDecimal actual) {
+ return mExpect.that(actual);
+ }
+
+ protected final Subject expectThat(Object actual) {
+ return mExpect.that(actual);
+ }
+
+ @GwtIncompatible("ClassSubject.java")
+ protected final ClassSubject expectThat(Class<?> actual) {
+ return mExpect.that(actual);
+ }
+
+ protected final ThrowableSubject expectThat(Throwable actual) {
+ return mExpect.that(actual);
+ }
+
+ protected final LongSubject expectThat(Long actual) {
+ return mExpect.that(actual);
+ }
+
+ protected final DoubleSubject expectThat(Double actual) {
+ return mExpect.that(actual);
+ }
+
+ protected final FloatSubject expectThat(Float actual) {
+ return mExpect.that(actual);
+ }
+
+ protected final IntegerSubject expectThat(Integer actual) {
+ return mExpect.that(actual);
+ }
+
+ protected final BooleanSubject expectThat(Boolean actual) {
+ return mExpect.that(actual);
+ }
+
+ protected final StringSubject expectThat(String actual) {
+ return mExpect.that(actual);
+ }
+
+ protected final IterableSubject expectThat(Iterable<?> actual) {
+ return mExpect.that(actual);
+ }
+
+ protected final <T> ObjectArraySubject<T> expectThat(T[] actual) {
+ return mExpect.that(actual);
+ }
+
+ protected final PrimitiveBooleanArraySubject expectThat(boolean[] actual) {
+ return mExpect.that(actual);
+ }
+
+ protected final PrimitiveShortArraySubject expectThat(short[] actual) {
+ return mExpect.that(actual);
+ }
+
+ protected final PrimitiveIntArraySubject expectThat(int[] actual) {
+ return mExpect.that(actual);
+ }
+
+ protected final PrimitiveLongArraySubject expectThat(long[] actual) {
+ return mExpect.that(actual);
+ }
+
+ protected final PrimitiveCharArraySubject expectThat(char[] actual) {
+ return mExpect.that(actual);
+ }
+
+ protected final PrimitiveByteArraySubject expectThat(byte[] actual) {
+ return mExpect.that(actual);
+ }
+
+ protected final PrimitiveFloatArraySubject expectThat(float[] actual) {
+ return mExpect.that(actual);
+ }
+
+ protected final PrimitiveDoubleArraySubject expectThat(double[] actual) {
+ return mExpect.that(actual);
+ }
+
+ protected final GuavaOptionalSubject expectThat(Optional<?> actual) {
+ return mExpect.that(actual);
+ }
+
+ protected final MapSubject expectThat(Map<?, ?> actual) {
+ return mExpect.that(actual);
+ }
+
+ protected final MultimapSubject expectThat(Multimap<?, ?> actual) {
+ return mExpect.that(actual);
+ }
+
+ protected final MultisetSubject expectThat(Multiset<?> actual) {
+ return mExpect.that(actual);
+ }
+
+ protected final TableSubject expectThat(Table<?, ?, ?> actual) {
+ return mExpect.that(actual);
+ }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/ExtendedMockitoRule.java b/services/tests/mockingservicestests/src/com/android/server/ExtendedMockitoRule.java
new file mode 100644
index 000000000000..881dd504428d
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/ExtendedMockitoRule.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.annotation.Nullable;
+import android.util.Log;
+
+import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder;
+import com.android.internal.util.Preconditions;
+import com.android.modules.utils.testing.StaticMockFixture;
+import com.android.modules.utils.testing.StaticMockFixtureRule;
+
+import org.mockito.Mockito;
+import org.mockito.quality.Strictness;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Rule to make it easier to use Extended Mockito.
+ *
+ * <p>It's derived from {@link StaticMockFixtureRule}, with the additional features:
+ *
+ * <ul>
+ * <li>Easier to define which classes must be statically mocked or spied
+ * <li>Automatically starts mocking (so tests don't need a mockito runner or rule)
+ * <li>Automatically clears the inlined mocks at the end (to avoid OOM)
+ * <li>Allows other customization like strictness
+ * </ul>
+ */
+public final class ExtendedMockitoRule extends StaticMockFixtureRule {
+
+ private static final String TAG = ExtendedMockitoRule.class.getSimpleName();
+
+ private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+
+ private final Object mTestClassInstance;
+ private final Strictness mStrictness;
+
+ private ExtendedMockitoRule(Builder builder) {
+ super(() -> new SimpleStatickMockFixture(builder.mMockedStaticClasses,
+ builder.mSpiedStaticClasses, builder.mDynamicSessionBuilderConfigurator,
+ builder.mAfterSessionFinishedCallback));
+ mTestClassInstance = builder.mTestClassInstance;
+ mStrictness = builder.mStrictness;
+ if (VERBOSE) {
+ Log.v(TAG, "strictness=" + mStrictness + ", testClassInstance" + mTestClassInstance
+ + ", mockedStaticClasses=" + builder.mMockedStaticClasses
+ + ", spiedStaticClasses=" + builder.mSpiedStaticClasses
+ + ", dynamicSessionBuilderConfigurator="
+ + builder.mDynamicSessionBuilderConfigurator
+ + ", afterSessionFinishedCallback=" + builder.mAfterSessionFinishedCallback);
+ }
+ }
+
+ @Override
+ public StaticMockitoSessionBuilder getSessionBuilder() {
+ StaticMockitoSessionBuilder sessionBuilder = super.getSessionBuilder();
+ if (mStrictness != null) {
+ if (VERBOSE) {
+ Log.v(TAG, "Setting strictness to " + mStrictness + " on " + sessionBuilder);
+ }
+ sessionBuilder.strictness(mStrictness);
+ }
+ return sessionBuilder.initMocks(mTestClassInstance);
+ }
+
+ public static final class Builder {
+ private final Object mTestClassInstance;
+ private @Nullable Strictness mStrictness;
+ private final List<Class<?>> mMockedStaticClasses = new ArrayList<>();
+ private final List<Class<?>> mSpiedStaticClasses = new ArrayList<>();
+ private @Nullable Visitor<StaticMockitoSessionBuilder> mDynamicSessionBuilderConfigurator;
+ private @Nullable Runnable mAfterSessionFinishedCallback;
+
+ public Builder(Object testClassInstance) {
+ mTestClassInstance = Objects.requireNonNull(testClassInstance);
+ }
+
+ public Builder setStrictness(Strictness strictness) {
+ mStrictness = Objects.requireNonNull(strictness);
+ return this;
+ }
+
+ public Builder mockStatic(Class<?> clazz) {
+ Objects.requireNonNull(clazz);
+ Preconditions.checkState(!mMockedStaticClasses.contains(clazz),
+ "class %s already mocked", clazz);
+ mMockedStaticClasses.add(clazz);
+ return this;
+ }
+
+ public Builder spyStatic(Class<?> clazz) {
+ Objects.requireNonNull(clazz);
+ Preconditions.checkState(!mSpiedStaticClasses.contains(clazz),
+ "class %s already spied", clazz);
+ mSpiedStaticClasses.add(clazz);
+ return this;
+ }
+
+ public Builder dynamiclyConfigureSessionBuilder(
+ Visitor<StaticMockitoSessionBuilder> dynamicSessionBuilderConfigurator) {
+ mDynamicSessionBuilderConfigurator = Objects
+ .requireNonNull(dynamicSessionBuilderConfigurator);
+ return this;
+ }
+
+ public Builder afterSessionFinished(Runnable runnable) {
+ mAfterSessionFinishedCallback = Objects.requireNonNull(runnable);
+ return this;
+ }
+
+ public ExtendedMockitoRule build() {
+ return new ExtendedMockitoRule(this);
+ }
+ }
+
+ private static final class SimpleStatickMockFixture implements StaticMockFixture {
+
+ private final List<Class<?>> mMockedStaticClasses;
+ private final List<Class<?>> mSpiedStaticClasses;
+ @Nullable
+ private final Visitor<StaticMockitoSessionBuilder> mDynamicSessionBuilderConfigurator;
+ @Nullable
+ private final Runnable mAfterSessionFinishedCallback;
+
+ private SimpleStatickMockFixture(List<Class<?>> mockedStaticClasses,
+ List<Class<?>> spiedStaticClasses,
+ @Nullable Visitor<StaticMockitoSessionBuilder> dynamicSessionBuilderConfigurator,
+ @Nullable Runnable afterSessionFinishedCallback) {
+ mMockedStaticClasses = mockedStaticClasses;
+ mSpiedStaticClasses = spiedStaticClasses;
+ mDynamicSessionBuilderConfigurator = dynamicSessionBuilderConfigurator;
+ mAfterSessionFinishedCallback = afterSessionFinishedCallback;
+ }
+
+ @Override
+ public StaticMockitoSessionBuilder setUpMockedClasses(
+ StaticMockitoSessionBuilder sessionBuilder) {
+ mMockedStaticClasses.forEach((c) -> sessionBuilder.mockStatic(c));
+ mSpiedStaticClasses.forEach((c) -> sessionBuilder.spyStatic(c));
+ if (mDynamicSessionBuilderConfigurator != null) {
+ mDynamicSessionBuilderConfigurator.visit(sessionBuilder);
+ }
+ return sessionBuilder;
+ }
+
+ @Override
+ public void setUpMockBehaviors() {
+ }
+
+ @Override
+ public void tearDown() {
+ try {
+ if (mAfterSessionFinishedCallback != null) {
+ mAfterSessionFinishedCallback.run();
+ }
+ } finally {
+ if (VERBOSE) {
+ Log.v(TAG, "calling Mockito.framework().clearInlineMocks()");
+ }
+ // When using inline mock maker, clean up inline mocks to prevent OutOfMemory
+ // errors. See https://github.com/mockito/mockito/issues/1614 and b/259280359.
+ Mockito.framework().clearInlineMocks();
+ }
+ }
+ }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/ExtendedMockitoTestCase.java b/services/tests/mockingservicestests/src/com/android/server/ExtendedMockitoTestCase.java
deleted file mode 100644
index 48483a14a8a0..000000000000
--- a/services/tests/mockingservicestests/src/com/android/server/ExtendedMockitoTestCase.java
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.server;
-
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
-
-import android.annotation.Nullable;
-import android.util.Log;
-
-import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder;
-
-import com.google.common.truth.Expect;
-import com.google.common.truth.StandardSubjectBuilder;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.rules.RuleChain;
-import org.mockito.Mockito;
-import org.mockito.MockitoSession;
-import org.mockito.quality.Strictness;
-
-import java.lang.reflect.Constructor;
-
-/**
- * Base class to make it easier to write tests that uses {@code ExtendedMockito}.
- *
- */
-public abstract class ExtendedMockitoTestCase {
-
- private static final String TAG = ExtendedMockitoTestCase.class.getSimpleName();
-
- private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
-
- /**
- * Number of invocations, used to force a failure on {@link #forceFailure(int, Class, String)}.
- */
- private static int sInvocationsCounter;
-
- /**
- * Sessions follow the "Highlander Rule": There can be only one!
- *
- * <p>So, we keep track of that and force-close it if needed.
- */
- @Nullable
- private static MockitoSession sHighlanderSession;
-
- /**
- * Points to where the current session was created.
- */
- private static Exception sSessionCreationLocation;
-
- private MockitoSession mSession;
-
- protected final Expect mExpect = Expect.create();
- protected final DumpableDumperRule mDumpableDumperRule = new DumpableDumperRule();
-
- @Rule
- public final RuleChain mTwoRingsOfPowerAndOneChainToRuleThemAll = RuleChain
- .outerRule(mDumpableDumperRule)
- .around(mExpect);
-
- public ExtendedMockitoTestCase() {
- sInvocationsCounter++;
- }
-
- @Before
- public final void startSession() {
- if (VERBOSE) {
- Log.v(TAG, "startSession() for " + getTestName() + " on thread "
- + Thread.currentThread() + "; sHighlanderSession=" + sHighlanderSession);
- }
- createSessionLocation();
- finishHighlanderSessionIfNeeded("startSession()");
- StaticMockitoSessionBuilder builder = mockitoSession()
- .initMocks(this)
- .strictness(getSessionStrictness());
- initializeSession(builder);
- sHighlanderSession = mSession = builder.startMocking();
- }
-
- private void createSessionLocation() {
- try {
- sSessionCreationLocation = new Exception(getTestName());
- } catch (Exception e) {
- // Better safe than sorry...
- Log.e(TAG, "Could not create sSessionCreationLocation with " + getTestName()
- + " on thread " + Thread.currentThread(), e);
- sSessionCreationLocation = e;
- }
- }
-
- /**
- * Gets the session strictness.
- *
- * @return {@link Strictness.LENIENT} by default; subclasses can override.
- */
- protected Strictness getSessionStrictness() {
- return Strictness.LENIENT;
- }
-
- /**
- * Initializes the mockito session.
- *
- * <p>Typically used to define which classes should have static methods mocked or spied.
- */
- protected void initializeSession(StaticMockitoSessionBuilder builder) {
- if (VERBOSE) {
- Log.v(TAG, "initializeSession()");
- }
- }
-
- @After
- public final void finishSession() throws Exception {
- if (false) { // For obvious reasons, should NEVER be merged as true
- forceFailure(1, RuntimeException.class, "to simulate an unfinished session");
- }
-
- // mSession.finishMocking() must ALWAYS be called (hence the over-protective try/finally
- // statements), otherwise it would cause failures on future tests as mockito
- // cannot start a session when a previous one is not finished
- try {
- if (VERBOSE) {
- Log.v(TAG, "finishSession() for " + getTestName() + " on thread "
- + Thread.currentThread() + "; sHighlanderSession=" + sHighlanderSession);
-
- }
- } finally {
- sHighlanderSession = null;
- finishSessionMocking();
- afterSessionFinished();
- }
- }
-
- /**
- * Called after the mockito session was finished
- *
- * <p>This method should be used by subclasses that MUST do their cleanup after the session is
- * finished (as methods marked with {@link After} in the subclasses would be called BEFORE
- * that).
- */
- protected void afterSessionFinished() {
- if (VERBOSE) {
- Log.v(TAG, "afterSessionFinished()");
- }
- }
-
- private void finishSessionMocking() {
- if (mSession == null) {
- Log.w(TAG, getClass().getSimpleName() + ".finishSession(): no session");
- return;
- }
- try {
- mSession.finishMocking();
- } finally {
- // Shouldn't need to set mSession to null as JUnit always instantiate a new object,
- // but it doesn't hurt....
- mSession = null;
- // When using inline mock maker, clean up inline mocks to prevent OutOfMemory
- // errors. See https://github.com/mockito/mockito/issues/1614 and b/259280359.
- Mockito.framework().clearInlineMocks();
- }
- }
-
- private void finishHighlanderSessionIfNeeded(String where) {
- if (sHighlanderSession == null) {
- if (VERBOSE) {
- Log.v(TAG, "finishHighlanderSessionIfNeeded(): sHighlanderSession already null");
- }
- return;
- }
-
- if (sSessionCreationLocation != null) {
- if (VERBOSE) {
- Log.e(TAG, where + ": There can be only one! Closing unfinished session, "
- + "created at", sSessionCreationLocation);
- } else {
- Log.e(TAG, where + ": There can be only one! Closing unfinished session, "
- + "created at " + sSessionCreationLocation);
- }
- } else {
- Log.e(TAG, where + ": There can be only one! Closing unfinished session created at "
- + "unknown location");
- }
- try {
- sHighlanderSession.finishMocking();
- } catch (Throwable t) {
- if (VERBOSE) {
- Log.e(TAG, "Failed to close unfinished session on " + getTestName(), t);
- } else {
- Log.e(TAG, "Failed to close unfinished session on " + getTestName() + ": " + t);
- }
- } finally {
- if (VERBOSE) {
- Log.v(TAG, "Resetting sHighlanderSession at finishHighlanderSessionIfNeeded()");
- }
- sHighlanderSession = null;
- }
- }
-
- /**
- * Forces a failure at the given invocation of a test method by throwing an exception.
- */
- protected final <T extends Throwable> void forceFailure(int invocationCount,
- Class<T> failureClass, String reason) throws T {
- if (sInvocationsCounter != invocationCount) {
- Log.d(TAG, "forceFailure(" + invocationCount + "): no-op on invocation #"
- + sInvocationsCounter);
- return;
- }
- String message = "Throwing on invocation #" + sInvocationsCounter + ": " + reason;
- Log.e(TAG, message);
- T throwable;
- try {
- Constructor<T> constructor = failureClass.getConstructor(String.class);
- throwable = constructor.newInstance("Throwing on invocation #" + sInvocationsCounter
- + ": " + reason);
- } catch (Exception e) {
- throw new IllegalArgumentException("Could not create exception of class " + failureClass
- + " using msg='" + message + "' as constructor");
- }
- throw throwable;
- }
-
- protected final @Nullable String getTestName() {
- return mDumpableDumperRule.getTestName();
- }
-
- protected final StandardSubjectBuilder expectWithMessage(String msg) {
- return mExpect.withMessage(msg);
- }
-
- protected final StandardSubjectBuilder expectWithMessage(String format, Object...args) {
- return mExpect.withMessage(format, args);
- }
-}
diff --git a/services/tests/mockingservicestests/src/com/android/server/Visitor.java b/services/tests/mockingservicestests/src/com/android/server/Visitor.java
new file mode 100644
index 000000000000..447910eba60b
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/Visitor.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2023 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;
+
+/**
+ * Generic visitor.
+ */
+public interface Visitor<V> {
+ void visit(V visitee);
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
index 9dd2f82ad59b..b395f42478b1 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
@@ -159,7 +159,6 @@ import android.util.SparseArray;
import androidx.test.runner.AndroidJUnit4;
import com.android.dx.mockito.inline.extended.MockedVoidMethod;
-import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsService;
@@ -168,7 +167,7 @@ import com.android.server.AlarmManagerInternal;
import com.android.server.AppStateTracker;
import com.android.server.AppStateTrackerImpl;
import com.android.server.DeviceIdleInternal;
-import com.android.server.ExtendedMockitoTestCase;
+import com.android.server.ExtendedMockitoRule;
import com.android.server.LocalServices;
import com.android.server.SystemClockTime.TimeConfidence;
import com.android.server.SystemService;
@@ -182,6 +181,7 @@ import com.android.server.usage.AppStandbyInternal;
import libcore.util.EmptyArray;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
@@ -204,7 +204,7 @@ import java.util.function.LongConsumer;
@Presubmit
@SuppressWarnings("GuardedBy") // This test enforces synchronous behavior.
@RunWith(AndroidJUnit4.class)
-public final class AlarmManagerServiceTest extends ExtendedMockitoTestCase {
+public final class AlarmManagerServiceTest {
private static final String TAG = AlarmManagerServiceTest.class.getSimpleName();
private static final int SYSTEM_UI_UID = 12345;
private static final int TEST_CALLING_USER = UserHandle.getUserId(TEST_CALLING_UID);
@@ -411,14 +411,9 @@ public final class AlarmManagerServiceTest extends ExtendedMockitoTestCase {
}
}
- @Override
- protected Strictness getSessionStrictness() {
- return Strictness.WARN;
- }
-
- @Override
- protected void initializeSession(StaticMockitoSessionBuilder builder) {
- builder
+ @Rule
+ public final ExtendedMockitoRule mExtendedMockitoRule = new ExtendedMockitoRule.Builder(this)
+ .setStrictness(Strictness.WARN)
.spyStatic(ActivityManager.class)
.mockStatic(CompatChanges.class)
.spyStatic(DateFormat.class)
@@ -431,8 +426,10 @@ public final class AlarmManagerServiceTest extends ExtendedMockitoTestCase {
.mockStatic(ServiceManager.class)
.mockStatic(Settings.Global.class)
.mockStatic(SystemProperties.class)
- .spyStatic(UserHandle.class);
- }
+ .spyStatic(UserHandle.class)
+ .afterSessionFinished(
+ () -> LocalServices.removeServiceForTest(AlarmManagerInternal.class))
+ .build();
@Before
public final void setUp() {
@@ -3805,9 +3802,4 @@ public final class AlarmManagerServiceTest extends ExtendedMockitoTestCase {
mListener.removeListenerAlarmsForCachedUid(TEST_CALLING_UID_2);
assertEquals(2, mService.mAlarmsPerUid.get(TEST_CALLING_UID_2));
}
-
- @Override
- public void afterSessionFinished() {
- LocalServices.removeServiceForTest(AlarmManagerInternal.class);
- }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceInjectorTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceInjectorTest.java
index e01a9a9d473a..9ceb5e7b018d 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceInjectorTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceInjectorTest.java
@@ -31,11 +31,11 @@ import android.os.UserManager;
import android.util.Log;
import android.view.Display;
-import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder;
-import com.android.server.ExtendedMockitoTestCase;
+import com.android.server.ExtendedMockitoRule;
import com.android.server.am.ActivityManagerService.Injector;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
@@ -45,7 +45,7 @@ import java.util.Arrays;
* Run as {@code atest
* FrameworksMockingServicesTests:com.android.server.am.ActivityManagerServiceInjectorTest}
*/
-public final class ActivityManagerServiceInjectorTest extends ExtendedMockitoTestCase {
+public final class ActivityManagerServiceInjectorTest {
private static final String TAG = ActivityManagerServiceInjectorTest.class.getSimpleName();
@@ -63,10 +63,10 @@ public final class ActivityManagerServiceInjectorTest extends ExtendedMockitoTes
when(mContext.getSystemService(DisplayManager.class)).thenReturn(mDisplayManager);
}
- @Override
- protected void initializeSession(StaticMockitoSessionBuilder builder) {
- builder.spyStatic(UserManager.class);
- }
+ @Rule
+ public final ExtendedMockitoRule mExtendedMockitoRule = new ExtendedMockitoRule.Builder(this)
+ .spyStatic(UserManager.class)
+ .build();
@Test
public void testGetDisplayIdsForStartingBackgroundUsers_notSupported() {
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
index dcdee37059a9..99da415380cd 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
@@ -78,18 +78,15 @@ import android.util.Pair;
import androidx.test.filters.SmallTest;
-import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder;
import com.android.internal.util.FrameworkStatsLog;
-import com.android.server.ExtendedMockitoTestCase;
+import com.android.server.ExtendedMockitoRule;
import com.android.server.am.BroadcastQueueTest.SyncBarrier;
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
-import org.junit.runner.RunWith;
import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.mockito.junit.MockitoJUnitRunner;
import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
@@ -98,8 +95,7 @@ import java.util.ArrayList;
import java.util.List;
@SmallTest
-@RunWith(MockitoJUnitRunner.class)
-public class BroadcastQueueModernImplTest extends ExtendedMockitoTestCase {
+public final class BroadcastQueueModernImplTest {
private static final int TEST_UID = android.os.Process.FIRST_APPLICATION_UID;
private static final int TEST_UID2 = android.os.Process.FIRST_APPLICATION_UID + 1;
@@ -118,15 +114,13 @@ public class BroadcastQueueModernImplTest extends ExtendedMockitoTestCase {
BroadcastProcessQueue mHead;
- @Override
- protected void initializeSession(StaticMockitoSessionBuilder builder) {
- builder.spyStatic(FrameworkStatsLog.class);
- }
+ @Rule
+ public final ExtendedMockitoRule mExtendedMockitoRule = new ExtendedMockitoRule.Builder(this)
+ .spyStatic(FrameworkStatsLog.class)
+ .build();
@Before
public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
-
mHandlerThread = new HandlerThread(getClass().getSimpleName());
mHandlerThread.start();
@@ -765,40 +759,6 @@ public class BroadcastQueueModernImplTest extends ExtendedMockitoTestCase {
}
/**
- * Verify that sending a broadcast that removes any matching pending
- * broadcasts is applied as expected.
- */
- @Test
- public void testRemoveMatchingFilter() {
- final Intent screenOn = new Intent(Intent.ACTION_SCREEN_ON);
- final BroadcastOptions optionsOn = BroadcastOptions.makeBasic();
- optionsOn.setRemoveMatchingFilter(new IntentFilter(Intent.ACTION_SCREEN_OFF));
-
- final Intent screenOff = new Intent(Intent.ACTION_SCREEN_OFF);
- final BroadcastOptions optionsOff = BroadcastOptions.makeBasic();
- optionsOff.setRemoveMatchingFilter(new IntentFilter(Intent.ACTION_SCREEN_ON));
-
- // Halt all processing so that we get a consistent view
- mHandlerThread.getLooper().getQueue().postSyncBarrier();
-
- mImpl.enqueueBroadcastLocked(makeBroadcastRecord(screenOn, optionsOn));
- mImpl.enqueueBroadcastLocked(makeBroadcastRecord(screenOff, optionsOff));
- mImpl.enqueueBroadcastLocked(makeBroadcastRecord(screenOn, optionsOn));
- mImpl.enqueueBroadcastLocked(makeBroadcastRecord(screenOff, optionsOff));
-
- // While we're here, give our health check some test coverage
- mImpl.checkHealthLocked();
-
- // Marching through the queue we should only have one SCREEN_OFF
- // broadcast, since that's the last state we dispatched
- final BroadcastProcessQueue queue = mImpl.getProcessQueue(PACKAGE_GREEN,
- getUidForPackage(PACKAGE_GREEN));
- queue.makeActiveNextPending();
- assertEquals(Intent.ACTION_SCREEN_OFF, queue.getActive().intent.getAction());
- assertTrue(queue.isEmpty());
- }
-
- /**
* Verify that sending a broadcast with DELIVERY_GROUP_POLICY_MOST_RECENT works as expected.
*/
@Test
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
index 3fd0e072809f..ec9e5b50579c 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
@@ -17,9 +17,12 @@
package com.android.server.am;
import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+
import static com.android.server.am.ActivityManagerService.Injector;
import static com.android.server.am.CachedAppOptimizer.compactActionIntToAction;
+
import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
@@ -34,27 +37,29 @@ import android.os.Process;
import android.platform.test.annotations.Presubmit;
import android.provider.DeviceConfig;
import android.text.TextUtils;
+
import androidx.test.platform.app.InstrumentationRegistry;
+
import com.android.modules.utils.testing.TestableDeviceConfig;
+import com.android.server.ExtendedMockitoRule;
import com.android.server.LocalServices;
import com.android.server.ServiceThread;
import com.android.server.appop.AppOpsService;
import com.android.server.wm.ActivityTaskManagerService;
-import java.io.File;
-import java.io.IOException;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
+
import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
-import org.junit.runner.RunWith;
import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnitRunner;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
/**
* Tests for {@link CachedAppOptimizer}.
@@ -63,9 +68,6 @@ import org.mockito.junit.MockitoJUnitRunner;
* atest FrameworksMockingServicesTests:CachedAppOptimizerTest
*/
@Presubmit
-@RunWith(MockitoJUnitRunner.class)
-@Ignore("TODO(b/226641572): this test is broken and it cannot use ExtendedMockitoTestCase as it "
- + "uses TestableDeviceConfigRule, which creates its own mockito session")
public final class CachedAppOptimizerTest {
private ServiceThread mThread;
@@ -84,16 +86,22 @@ public final class CachedAppOptimizerTest {
@Mock
private PackageManagerInternal mPackageManagerInt;
- @Rule
- public final TestableDeviceConfig.TestableDeviceConfigRule
- mDeviceConfigRule = new TestableDeviceConfig.TestableDeviceConfigRule();
+ private final TestableDeviceConfig mDeviceConfig = new TestableDeviceConfig();
+
@Rule
public final ApplicationExitInfoTest.ServiceThreadRule
mServiceThreadRule = new ApplicationExitInfoTest.ServiceThreadRule();
+ @Rule
+ public final ExtendedMockitoRule mExtendedMockitoRule = new ExtendedMockitoRule.Builder(this)
+ .dynamiclyConfigureSessionBuilder(
+ sessionBuilder -> mDeviceConfig.setUpMockedClasses(sessionBuilder))
+ .build();
+
@Before
public void setUp() {
System.loadLibrary("mockingservicestestjni");
+ mDeviceConfig.setUpMockBehaviors();
mHandlerThread = new HandlerThread("");
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper());
@@ -124,6 +132,7 @@ public final class CachedAppOptimizerTest {
mHandlerThread.quit();
mThread.quit();
mCountDown = null;
+ mDeviceConfig.tearDown();
}
private ProcessRecord makeProcessRecord(int pid, int uid, int packageUid, String processName,
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index dc7f3cdc1f7f..0b4c70c285c1 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -143,8 +143,8 @@ public class MockingOomAdjusterTests {
private static final String MOCKAPP5_PROCESSNAME = "test #5";
private static final String MOCKAPP5_PACKAGENAME = "com.android.test.test5";
private static final int MOCKAPP2_UID_OTHER = MOCKAPP2_UID + UserHandle.PER_USER_RANGE;
- private static final int FIRST_CACHED_ADJ = ProcessList.CACHED_APP_MIN_ADJ
- + ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
+ private static int sFirstCachedAdj = ProcessList.CACHED_APP_MIN_ADJ
+ + ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
private static Context sContext;
private static PackageManagerInternal sPackageManagerInternal;
private static ActivityManagerService sService;
@@ -208,6 +208,9 @@ public class MockingOomAdjusterTests {
new ActiveUids(sService, false));
sService.mOomAdjuster.mAdjSeq = 10000;
sService.mWakefulness = new AtomicInteger(PowerManagerInternal.WAKEFULNESS_AWAKE);
+ if (sService.mConstants.USE_TIERED_CACHED_ADJ) {
+ sFirstCachedAdj = ProcessList.CACHED_APP_MIN_ADJ + 10;
+ }
}
@AfterClass
@@ -834,7 +837,7 @@ public class MockingOomAdjusterTests {
updateOomAdj(client, app);
doReturn(null).when(sService).getTopApp();
- assertProcStates(app, PROCESS_STATE_SERVICE, FIRST_CACHED_ADJ, SCHED_GROUP_BACKGROUND);
+ assertProcStates(app, PROCESS_STATE_SERVICE, sFirstCachedAdj, SCHED_GROUP_BACKGROUND);
}
@SuppressWarnings("GuardedBy")
@@ -882,7 +885,7 @@ public class MockingOomAdjusterTests {
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
updateOomAdj(app);
- assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, FIRST_CACHED_ADJ, SCHED_GROUP_BACKGROUND);
+ assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, sFirstCachedAdj, SCHED_GROUP_BACKGROUND);
}
@SuppressWarnings("GuardedBy")
@@ -1286,7 +1289,7 @@ public class MockingOomAdjusterTests {
bindProvider(app, app, null, null, false);
updateOomAdj(app);
- assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, FIRST_CACHED_ADJ, SCHED_GROUP_BACKGROUND);
+ assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, sFirstCachedAdj, SCHED_GROUP_BACKGROUND);
}
@SuppressWarnings("GuardedBy")
@@ -1301,7 +1304,7 @@ public class MockingOomAdjusterTests {
sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
updateOomAdj(app, client);
- assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, FIRST_CACHED_ADJ, SCHED_GROUP_BACKGROUND);
+ assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, sFirstCachedAdj, SCHED_GROUP_BACKGROUND);
}
@SuppressWarnings("GuardedBy")
@@ -1965,6 +1968,36 @@ public class MockingOomAdjusterTests {
@SuppressWarnings("GuardedBy")
@Test
+ public void testUpdateOomAdj_DoOne_PendingFinishAttach() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ app.setPendingFinishAttach(true);
+ app.mState.setHasForegroundActivities(false);
+
+ sService.mOomAdjuster.setAttachingProcessStatesLSP(app);
+ updateOomAdj(app);
+
+ assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, FOREGROUND_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoOne_TopApp_PendingFinishAttach() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ app.setPendingFinishAttach(true);
+ app.mState.setHasForegroundActivities(true);
+
+ sService.mOomAdjuster.setAttachingProcessStatesLSP(app);
+ updateOomAdj(app);
+
+ assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, FOREGROUND_APP_ADJ,
+ SCHED_GROUP_TOP_APP);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
public void testUpdateOomAdj_UidIdle_StopService() {
final ProcessRecord app1 = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
@@ -2378,8 +2411,12 @@ public class MockingOomAdjusterTests {
MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
final int userOwner = 0;
final int userOther = 1;
- final int cachedAdj1 = CACHED_APP_MIN_ADJ + ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
- final int cachedAdj2 = cachedAdj1 + ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
+ final int cachedAdj1 = sService.mConstants.USE_TIERED_CACHED_ADJ
+ ? CACHED_APP_MIN_ADJ + 10
+ : CACHED_APP_MIN_ADJ + ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
+ final int cachedAdj2 = sService.mConstants.USE_TIERED_CACHED_ADJ
+ ? CACHED_APP_MIN_ADJ + 10
+ : cachedAdj1 + ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
doReturn(userOwner).when(sService.mUserController).getCurrentUserId();
final ArrayList<ProcessRecord> lru = sService.mProcessList.getLruProcessesLOSP();
diff --git a/services/tests/mockingservicestests/src/com/android/server/cpu/CpuInfoReaderTest.java b/services/tests/mockingservicestests/src/com/android/server/cpu/CpuInfoReaderTest.java
index 9f3bc3358a4c..b21478753301 100644
--- a/services/tests/mockingservicestests/src/com/android/server/cpu/CpuInfoReaderTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/cpu/CpuInfoReaderTest.java
@@ -29,7 +29,7 @@ import android.content.res.AssetManager;
import android.util.Log;
import android.util.SparseArray;
-import com.android.server.ExtendedMockitoTestCase;
+import com.android.server.ExpectableTestCase;
import libcore.io.Streams;
@@ -44,7 +44,7 @@ import java.io.OutputStream;
import java.util.Objects;
/** This class contains unit tests for the {@link CpuInfoReader}. */
-public final class CpuInfoReaderTest extends ExtendedMockitoTestCase {
+public final class CpuInfoReaderTest extends ExpectableTestCase {
private static final String TAG = CpuInfoReaderTest.class.getSimpleName();
private static final String ROOT_DIR_NAME = "CpuInfoReaderTest";
private static final String VALID_CPUSET_DIR = "valid_cpuset";
@@ -426,7 +426,7 @@ public final class CpuInfoReaderTest extends ExtendedMockitoTestCase {
.isNull();
}
- private static void compareCpuInfos(String message,
+ private void compareCpuInfos(String message,
SparseArray<CpuInfoReader.CpuInfo> expected,
SparseArray<CpuInfoReader.CpuInfo> actual) {
assertWithMessage("%s. Total CPU infos", message).that(actual.size())
@@ -435,7 +435,7 @@ public final class CpuInfoReaderTest extends ExtendedMockitoTestCase {
int cpuCoreId = expected.keyAt(i);
CpuInfoReader.CpuInfo expectedCpuInfo = expected.valueAt(i);
CpuInfoReader.CpuInfo actualCpuInfo = actual.get(cpuCoreId);
- assertWithMessage("%s. Core %d's CPU info", message, cpuCoreId).that(actualCpuInfo)
+ expectWithMessage("%s. Core %s's CPU info", message, cpuCoreId).that(actualCpuInfo)
.isEqualTo(expectedCpuInfo);
}
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/cpu/CpuMonitorServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/cpu/CpuMonitorServiceTest.java
index 7ab1363b5087..49a2cc696744 100644
--- a/services/tests/mockingservicestests/src/com/android/server/cpu/CpuMonitorServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/cpu/CpuMonitorServiceTest.java
@@ -32,16 +32,16 @@ import android.os.HandlerExecutor;
import android.os.Looper;
import android.os.ServiceManager;
-import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder;
-import com.android.server.ExtendedMockitoTestCase;
+import com.android.server.ExtendedMockitoRule;
import com.android.server.LocalServices;
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
-public final class CpuMonitorServiceTest extends ExtendedMockitoTestCase {
+public final class CpuMonitorServiceTest {
private static final CpuAvailabilityMonitoringConfig TEST_CPU_AVAILABILITY_MONITORING_CONFIG =
new CpuAvailabilityMonitoringConfig.Builder(CPUSET_ALL)
.addThreshold(30).addThreshold(70).build();
@@ -56,10 +56,10 @@ public final class CpuMonitorServiceTest extends ExtendedMockitoTestCase {
private HandlerExecutor mHandlerExecutor;
private CpuMonitorInternal mLocalService;
- @Override
- protected void initializeSession(StaticMockitoSessionBuilder builder) {
- builder.mockStatic(ServiceManager.class);
- }
+ @Rule
+ public final ExtendedMockitoRule mExtendedMockitoRule = new ExtendedMockitoRule.Builder(this)
+ .mockStatic(ServiceManager.class)
+ .build();
@Before
public void setUp() {
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
index 96b63455598d..7942e246c2a7 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
@@ -64,6 +64,7 @@ import com.android.server.am.BatteryStatsService;
import com.android.server.display.RampAnimator.DualRampAnimator;
import com.android.server.display.brightness.BrightnessEvent;
import com.android.server.display.color.ColorDisplayService;
+import com.android.server.display.layout.Layout;
import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.testutils.OffsettableClock;
@@ -240,12 +241,15 @@ public final class DisplayPowerController2Test {
boolean isEnabled) {
DisplayInfo info = new DisplayInfo();
DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo();
+ deviceInfo.uniqueId = uniqueId;
when(logicalDisplayMock.getDisplayIdLocked()).thenReturn(displayId);
when(logicalDisplayMock.getPrimaryDisplayDeviceLocked()).thenReturn(displayDeviceMock);
when(logicalDisplayMock.getDisplayInfoLocked()).thenReturn(info);
when(logicalDisplayMock.isEnabledLocked()).thenReturn(isEnabled);
when(logicalDisplayMock.isInTransitionLocked()).thenReturn(false);
+ when(logicalDisplayMock.getBrightnessThrottlingDataIdLocked()).thenReturn(
+ DisplayDeviceConfig.DEFAULT_ID);
when(displayDeviceMock.getDisplayDeviceInfoLocked()).thenReturn(deviceInfo);
when(displayDeviceMock.getUniqueId()).thenReturn(uniqueId);
when(displayDeviceMock.getDisplayDeviceConfig()).thenReturn(displayDeviceConfigMock);
@@ -626,6 +630,19 @@ public final class DisplayPowerController2Test {
.setLightSensorEnabled(false);
}
+ @Test
+ public void testStopScreenOffBrightnessSensorControllerWhenDisplayDeviceChanges() {
+ setUpDisplay(DISPLAY_ID, "new_unique_id", mHolder.display, mock(DisplayDevice.class),
+ mock(DisplayDeviceConfig.class), /* isEnabled= */ true);
+
+ mHolder.dpc.onDisplayChanged(mHolder.hbmMetadata, Layout.NO_LEAD_DISPLAY);
+ DisplayPowerRequest dpr = new DisplayPowerRequest();
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1); // Run updatePowerState
+
+ verify(mHolder.screenOffBrightnessSensorController).stop();
+ }
+
private DisplayPowerControllerHolder createDisplayPowerController(int displayId,
String uniqueId) {
return createDisplayPowerController(displayId, uniqueId, /* isEnabled= */ true);
@@ -662,8 +679,8 @@ public final class DisplayPowerController2Test {
mBrightnessTrackerMock, brightnessSetting, () -> {},
hbmMetadata, /* bootCompleted= */ false);
- return new DisplayPowerControllerHolder(dpc, displayPowerState, brightnessSetting, animator,
- automaticBrightnessController, wakelockController,
+ return new DisplayPowerControllerHolder(dpc, display, displayPowerState, brightnessSetting,
+ animator, automaticBrightnessController, wakelockController,
screenOffBrightnessSensorController, hbmMetadata);
}
@@ -673,6 +690,7 @@ public final class DisplayPowerController2Test {
*/
private static class DisplayPowerControllerHolder {
public final DisplayPowerController2 dpc;
+ public final LogicalDisplay display;
public final DisplayPowerState displayPowerState;
public final BrightnessSetting brightnessSetting;
public final DualRampAnimator<DisplayPowerState> animator;
@@ -681,7 +699,7 @@ public final class DisplayPowerController2Test {
public final ScreenOffBrightnessSensorController screenOffBrightnessSensorController;
public final HighBrightnessModeMetadata hbmMetadata;
- DisplayPowerControllerHolder(DisplayPowerController2 dpc,
+ DisplayPowerControllerHolder(DisplayPowerController2 dpc, LogicalDisplay display,
DisplayPowerState displayPowerState, BrightnessSetting brightnessSetting,
DualRampAnimator<DisplayPowerState> animator,
AutomaticBrightnessController automaticBrightnessController,
@@ -689,6 +707,7 @@ public final class DisplayPowerController2Test {
ScreenOffBrightnessSensorController screenOffBrightnessSensorController,
HighBrightnessModeMetadata hbmMetadata) {
this.dpc = dpc;
+ this.display = display;
this.displayPowerState = displayPowerState;
this.brightnessSetting = brightnessSetting;
this.animator = animator;
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java
index 28319acc5f1b..16bf2a227c8a 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java
@@ -64,6 +64,7 @@ import com.android.server.am.BatteryStatsService;
import com.android.server.display.RampAnimator.DualRampAnimator;
import com.android.server.display.brightness.BrightnessEvent;
import com.android.server.display.color.ColorDisplayService;
+import com.android.server.display.layout.Layout;
import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.testutils.OffsettableClock;
@@ -243,12 +244,15 @@ public final class DisplayPowerControllerTest {
boolean isEnabled) {
DisplayInfo info = new DisplayInfo();
DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo();
+ deviceInfo.uniqueId = uniqueId;
when(logicalDisplayMock.getDisplayIdLocked()).thenReturn(displayId);
when(logicalDisplayMock.getPrimaryDisplayDeviceLocked()).thenReturn(displayDeviceMock);
when(logicalDisplayMock.getDisplayInfoLocked()).thenReturn(info);
when(logicalDisplayMock.isEnabledLocked()).thenReturn(isEnabled);
when(logicalDisplayMock.isInTransitionLocked()).thenReturn(false);
+ when(logicalDisplayMock.getBrightnessThrottlingDataIdLocked()).thenReturn(
+ DisplayDeviceConfig.DEFAULT_ID);
when(displayDeviceMock.getDisplayDeviceInfoLocked()).thenReturn(deviceInfo);
when(displayDeviceMock.getUniqueId()).thenReturn(uniqueId);
when(displayDeviceMock.getDisplayDeviceConfig()).thenReturn(displayDeviceConfigMock);
@@ -630,6 +634,19 @@ public final class DisplayPowerControllerTest {
.setLightSensorEnabled(false);
}
+ @Test
+ public void testStopScreenOffBrightnessSensorControllerWhenDisplayDeviceChanges() {
+ setUpDisplay(DISPLAY_ID, "new_unique_id", mHolder.display, mock(DisplayDevice.class),
+ mock(DisplayDeviceConfig.class), /* isEnabled= */ true);
+
+ mHolder.dpc.onDisplayChanged(mHolder.hbmMetadata, Layout.NO_LEAD_DISPLAY);
+ DisplayPowerRequest dpr = new DisplayPowerRequest();
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1); // Run updatePowerState
+
+ verify(mHolder.screenOffBrightnessSensorController).stop();
+ }
+
private DisplayPowerControllerHolder createDisplayPowerController(int displayId,
String uniqueId) {
return createDisplayPowerController(displayId, uniqueId, /* isEnabled= */ true);
@@ -665,8 +682,9 @@ public final class DisplayPowerControllerTest {
mBrightnessTrackerMock, brightnessSetting, () -> {},
hbmMetadata, /* bootCompleted= */ false);
- return new DisplayPowerControllerHolder(dpc, displayPowerState, brightnessSetting, animator,
- automaticBrightnessController, screenOffBrightnessSensorController, hbmMetadata);
+ return new DisplayPowerControllerHolder(dpc, display, displayPowerState, brightnessSetting,
+ animator, automaticBrightnessController, screenOffBrightnessSensorController,
+ hbmMetadata);
}
/**
@@ -675,6 +693,7 @@ public final class DisplayPowerControllerTest {
*/
private static class DisplayPowerControllerHolder {
public final DisplayPowerController dpc;
+ public final LogicalDisplay display;
public final DisplayPowerState displayPowerState;
public final BrightnessSetting brightnessSetting;
public final DualRampAnimator<DisplayPowerState> animator;
@@ -682,13 +701,14 @@ public final class DisplayPowerControllerTest {
public final ScreenOffBrightnessSensorController screenOffBrightnessSensorController;
public final HighBrightnessModeMetadata hbmMetadata;
- DisplayPowerControllerHolder(DisplayPowerController dpc,
+ DisplayPowerControllerHolder(DisplayPowerController dpc, LogicalDisplay display,
DisplayPowerState displayPowerState, BrightnessSetting brightnessSetting,
DualRampAnimator<DisplayPowerState> animator,
AutomaticBrightnessController automaticBrightnessController,
ScreenOffBrightnessSensorController screenOffBrightnessSensorController,
HighBrightnessModeMetadata hbmMetadata) {
this.dpc = dpc;
+ this.display = display;
this.displayPowerState = displayPowerState;
this.brightnessSetting = brightnessSetting;
this.animator = animator;
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
index 95a588497980..5f82ec1dde02 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
@@ -53,6 +53,7 @@ import com.android.dx.mockito.inline.extended.StaticMockitoSession;
import com.android.internal.R;
import com.android.server.LocalServices;
import com.android.server.display.LocalDisplayAdapter.BacklightAdapter;
+import com.android.server.display.mode.DisplayModeDirector;
import com.android.server.lights.LightsManager;
import com.android.server.lights.LogicalLight;
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/JobNotificationCoordinatorTest.java b/services/tests/mockingservicestests/src/com/android/server/job/JobNotificationCoordinatorTest.java
index b4104dbc89f9..03f667f0d336 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/JobNotificationCoordinatorTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/JobNotificationCoordinatorTest.java
@@ -33,6 +33,7 @@ import static org.mockito.Mockito.verify;
import android.app.Notification;
import android.app.NotificationChannel;
+import android.app.job.JobParameters;
import android.app.job.JobService;
import android.graphics.drawable.Icon;
import android.os.UserHandle;
@@ -145,7 +146,7 @@ public class JobNotificationCoordinatorTest {
.enqueueNotification(eq(TEST_PACKAGE), eq(TEST_PACKAGE), eq(uid), eq(pid), any(),
eq(notificationId), eq(notification), eq(UserHandle.getUserId(uid)));
- coordinator.removeNotificationAssociation(jsc);
+ coordinator.removeNotificationAssociation(jsc, JobParameters.STOP_REASON_UNDEFINED);
verify(mNotificationManagerInternal, never())
.cancelNotification(anyString(), anyString(), anyInt(), anyInt(), any(),
anyInt(), anyInt());
@@ -166,7 +167,7 @@ public class JobNotificationCoordinatorTest {
.enqueueNotification(eq(TEST_PACKAGE), eq(TEST_PACKAGE), eq(uid), eq(pid), any(),
eq(notificationId), eq(notification), eq(UserHandle.getUserId(uid)));
- coordinator.removeNotificationAssociation(jsc);
+ coordinator.removeNotificationAssociation(jsc, JobParameters.STOP_REASON_UNDEFINED);
verify(mNotificationManagerInternal)
.cancelNotification(eq(TEST_PACKAGE), eq(TEST_PACKAGE), eq(uid), eq(pid), any(),
eq(notificationId), eq(UserHandle.getUserId(uid)));
@@ -288,7 +289,7 @@ public class JobNotificationCoordinatorTest {
eq(notificationId2), eq(notification2), eq(UserHandle.getUserId(uid)));
// Remove the first job. Only the first notification should be removed.
- coordinator.removeNotificationAssociation(jsc1);
+ coordinator.removeNotificationAssociation(jsc1, JobParameters.STOP_REASON_UNDEFINED);
inOrder.verify(mNotificationManagerInternal)
.cancelNotification(eq(TEST_PACKAGE), eq(TEST_PACKAGE), eq(uid), eq(pid), any(),
eq(notificationId1), eq(UserHandle.getUserId(uid)));
@@ -296,7 +297,7 @@ public class JobNotificationCoordinatorTest {
.cancelNotification(anyString(), anyString(), anyInt(), anyInt(), any(),
eq(notificationId2), anyInt());
- coordinator.removeNotificationAssociation(jsc2);
+ coordinator.removeNotificationAssociation(jsc2, JobParameters.STOP_REASON_UNDEFINED);
inOrder.verify(mNotificationManagerInternal)
.cancelNotification(eq(TEST_PACKAGE), eq(TEST_PACKAGE), eq(uid), eq(pid), any(),
eq(notificationId2), eq(UserHandle.getUserId(uid)));
@@ -331,12 +332,12 @@ public class JobNotificationCoordinatorTest {
eq(notificationId), eq(notification2), eq(UserHandle.getUserId(uid)));
// Remove the first job. The notification shouldn't be touched because of the 2nd job.
- coordinator.removeNotificationAssociation(jsc1);
+ coordinator.removeNotificationAssociation(jsc1, JobParameters.STOP_REASON_UNDEFINED);
inOrder.verify(mNotificationManagerInternal, never())
.cancelNotification(anyString(), anyString(), anyInt(), anyInt(), any(),
anyInt(), anyInt());
- coordinator.removeNotificationAssociation(jsc2);
+ coordinator.removeNotificationAssociation(jsc2, JobParameters.STOP_REASON_UNDEFINED);
inOrder.verify(mNotificationManagerInternal)
.cancelNotification(eq(TEST_PACKAGE), eq(TEST_PACKAGE), eq(uid), eq(pid), any(),
eq(notificationId), eq(UserHandle.getUserId(uid)));
@@ -372,7 +373,7 @@ public class JobNotificationCoordinatorTest {
eq(notificationId), eq(notification2), eq(UserHandle.getUserId(uid2)));
// Remove the first job. Only the first notification should be removed.
- coordinator.removeNotificationAssociation(jsc1);
+ coordinator.removeNotificationAssociation(jsc1, JobParameters.STOP_REASON_UNDEFINED);
inOrder.verify(mNotificationManagerInternal)
.cancelNotification(eq(TEST_PACKAGE), eq(TEST_PACKAGE), eq(uid1), eq(pid), any(),
eq(notificationId), eq(UserHandle.getUserId(uid1)));
@@ -380,7 +381,7 @@ public class JobNotificationCoordinatorTest {
.cancelNotification(anyString(), anyString(), eq(uid2), anyInt(), any(),
anyInt(), anyInt());
- coordinator.removeNotificationAssociation(jsc2);
+ coordinator.removeNotificationAssociation(jsc2, JobParameters.STOP_REASON_UNDEFINED);
inOrder.verify(mNotificationManagerInternal)
.cancelNotification(eq(TEST_PACKAGE), eq(TEST_PACKAGE), eq(uid2), eq(pid), any(),
eq(notificationId), eq(UserHandle.getUserId(uid2)));
@@ -417,7 +418,7 @@ public class JobNotificationCoordinatorTest {
eq(notificationId), eq(notification2), eq(UserHandle.getUserId(uid)));
// Remove the first job. Only the first notification should be removed.
- coordinator.removeNotificationAssociation(jsc1);
+ coordinator.removeNotificationAssociation(jsc1, JobParameters.STOP_REASON_UNDEFINED);
inOrder.verify(mNotificationManagerInternal)
.cancelNotification(eq(pkg1), eq(pkg1), eq(uid), eq(pid), any(),
eq(notificationId), eq(UserHandle.getUserId(uid)));
@@ -425,12 +426,73 @@ public class JobNotificationCoordinatorTest {
.cancelNotification(anyString(), anyString(), eq(uid), anyInt(), any(),
anyInt(), anyInt());
- coordinator.removeNotificationAssociation(jsc2);
+ coordinator.removeNotificationAssociation(jsc2, JobParameters.STOP_REASON_UNDEFINED);
inOrder.verify(mNotificationManagerInternal)
.cancelNotification(eq(pkg2), eq(pkg2), eq(uid), eq(pid), any(),
eq(notificationId), eq(UserHandle.getUserId(uid)));
}
+ @Test
+ public void testUserStop_SingleJob_DetachOnStop() {
+ final JobNotificationCoordinator coordinator = new JobNotificationCoordinator();
+ final JobServiceContext jsc = mock(JobServiceContext.class);
+ final Notification notification = createValidNotification();
+ final int uid = 10123;
+ final int pid = 42;
+ final int notificationId = 23;
+
+ coordinator.enqueueNotification(jsc, TEST_PACKAGE, pid, uid, notificationId, notification,
+ JobService.JOB_END_NOTIFICATION_POLICY_DETACH);
+ verify(mNotificationManagerInternal)
+ .enqueueNotification(eq(TEST_PACKAGE), eq(TEST_PACKAGE), eq(uid), eq(pid), any(),
+ eq(notificationId), eq(notification), eq(UserHandle.getUserId(uid)));
+
+ coordinator.removeNotificationAssociation(jsc, JobParameters.STOP_REASON_USER);
+ verify(mNotificationManagerInternal)
+ .cancelNotification(eq(TEST_PACKAGE), eq(TEST_PACKAGE), eq(uid), eq(pid), any(),
+ eq(notificationId), eq(UserHandle.getUserId(uid)));
+ }
+
+ @Test
+ public void testUserStop_MultipleJobs_sameApp_EnqueueSameNotificationId_DetachOnStop() {
+ final JobNotificationCoordinator coordinator = new JobNotificationCoordinator();
+ final JobServiceContext jsc1 = mock(JobServiceContext.class);
+ final JobServiceContext jsc2 = mock(JobServiceContext.class);
+ final Notification notification1 = createValidNotification();
+ final Notification notification2 = createValidNotification();
+ final int uid = 10123;
+ final int pid = 42;
+ final int notificationId = 23;
+
+ InOrder inOrder = inOrder(mNotificationManagerInternal);
+
+ coordinator.enqueueNotification(jsc1, TEST_PACKAGE, pid, uid, notificationId, notification1,
+ JobService.JOB_END_NOTIFICATION_POLICY_DETACH);
+ inOrder.verify(mNotificationManagerInternal)
+ .enqueueNotification(eq(TEST_PACKAGE), eq(TEST_PACKAGE), eq(uid), eq(pid), any(),
+ eq(notificationId), eq(notification1), eq(UserHandle.getUserId(uid)));
+
+ coordinator.enqueueNotification(jsc2, TEST_PACKAGE, pid, uid, notificationId, notification2,
+ JobService.JOB_END_NOTIFICATION_POLICY_DETACH);
+ inOrder.verify(mNotificationManagerInternal, never())
+ .cancelNotification(anyString(), anyString(), anyInt(), anyInt(), any(),
+ anyInt(), anyInt());
+ inOrder.verify(mNotificationManagerInternal)
+ .enqueueNotification(eq(TEST_PACKAGE), eq(TEST_PACKAGE), eq(uid), eq(pid), any(),
+ eq(notificationId), eq(notification2), eq(UserHandle.getUserId(uid)));
+
+ // Remove the first job. The notification shouldn't be touched because of the 2nd job.
+ coordinator.removeNotificationAssociation(jsc1, JobParameters.STOP_REASON_USER);
+ inOrder.verify(mNotificationManagerInternal, never())
+ .cancelNotification(anyString(), anyString(), anyInt(), anyInt(), any(),
+ anyInt(), anyInt());
+
+ coordinator.removeNotificationAssociation(jsc2, JobParameters.STOP_REASON_USER);
+ inOrder.verify(mNotificationManagerInternal)
+ .cancelNotification(eq(TEST_PACKAGE), eq(TEST_PACKAGE), eq(uid), eq(pid), any(),
+ eq(notificationId), eq(UserHandle.getUserId(uid)));
+ }
+
private Notification createValidNotification() {
final Notification notification = mock(Notification.class);
doReturn(mock(Icon.class)).when(notification).getSmallIcon();
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
index 991d5667206b..8b420a36602c 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
@@ -234,15 +234,9 @@ public class JobSchedulerServiceTest {
createJobInfo(5).setPriority(JobInfo.PRIORITY_HIGH));
JobStatus jobDef = createJobStatus("testGetMinJobExecutionGuaranteeMs",
createJobInfo(6));
- JobStatus jobDT = createJobStatus("testGetMinJobExecutionGuaranteeMs",
- createJobInfo(7)
- .setDataTransfer(true).setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY));
- JobStatus jobUI = createJobStatus("testGetMinJobExecutionGuaranteeMs",
- createJobInfo(8)); // TODO(255371817): add setUserInitiated(true)
JobStatus jobUIDT = createJobStatus("testGetMinJobExecutionGuaranteeMs",
- // TODO(255371817): add setUserInitiated(true)
createJobInfo(9)
- .setDataTransfer(true).setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY));
+ .setUserInitiated(true).setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY));
spyOn(ejMax);
spyOn(ejHigh);
@@ -250,8 +244,6 @@ public class JobSchedulerServiceTest {
spyOn(ejHighDowngraded);
spyOn(jobHigh);
spyOn(jobDef);
- spyOn(jobDT);
- spyOn(jobUI);
spyOn(jobUIDT);
when(ejMax.shouldTreatAsExpeditedJob()).thenReturn(true);
@@ -260,14 +252,11 @@ public class JobSchedulerServiceTest {
when(ejHighDowngraded.shouldTreatAsExpeditedJob()).thenReturn(false);
when(jobHigh.shouldTreatAsExpeditedJob()).thenReturn(false);
when(jobDef.shouldTreatAsExpeditedJob()).thenReturn(false);
- when(jobUI.shouldTreatAsUserInitiatedJob()).thenReturn(true);
when(jobUIDT.shouldTreatAsUserInitiatedJob()).thenReturn(true);
ConnectivityController connectivityController = mService.getConnectivityController();
spyOn(connectivityController);
mService.mConstants.RUNTIME_MIN_GUARANTEE_MS = 10 * MINUTE_IN_MILLIS;
- mService.mConstants.RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS = 15 * MINUTE_IN_MILLIS;
- mService.mConstants.RUNTIME_DATA_TRANSFER_LIMIT_MS = 60 * MINUTE_IN_MILLIS;
mService.mConstants.RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_BUFFER_FACTOR = 1.5f;
mService.mConstants.RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_MS = HOUR_IN_MILLIS;
mService.mConstants.RUNTIME_USER_INITIATED_DATA_TRANSFER_LIMIT_MS = 6 * HOUR_IN_MILLIS;
@@ -284,37 +273,14 @@ public class JobSchedulerServiceTest {
mService.getMinJobExecutionGuaranteeMs(jobHigh));
assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
mService.getMinJobExecutionGuaranteeMs(jobDef));
- grantRunUserInitiatedJobsPermission(false); // Without permission
- assertEquals(mService.mConstants.RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS,
- mService.getMinJobExecutionGuaranteeMs(jobDT));
- grantRunUserInitiatedJobsPermission(true); // With permission
- doReturn(ConnectivityController.UNKNOWN_TIME)
- .when(connectivityController).getEstimatedTransferTimeMs(any());
- assertEquals(mService.mConstants.RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS,
- mService.getMinJobExecutionGuaranteeMs(jobDT));
- doReturn(mService.mConstants.RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS / 2)
- .when(connectivityController).getEstimatedTransferTimeMs(any());
- assertEquals(mService.mConstants.RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS,
- mService.getMinJobExecutionGuaranteeMs(jobDT));
- doReturn(mService.mConstants.RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS * 2)
- .when(connectivityController).getEstimatedTransferTimeMs(any());
- assertEquals(mService.mConstants.RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS,
- mService.getMinJobExecutionGuaranteeMs(jobDT));
- doReturn(mService.mConstants.RUNTIME_DATA_TRANSFER_LIMIT_MS * 2)
- .when(connectivityController).getEstimatedTransferTimeMs(any());
- assertEquals(mService.mConstants.RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS,
- mService.getMinJobExecutionGuaranteeMs(jobDT));
// UserInitiated
grantRunUserInitiatedJobsPermission(false);
- // Permission isn't granted, so it should just be treated as a regular data transfer job.
- assertEquals(mService.mConstants.RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS,
- mService.getMinJobExecutionGuaranteeMs(jobUIDT));
// Permission isn't granted, so it should just be treated as a regular job.
assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
- mService.getMinJobExecutionGuaranteeMs(jobUI));
+ mService.getMinJobExecutionGuaranteeMs(jobUIDT));
grantRunUserInitiatedJobsPermission(true); // With permission
- assertEquals(mService.mConstants.RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS,
- mService.getMinJobExecutionGuaranteeMs(jobUI));
+ assertEquals(mService.mConstants.RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_MS,
+ mService.getMinJobExecutionGuaranteeMs(jobUIDT));
doReturn(ConnectivityController.UNKNOWN_TIME)
.when(connectivityController).getEstimatedTransferTimeMs(any());
assertEquals(mService.mConstants.RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_MS,
@@ -338,21 +304,10 @@ public class JobSchedulerServiceTest {
@Test
public void testGetMaxJobExecutionTimeMs() {
- JobStatus jobDT = createJobStatus("testGetMaxJobExecutionTimeMs",
- createJobInfo(7)
- .setDataTransfer(true).setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY));
- JobStatus jobUI = createJobStatus("testGetMaxJobExecutionTimeMs",
- createJobInfo(9)); // TODO(255371817): add setUserInitiated(true)
JobStatus jobUIDT = createJobStatus("testGetMaxJobExecutionTimeMs",
- // TODO(255371817): add setUserInitiated(true)
createJobInfo(10)
- .setDataTransfer(true).setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY));
-
- spyOn(jobDT);
- spyOn(jobUI);
+ .setUserInitiated(true).setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY));
spyOn(jobUIDT);
-
- when(jobUI.shouldTreatAsUserInitiatedJob()).thenReturn(true);
when(jobUIDT.shouldTreatAsUserInitiatedJob()).thenReturn(true);
QuotaController quotaController = mService.getQuotaController();
@@ -365,17 +320,9 @@ public class JobSchedulerServiceTest {
.when(quotaController).getMaxJobExecutionTimeMsLocked(any());
grantRunUserInitiatedJobsPermission(true);
- assertEquals(mService.mConstants.RUNTIME_DATA_TRANSFER_LIMIT_MS,
- mService.getMaxJobExecutionTimeMs(jobDT));
- assertEquals(mService.mConstants.RUNTIME_USER_INITIATED_LIMIT_MS,
- mService.getMaxJobExecutionTimeMs(jobUI));
assertEquals(mService.mConstants.RUNTIME_USER_INITIATED_DATA_TRANSFER_LIMIT_MS,
mService.getMaxJobExecutionTimeMs(jobUIDT));
grantRunUserInitiatedJobsPermission(false);
- assertEquals(mService.mConstants.RUNTIME_DATA_TRANSFER_LIMIT_MS,
- mService.getMaxJobExecutionTimeMs(jobDT));
- assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
- mService.getMaxJobExecutionTimeMs(jobUI));
assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
mService.getMaxJobExecutionTimeMs(jobUIDT));
}
@@ -478,7 +425,8 @@ public class JobSchedulerServiceTest {
@Test
public void testGetRescheduleJobForFailure_userStopped() {
JobStatus uiJob = createJobStatus("testGetRescheduleJobForFailure",
- createJobInfo().setUserInitiated(true));
+ createJobInfo().setUserInitiated(true)
+ .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY));
JobStatus uvJob = createJobStatus("testGetRescheduleJobForFailure", createJobInfo());
spyOn(uvJob);
doReturn(true).when(uvJob).isUserVisibleJob();
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java
index 1e65b380310f..6bc552c7f32e 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java
@@ -619,7 +619,7 @@ public class FlexibilityControllerTest {
@Test
public void testExceptions_UserInitiated() {
JobInfo.Builder jb = createJob(0);
- jb.setUserInitiated(true);
+ jb.setUserInitiated(true).setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
JobStatus js = createJobStatus("testExceptions_UserInitiated", jb);
assertFalse(js.hasFlexibilityConstraint());
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
index e6bc72f94f05..5dc8ed58994d 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
@@ -170,6 +170,7 @@ public class JobStatusTest {
final JobInfo jobInfo =
new JobInfo.Builder(101, new ComponentName("foo", "bar"))
.setUserInitiated(true)
+ .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.build();
JobStatus job = createJobStatus(jobInfo);
assertTrue(job.canRunInBatterySaver());
@@ -216,6 +217,7 @@ public class JobStatusTest {
final JobInfo jobInfo =
new JobInfo.Builder(101, new ComponentName("foo", "bar"))
.setUserInitiated(true)
+ .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.build();
JobStatus job = createJobStatus(jobInfo);
assertTrue(job.canRunInDoze());
@@ -236,6 +238,7 @@ public class JobStatusTest {
// User-initiated jobs are always user-visible unless they've been demoted.
jobInfo = new JobInfo.Builder(101, new ComponentName("foo", "bar"))
.setUserInitiated(true)
+ .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.build();
job = createJobStatus(jobInfo);
@@ -507,6 +510,7 @@ public class JobStatusTest {
jobInfo = new JobInfo.Builder(101, new ComponentName("foo", "bar"))
.setUserInitiated(true)
+ .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.build();
job = createJobStatus(jobInfo);
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java
index 1ed2f789d9b2..564893c3c629 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java
@@ -40,9 +40,8 @@ import android.util.SparseArray;
import androidx.test.annotation.UiThreadTest;
-import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder;
import com.android.internal.widget.LockSettingsInternal;
-import com.android.server.ExtendedMockitoTestCase;
+import com.android.server.ExtendedMockitoRule;
import com.android.server.LocalServices;
import com.android.server.am.UserState;
import com.android.server.pm.UserManagerService.UserData;
@@ -50,13 +49,14 @@ import com.android.server.storage.DeviceStorageMonitorInternal;
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
/**
* Run as {@code atest FrameworksMockingServicesTests:com.android.server.pm.UserManagerServiceTest}
*/
-public final class UserManagerServiceTest extends ExtendedMockitoTestCase {
+public final class UserManagerServiceTest {
private static final String TAG = UserManagerServiceTest.class.getSimpleName();
@@ -84,6 +84,13 @@ public final class UserManagerServiceTest extends ExtendedMockitoTestCase {
*/
private static final int PROFILE_USER_ID = 643;
+ @Rule
+ public final ExtendedMockitoRule mExtendedMockitoRule = new ExtendedMockitoRule.Builder(this)
+ .spyStatic(UserManager.class)
+ .spyStatic(LocalServices.class)
+ .mockStatic(Settings.Global.class)
+ .build();
+
private final Object mPackagesLock = new Object();
private final Context mRealContext = androidx.test.InstrumentationRegistry.getInstrumentation()
.getTargetContext();
@@ -109,14 +116,6 @@ public final class UserManagerServiceTest extends ExtendedMockitoTestCase {
*/
private UserManagerInternal mUmi;
- @Override
- protected void initializeSession(StaticMockitoSessionBuilder builder) {
- builder
- .spyStatic(UserManager.class)
- .spyStatic(LocalServices.class)
- .mockStatic(Settings.Global.class);
- }
-
@Before
@UiThreadTest // Needed to initialize main handler
public void setFixtures() {
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUPANDTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUPANDTest.java
index 38cf6341e798..8979585d9235 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUPANDTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUPANDTest.java
@@ -75,8 +75,8 @@ public final class UserVisibilityMediatorMUPANDTest
assertUserCanBeAssignedExtraDisplay(USER_ID, OTHER_SECONDARY_DISPLAY_ID);
// Make sure another user cannot be started on default display
- int result2 = mMediator.assignUserToDisplayOnStart(otherUserId, visibleBgUserId,
- BG_VISIBLE, DEFAULT_DISPLAY);
+ int result2 = mMediator.assignUserToDisplayOnStart(otherUserId, otherUserId, BG_VISIBLE,
+ DEFAULT_DISPLAY);
assertStartUserResult(result2, USER_ASSIGNMENT_RESULT_FAILURE,
"when user (%d) is starting on default display after it was started by user %d",
otherUserId, visibleBgUserId);
@@ -119,8 +119,8 @@ public final class UserVisibilityMediatorMUPANDTest
assertUserCanBeAssignedExtraDisplay(USER_ID, OTHER_SECONDARY_DISPLAY_ID);
// Make sure another user cannot be started on default display
- int result2 = mMediator.assignUserToDisplayOnStart(otherUserId, visibleBgUserId,
- BG_VISIBLE, DEFAULT_DISPLAY);
+ int result2 = mMediator.assignUserToDisplayOnStart(otherUserId, otherUserId, BG_VISIBLE,
+ DEFAULT_DISPLAY);
assertStartUserResult(result2, USER_ASSIGNMENT_RESULT_FAILURE,
"when user (%d) is starting on default display after it was started by user %d",
otherUserId, visibleBgUserId);
@@ -128,7 +128,6 @@ public final class UserVisibilityMediatorMUPANDTest
listener.verify();
}
- /* TODO: re-add
@Test
public void
@@ -227,5 +226,4 @@ public final class UserVisibilityMediatorMUPANDTest
listener.verify();
}
- */
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java
index 5176d684ace6..277480316c66 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java
@@ -44,8 +44,8 @@ import android.text.TextUtils;
import android.util.IntArray;
import android.util.Log;
-import com.android.internal.util.Preconditions;
-import com.android.server.ExtendedMockitoTestCase;
+import com.android.server.DumpableDumperRule;
+import com.android.server.ExpectableTestCase;
import org.junit.Before;
import org.junit.Test;
@@ -64,7 +64,7 @@ import java.util.Arrays;
* is visible, display associated to the user, etc...) for each scenario (full user started on fg,
* profile user started on bg, etc...).
*/
-abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase {
+abstract class UserVisibilityMediatorTestCase extends ExpectableTestCase {
private static final String TAG = UserVisibilityMediatorTestCase.class.getSimpleName();
@@ -125,6 +125,8 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase {
mBackgroundUserOnDefaultDisplayAllowed = backgroundUserOnDefaultDisplayAllowed;
}
+ protected final DumpableDumperRule mDumpableDumperRule = new DumpableDumperRule();
+
@Before
public final void setFixtures() {
mHandler = Handler.getMain();
@@ -149,6 +151,12 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase {
}
@Test
+ public final void testAssignUserToDisplayOnStart_invalidUserStartMode() {
+ assertThrows(IllegalArgumentException.class, () -> mMediator
+ .assignUserToDisplayOnStart(USER_ID, USER_ID, 666, DEFAULT_DISPLAY));
+ }
+
+ @Test
public final void testStartFgUser_onSecondaryDisplay() throws Exception {
AsyncUserVisibilityListener listener = addListenerForNoEvents();
@@ -283,7 +291,7 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase {
int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
BG_VISIBLE, DEFAULT_DISPLAY);
- assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
+ assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
expectNoDisplayAssignedToUser(PROFILE_USER_ID);
@@ -299,14 +307,14 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase {
int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
BG_VISIBLE, DEFAULT_DISPLAY);
- assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
+ assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
expectNoDisplayAssignedToUser(PROFILE_USER_ID);
expectInitialCurrentUserAssignedToDisplay(DEFAULT_DISPLAY);
- assertUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
+ assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
listener.verify();
}
@@ -332,6 +340,41 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase {
}
@Test
+ public final void testStartBgProfile_onDefaultDisplay_whenParentIsNotStarted()
+ throws Exception {
+ AsyncUserVisibilityListener listener = addListenerForNoEvents();
+
+ int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID, BG,
+ DEFAULT_DISPLAY);
+ assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
+
+ expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
+ expectNoDisplayAssignedToUser(PROFILE_USER_ID);
+
+ listener.verify();
+ }
+
+ @Test
+ public final void testStartBgProfile_onDefaultDisplay_whenParentIsStartedOnBg()
+ throws Exception {
+ AsyncUserVisibilityListener listener = addListenerForNoEvents();
+ startBackgroundUser(PARENT_USER_ID);
+
+ int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID, BG,
+ DEFAULT_DISPLAY);
+ assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
+
+ expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
+
+ expectNoDisplayAssignedToUser(PROFILE_USER_ID);
+ expectInitialCurrentUserAssignedToDisplay(DEFAULT_DISPLAY);
+
+ assertUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
+
+ listener.verify();
+ }
+
+ @Test
public final void testStartBgProfile_onSecondaryDisplay() throws Exception {
AsyncUserVisibilityListener listener = addListenerForNoEvents();
@@ -485,8 +528,6 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase {
* se.
*/
protected final void startUserInSecondaryDisplay(@UserIdInt int userId, int displayId) {
- Preconditions.checkArgument(displayId != INVALID_DISPLAY && displayId != DEFAULT_DISPLAY,
- "must pass a secondary display, not %d", displayId);
Log.d(TAG, "startUserInSecondaryDisplay(" + userId + ", " + displayId + ")");
int result = mMediator.assignUserToDisplayOnStart(userId, userId, BG_VISIBLE, displayId);
if (result != USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorVisibleBackgroundUserTestCase.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorVisibleBackgroundUserTestCase.java
index af85ef4b6b87..e82910f25a2c 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorVisibleBackgroundUserTestCase.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorVisibleBackgroundUserTestCase.java
@@ -109,34 +109,6 @@ abstract class UserVisibilityMediatorVisibleBackgroundUserTestCase
}
@Test
- public final void testStartVisibleBgProfile_onDefaultDisplay_whenParentIsCurrentUser()
- throws Exception {
- AsyncUserVisibilityListener listener = addListenerForEvents(
- onInvisible(INITIAL_CURRENT_USER_ID),
- onVisible(PARENT_USER_ID),
- onVisible(PROFILE_USER_ID));
- startForegroundUser(PARENT_USER_ID);
-
- int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
- BG_VISIBLE, DEFAULT_DISPLAY);
- assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
- expectUserCannotBeUnassignedFromDisplay(PROFILE_USER_ID, DEFAULT_DISPLAY);
-
- expectUserIsVisible(PROFILE_USER_ID);
- expectUserIsNotVisibleOnDisplay(PROFILE_USER_ID, INVALID_DISPLAY);
- expectUserIsNotVisibleOnDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
- expectUserIsVisibleOnDisplay(PROFILE_USER_ID, DEFAULT_DISPLAY);
- expectVisibleUsers(PARENT_USER_ID, PROFILE_USER_ID);
-
- expectDisplayAssignedToUser(PROFILE_USER_ID, DEFAULT_DISPLAY);
- expectUserAssignedToDisplay(DEFAULT_DISPLAY, PARENT_USER_ID);
-
- assertUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
-
- listener.verify();
- }
-
- @Test
public final void testStartFgUser_onInvalidDisplay() throws Exception {
AsyncUserVisibilityListener listener = addListenerForNoEvents();
@@ -301,14 +273,83 @@ abstract class UserVisibilityMediatorVisibleBackgroundUserTestCase
}
@Test
+ public final void testStartVisibleBgProfile_onDefaultDisplay_whenParentIsCurrentUser()
+ throws Exception {
+ AsyncUserVisibilityListener listener = addListenerForEvents(
+ onInvisible(INITIAL_CURRENT_USER_ID),
+ onVisible(PARENT_USER_ID),
+ onVisible(PROFILE_USER_ID));
+ startForegroundUser(PARENT_USER_ID);
+
+ int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
+ BG_VISIBLE, DEFAULT_DISPLAY);
+ assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
+ expectUserCannotBeUnassignedFromDisplay(PROFILE_USER_ID, DEFAULT_DISPLAY);
+
+ expectUserIsVisible(PROFILE_USER_ID);
+ expectUserIsNotVisibleOnDisplay(PROFILE_USER_ID, INVALID_DISPLAY);
+ expectUserIsNotVisibleOnDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
+ expectUserIsVisibleOnDisplay(PROFILE_USER_ID, DEFAULT_DISPLAY);
+ expectVisibleUsers(PARENT_USER_ID, PROFILE_USER_ID);
+
+ expectDisplayAssignedToUser(PROFILE_USER_ID, DEFAULT_DISPLAY);
+ expectUserAssignedToDisplay(DEFAULT_DISPLAY, PARENT_USER_ID);
+
+ assertUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
+
+ listener.verify();
+ }
+
+ @Test
public final void
- testStartVisibleBgProfile_onDefaultDisplay_whenParentVisibleOnSecondaryDisplay()
- throws Exception {
+ testStartVisibleBgProfile_onDefaultDisplay_whenParentIsStartedVisibleOnAnotherDisplay()
+ throws Exception {
AsyncUserVisibilityListener listener = addListenerForEvents(onVisible(PARENT_USER_ID));
startUserInSecondaryDisplay(PARENT_USER_ID, OTHER_SECONDARY_DISPLAY_ID);
int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
BG_VISIBLE, DEFAULT_DISPLAY);
+ assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
+
+ expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
+ expectNoDisplayAssignedToUser(PROFILE_USER_ID);
+ expectUserAssignedToDisplay(OTHER_SECONDARY_DISPLAY_ID, PARENT_USER_ID);
+
+ assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
+
+ listener.verify();
+ }
+
+ // Not supported - profiles can only be started on default display
+ @Test
+ public final void
+ testStartVisibleBgProfile_onSecondaryDisplay_whenParentIsStartedVisibleOnThatDisplay()
+ throws Exception {
+ AsyncUserVisibilityListener listener = addListenerForEvents(onVisible(PARENT_USER_ID));
+ startUserInSecondaryDisplay(PARENT_USER_ID, OTHER_SECONDARY_DISPLAY_ID);
+
+ int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
+ BG_VISIBLE, DEFAULT_DISPLAY);
+ assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
+
+ expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
+ expectNoDisplayAssignedToUser(PROFILE_USER_ID);
+ expectUserAssignedToDisplay(OTHER_SECONDARY_DISPLAY_ID, PARENT_USER_ID);
+
+ assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
+
+ listener.verify();
+ }
+
+ @Test
+ public final void
+ testStartProfile_onDefaultDisplay_whenParentIsStartedVisibleOnSecondaryDisplay()
+ throws Exception {
+ AsyncUserVisibilityListener listener = addListenerForEvents(onVisible(PARENT_USER_ID));
+ startUserInSecondaryDisplay(PARENT_USER_ID, OTHER_SECONDARY_DISPLAY_ID);
+
+ int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID, BG,
+ DEFAULT_DISPLAY);
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
diff --git a/services/tests/mockingservicestests/src/com/android/server/utils/SlogfTest.java b/services/tests/mockingservicestests/src/com/android/server/utils/SlogfTest.java
index cb59d37e46ec..02e46bb2ed39 100644
--- a/services/tests/mockingservicestests/src/com/android/server/utils/SlogfTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/utils/SlogfTest.java
@@ -16,16 +16,9 @@
package com.android.server.utils;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.never;
-
import android.util.Log;
import android.util.Slog;
@@ -51,7 +44,6 @@ public final class SlogfTest {
mSession = mockitoSession()
.initMocks(this)
.mockStatic(Slog.class)
- .spyStatic(Slogf.class) // for isLoggable only
.strictness(Strictness.LENIENT)
.startMocking();
}
@@ -66,11 +58,6 @@ public final class SlogfTest {
}
@Test
- public void testIsLoggable() {
- assertThat(Slogf.isLoggable(TAG, Log.VERBOSE)).isEqualTo(Log.isLoggable(TAG, Log.VERBOSE));
- }
-
- @Test
public void testV_msg() {
Slogf.v(TAG, "msg");
@@ -85,42 +72,20 @@ public final class SlogfTest {
}
@Test
- public void testV_msgFormatted_enabled() {
- enableLogging(Log.VERBOSE);
-
+ public void testV_msgFormatted() {
Slogf.v(TAG, "msg in a %s", "bottle");
verify(()-> Slog.v(TAG, "msg in a bottle"));
}
@Test
- public void testV_msgFormatted_disabled() {
- disableLogging(Log.VERBOSE);
-
- Slogf.v(TAG, "msg in a %s", "bottle");
-
- verify(()-> Slog.v(eq(TAG), any()), never());
- }
-
- @Test
- public void testV_msgFormattedWithThrowable_enabled() {
- enableLogging(Log.VERBOSE);
-
+ public void testV_msgFormattedWithThrowable() {
Slogf.v(TAG, mThrowable, "msg in a %s", "bottle");
verify(()-> Slog.v(TAG, "msg in a bottle", mThrowable));
}
@Test
- public void testV_msgFormattedWithException_disabled() {
- disableLogging(Log.VERBOSE);
-
- Slogf.v(TAG, "msg in a %s", "bottle");
-
- verify(()-> Slog.v(eq(TAG), any(String.class), any(Throwable.class)), never());
- }
-
- @Test
public void testD_msg() {
Slogf.d(TAG, "msg");
@@ -135,42 +100,20 @@ public final class SlogfTest {
}
@Test
- public void testD_msgFormatted_enabled() {
- enableLogging(Log.DEBUG);
-
+ public void testD_msgFormatted() {
Slogf.d(TAG, "msg in a %s", "bottle");
verify(()-> Slog.d(TAG, "msg in a bottle"));
}
@Test
- public void testD_msgFormatted_disabled() {
- disableLogging(Log.DEBUG);
-
- Slogf.d(TAG, "msg in a %s", "bottle");
-
- verify(()-> Slog.d(eq(TAG), any()), never());
- }
-
- @Test
- public void testD_msgFormattedWithThrowable_enabled() {
- enableLogging(Log.DEBUG);
-
+ public void testD_msgFormattedWithThrowable() {
Slogf.d(TAG, mThrowable, "msg in a %s", "bottle");
verify(()-> Slog.d(TAG, "msg in a bottle", mThrowable));
}
@Test
- public void testD_msgFormattedWithException_disabled() {
- disableLogging(Log.DEBUG);
-
- Slogf.d(TAG, mThrowable, "msg in a %s", "bottle");
-
- verify(()-> Slog.d(eq(TAG), any(String.class), any(Throwable.class)), never());
- }
-
- @Test
public void testI_msg() {
Slogf.i(TAG, "msg");
@@ -185,42 +128,20 @@ public final class SlogfTest {
}
@Test
- public void testI_msgFormatted_enabled() {
- enableLogging(Log.INFO);
-
+ public void testI_msgFormatted() {
Slogf.i(TAG, "msg in a %s", "bottle");
verify(()-> Slog.i(TAG, "msg in a bottle"));
}
@Test
- public void testI_msgFormatted_disabled() {
- disableLogging(Log.INFO);
-
- Slogf.i(TAG, "msg in a %s", "bottle");
-
- verify(()-> Slog.i(eq(TAG), any()), never());
- }
-
- @Test
- public void testI_msgFormattedWithThrowable_enabled() {
- enableLogging(Log.INFO);
-
+ public void testI_msgFormattedWithThrowable() {
Slogf.i(TAG, mThrowable, "msg in a %s", "bottle");
verify(()-> Slog.i(TAG, "msg in a bottle", mThrowable));
}
@Test
- public void testI_msgFormattedWithException_disabled() {
- disableLogging(Log.INFO);
-
- Slogf.i(TAG, mThrowable, "msg in a %s", "bottle");
-
- verify(()-> Slog.i(eq(TAG), any(String.class), any(Throwable.class)), never());
- }
-
- @Test
public void testW_msg() {
Slogf.w(TAG, "msg");
@@ -242,42 +163,20 @@ public final class SlogfTest {
}
@Test
- public void testW_msgFormatted_enabled() {
- enableLogging(Log.WARN);
-
+ public void testW_msgFormatted() {
Slogf.w(TAG, "msg in a %s", "bottle");
verify(()-> Slog.w(TAG, "msg in a bottle"));
}
@Test
- public void testW_msgFormatted_disabled() {
- disableLogging(Log.WARN);
-
- Slogf.w(TAG, "msg in a %s", "bottle");
-
- verify(()-> Slog.w(eq(TAG), any(String.class)), never());
- }
-
- @Test
- public void testW_msgFormattedWithThrowable_enabled() {
- enableLogging(Log.WARN);
-
+ public void testW_msgFormattedWithThrowable() {
Slogf.w(TAG, mThrowable, "msg in a %s", "bottle");
verify(()-> Slog.w(TAG, "msg in a bottle", mThrowable));
}
@Test
- public void testW_msgFormattedWithException_disabled() {
- disableLogging(Log.WARN);
-
- Slogf.w(TAG, mThrowable, "msg in a %s", "bottle");
-
- verify(()-> Slog.w(eq(TAG), any(String.class), any(Throwable.class)), never());
- }
-
- @Test
public void testE_msg() {
Slogf.e(TAG, "msg");
@@ -292,42 +191,20 @@ public final class SlogfTest {
}
@Test
- public void testE_msgFormatted_enabled() {
- enableLogging(Log.ERROR);
-
+ public void testE_msgFormatted() {
Slogf.e(TAG, "msg in a %s", "bottle");
verify(()-> Slog.e(TAG, "msg in a bottle"));
}
@Test
- public void testE_msgFormatted_disabled() {
- disableLogging(Log.ERROR);
-
- Slogf.e(TAG, "msg in a %s", "bottle");
-
- verify(()-> Slog.e(eq(TAG), any()), never());
- }
-
- @Test
- public void testE_msgFormattedWithThrowable_enabled() {
- enableLogging(Log.ERROR);
-
+ public void testE_msgFormattedWithThrowable() {
Slogf.e(TAG, mThrowable, "msg in a %s", "bottle");
verify(()-> Slog.e(TAG, "msg in a bottle", mThrowable));
}
@Test
- public void testE_msgFormattedWithException_disabled() {
- disableLogging(Log.ERROR);
-
- Slogf.e(TAG, mThrowable, "msg in a %s", "bottle");
-
- verify(()-> Slog.e(eq(TAG), any(String.class), any(Throwable.class)), never());
- }
-
- @Test
public void testWtf_msg() {
Slogf.wtf(TAG, "msg");
@@ -382,16 +259,4 @@ public final class SlogfTest {
verify(()-> Slog.wtf(TAG, "msg in a bottle", mThrowable));
}
-
- private void enableLogging(@Log.Level int level) {
- setIsLogging(level, true);
- }
-
- private void disableLogging(@Log.Level int level) {
- setIsLogging(level, false);
- }
-
- private void setIsLogging(@Log.Level int level, boolean value) {
- doReturn(value).when(() -> Slogf.isLoggable(TAG, level));
- }
}
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 3a7b9a49f161..6f26a5fe8970 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -31,6 +31,7 @@ android_test {
"services.backup",
"services.companion",
"services.core",
+ "services.credentials",
"services.devicepolicy",
"services.net",
"services.people",
@@ -115,6 +116,7 @@ android_test {
":StubTestApp",
":SuspendTestApp",
":MediaButtonReceiverHolderTestHelperApp",
+ "data/broken_shortcut.xml",
],
java_resources: [
diff --git a/services/tests/servicestests/AndroidTest.xml b/services/tests/servicestests/AndroidTest.xml
index d9676470aca3..b304968f3e69 100644
--- a/services/tests/servicestests/AndroidTest.xml
+++ b/services/tests/servicestests/AndroidTest.xml
@@ -21,6 +21,8 @@
<option name="cleanup" value="true" />
<option name="push-file" key="SimpleServiceTestApp3.apk"
value="/data/local/tmp/cts/content/SimpleServiceTestApp3.apk" />
+ <option name="push-file" key="broken_shortcut.xml"
+ value="/data/local/tmp/cts/content/broken_shortcut.xml" />
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
diff --git a/services/tests/servicestests/data/broken_shortcut.xml b/services/tests/servicestests/data/broken_shortcut.xml
new file mode 100644
index 000000000000..f2b083ddc3a0
--- /dev/null
+++ b/services/tests/servicestests/data/broken_shortcut.xml
Binary files differ
diff --git a/services/tests/servicestests/res/xml/irq_device_map_3.xml b/services/tests/servicestests/res/xml/irq_device_map_3.xml
index 498b676dd1dc..1d2a7d37d613 100644
--- a/services/tests/servicestests/res/xml/irq_device_map_3.xml
+++ b/services/tests/servicestests/res/xml/irq_device_map_3.xml
@@ -21,6 +21,6 @@
<subsystem>Alarm</subsystem>
</device>
<device name="test.wifi.device">
- <subsystem>undefined</subsystem>
+ <subsystem>Wifi</subsystem>
</device>
</irq-device-map> \ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
index 424940567da5..96eca7171af0 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
@@ -284,19 +284,31 @@ public class AccessibilityManagerServiceTest {
verify(mProxyManager).registerProxy(eq(mMockServiceClient), eq(TEST_DISPLAY),
eq(mTestableContext), anyInt(), any(), eq(mMockSecurityPolicy),
eq(mA11yms), eq(mA11yms.getTraceManager()),
- eq(mMockWindowManagerService), eq(mMockA11yWindowManager));
+ eq(mMockWindowManagerService));
}
@SmallTest
@Test
- public void testRegisterProxyWithoutPermission() throws Exception {
+ public void testRegisterProxyWithoutA11yPermission() throws Exception {
doThrow(SecurityException.class).when(mMockSecurityPolicy)
.enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY);
assertThrows(SecurityException.class,
() -> mA11yms.registerProxyForDisplay(mMockServiceClient, TEST_DISPLAY));
verify(mProxyManager, never()).registerProxy(any(), anyInt(), any(), anyInt(), any(), any(),
- any(), any(), any(), any());
+ any(), any(), any());
+ }
+
+ @SmallTest
+ @Test
+ public void testRegisterProxyWithoutDevicePermission() throws Exception {
+ doThrow(SecurityException.class).when(mMockSecurityPolicy)
+ .enforceCallingOrSelfPermission(Manifest.permission.CREATE_VIRTUAL_DEVICE);
+
+ assertThrows(SecurityException.class,
+ () -> mA11yms.registerProxyForDisplay(mMockServiceClient, TEST_DISPLAY));
+ verify(mProxyManager, never()).registerProxy(any(), anyInt(), any(), anyInt(), any(), any(),
+ any(), any(), any());
}
@SmallTest
@@ -305,7 +317,7 @@ public class AccessibilityManagerServiceTest {
assertThrows(IllegalArgumentException.class,
() -> mA11yms.registerProxyForDisplay(mMockServiceClient, Display.DEFAULT_DISPLAY));
verify(mProxyManager, never()).registerProxy(any(), anyInt(), any(), anyInt(), any(), any(),
- any(), any(), any(), any());
+ any(), any(), any());
}
@SmallTest
@@ -314,7 +326,7 @@ public class AccessibilityManagerServiceTest {
assertThrows(IllegalArgumentException.class,
() -> mA11yms.registerProxyForDisplay(mMockServiceClient, Display.INVALID_DISPLAY));
verify(mProxyManager, never()).registerProxy(any(), anyInt(), any(), anyInt(), any(), any(),
- any(), any(), any(), any());
+ any(), any(), any());
}
@SmallTest
@@ -328,7 +340,7 @@ public class AccessibilityManagerServiceTest {
@SmallTest
@Test
- public void testUnRegisterProxyWithoutPermission() throws Exception {
+ public void testUnRegisterProxyWithoutA11yPermission() {
doThrow(SecurityException.class).when(mMockSecurityPolicy)
.enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY);
@@ -339,6 +351,17 @@ public class AccessibilityManagerServiceTest {
@SmallTest
@Test
+ public void testUnRegisterProxyWithoutDevicePermission() {
+ doThrow(SecurityException.class).when(mMockSecurityPolicy)
+ .enforceCallingOrSelfPermission(Manifest.permission.CREATE_VIRTUAL_DEVICE);
+
+ assertThrows(SecurityException.class,
+ () -> mA11yms.unregisterProxyForDisplay(TEST_DISPLAY));
+ verify(mProxyManager, never()).unregisterProxy(TEST_DISPLAY);
+ }
+
+ @SmallTest
+ @Test
public void testOnMagnificationTransitionFailed_capabilitiesIsAll_fallBackToPreviousMode() {
final AccessibilityUserState userState = mA11yms.mUserStates.get(
mA11yms.getCurrentUserIdLocked());
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
index 51d3bae7d32c..306ce4dbf707 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
@@ -44,6 +44,8 @@ import android.annotation.NonNull;
import android.graphics.PointF;
import android.os.Handler;
import android.os.Message;
+import android.os.VibrationEffect;
+import android.os.Vibrator;
import android.testing.TestableContext;
import android.util.DebugUtils;
import android.view.InputDevice;
@@ -507,6 +509,91 @@ public class FullScreenMagnificationGestureHandlerTest {
verify(mWindowMagnificationPromptController).showNotificationIfNeeded();
}
+ @Test
+ public void testTransitToPanningState_scaleDifferenceOverThreshold_startDetecting() {
+ final float scale = 2.0f;
+ final float threshold = FullScreenMagnificationGestureHandler.PanningScalingState
+ .CHECK_DETECTING_PASS_PERSISTED_SCALE_THRESHOLD;
+ final float persistedScale = (1.0f + threshold) * scale + 1.0f;
+ mFullScreenMagnificationController.setScale(DISPLAY_0, persistedScale, DEFAULT_X,
+ DEFAULT_Y, /* animate= */ false,
+ AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
+ mFullScreenMagnificationController.persistScale(DISPLAY_0);
+ mFullScreenMagnificationController.setScale(DISPLAY_0, scale, DEFAULT_X,
+ DEFAULT_Y, /* animate= */ false,
+ AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
+
+ mMgh.transitionTo(mMgh.mPanningScalingState);
+
+ assertTrue(mMgh.mPanningScalingState.mDetectingPassPersistedScale);
+
+ mMgh.clearAndTransitionToStateDetecting();
+ mFullScreenMagnificationController.reset(DISPLAY_0, /* animate= */ false);
+ }
+
+ @Test
+ public void testTransitToPanningState_scaleDifferenceLessThanThreshold_doNotDetect() {
+ final float scale = 2.0f;
+ final float threshold = FullScreenMagnificationGestureHandler.PanningScalingState
+ .CHECK_DETECTING_PASS_PERSISTED_SCALE_THRESHOLD;
+ final float persistedScale = (1.0f + threshold) * scale - 0.1f;
+ mFullScreenMagnificationController.setScale(DISPLAY_0, persistedScale, DEFAULT_X,
+ DEFAULT_Y, /* animate= */ false,
+ AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
+ mFullScreenMagnificationController.persistScale(DISPLAY_0);
+ mFullScreenMagnificationController.setScale(DISPLAY_0, scale, DEFAULT_X,
+ DEFAULT_Y, /* animate= */ false,
+ AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
+
+ mMgh.transitionTo(mMgh.mPanningScalingState);
+
+ assertFalse(mMgh.mPanningScalingState.mDetectingPassPersistedScale);
+
+ mMgh.clearAndTransitionToStateDetecting();
+ mFullScreenMagnificationController.reset(DISPLAY_0, /* animate= */ false);
+ }
+
+ @Test
+ public void testPanningScaleToPersistedScale_detecting_vibrateAndClear() {
+ Vibrator vibrator = mock(Vibrator.class);
+ mContext.addMockSystemService(Vibrator.class, vibrator);
+
+ mMgh.mPanningScalingState.mDetectingPassPersistedScale = true;
+
+ final float persistedScale =
+ mFullScreenMagnificationController.getPersistedScale(DISPLAY_0);
+
+ mMgh.transitionTo(mMgh.mPanningScalingState);
+ mMgh.mPanningScalingState.setScaleAndClearIfNeeded(persistedScale, DEFAULT_X, DEFAULT_Y);
+
+ verify(vibrator).vibrate(any(VibrationEffect.class));
+ assertFalse(mMgh.mPanningScalingState.mScaling);
+
+ mMgh.clearAndTransitionToStateDetecting();
+ mFullScreenMagnificationController.reset(DISPLAY_0, /* animate= */ false);
+ }
+
+ @Test
+ public void testPanningScaleOverThreshold_notDetecting_startDetecting() {
+ final float persistedScale =
+ mFullScreenMagnificationController.getPersistedScale(DISPLAY_0);
+
+ mFullScreenMagnificationController.setScale(DISPLAY_0, persistedScale, DEFAULT_X,
+ DEFAULT_Y, /* animate= */ false,
+ AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
+ mMgh.transitionTo(mMgh.mPanningScalingState);
+
+ final float threshold = FullScreenMagnificationGestureHandler.PanningScalingState
+ .CHECK_DETECTING_PASS_PERSISTED_SCALE_THRESHOLD;
+ final float scale = (1.0f + threshold) * persistedScale + 1.0f;
+ mMgh.mPanningScalingState.setScaleAndClearIfNeeded(scale, DEFAULT_X, DEFAULT_Y);
+
+ assertTrue(mMgh.mPanningScalingState.mDetectingPassPersistedScale);
+
+ mMgh.clearAndTransitionToStateDetecting();
+ mFullScreenMagnificationController.reset(DISPLAY_0, /* animate= */ false);
+ }
+
private void assertActionsInOrder(List<MotionEvent> actualEvents,
List<Integer> expectedActions) {
assertTrue(actualEvents.size() == expectedActions.size());
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
index 1298e7bbd344..24b003c2c011 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
@@ -24,6 +24,7 @@ import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.nullable;
import static org.mockito.Mockito.times;
@@ -37,6 +38,7 @@ import android.accounts.AccountManagerInternal;
import android.accounts.CantAddAccountActivity;
import android.accounts.IAccountManagerResponse;
import android.app.AppOpsManager;
+import android.app.BroadcastOptions;
import android.app.INotificationManager;
import android.app.PropertyInvalidatedCache;
import android.app.admin.DevicePolicyManager;
@@ -171,6 +173,16 @@ public class AccountManagerServiceTest extends AndroidTestCase {
setContext(mockContext);
mTestInjector = new TestInjector(realTestContext, mockContext, mMockNotificationManager);
mAms = new AccountManagerService(mTestInjector);
+ doAnswer(invocation -> {
+ final Intent intent = invocation.getArgument(0);
+ final Bundle options = invocation.getArgument(3);
+ if (AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION.endsWith(intent.getAction())) {
+ final BroadcastOptions bOptions = new BroadcastOptions(options);
+ assertEquals(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT,
+ bOptions.getDeliveryGroupPolicy());
+ }
+ return null;
+ }).when(mMockContext).sendBroadcastAsUser(any(), any(), any(), any());
}
@Override
@@ -3142,7 +3154,7 @@ public class AccountManagerServiceTest extends AndroidTestCase {
mAccountRemovedBroadcasts = 0;
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
verify(mMockContext, atLeast(expectedBroadcasts)).sendBroadcastAsUser(captor.capture(),
- any(UserHandle.class));
+ any(UserHandle.class), any(), any());
for (Intent intent : captor.getAllValues()) {
if (AccountManager.ACTION_VISIBLE_ACCOUNTS_CHANGED.equals(intent.getAction())) {
mVisibleAccountsChangedBroadcasts++;
@@ -3499,7 +3511,19 @@ public class AccountManagerServiceTest extends AndroidTestCase {
@Override
public void sendBroadcastAsUser(Intent intent, UserHandle user) {
- mMockContext.sendBroadcastAsUser(intent, user);
+ sendBroadcastAsUser(intent, user, null, null);
+ }
+
+ @Override
+ public void sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission,
+ Bundle options) {
+ mMockContext.sendBroadcastAsUser(intent, user, receiverPermission, options);
+ }
+
+ @Override
+ public Intent registerReceiver(BroadcastReceiver receiver,
+ IntentFilter filter, String broadcastPermission, Handler scheduler) {
+ return mMockContext.registerReceiver(receiver, filter, broadcastPermission, scheduler);
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
index 93dfee6f2da4..8c7b0c5a569a 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
@@ -528,7 +528,7 @@ public class ActivityManagerServiceTest {
ActivityManager.PROCESS_CAPABILITY_NONE,
ActivityManager.PROCESS_CAPABILITY_NONE,
ActivityManager.PROCESS_CAPABILITY_NONE,
- ActivityManager.PROCESS_CAPABILITY_NETWORK,
+ ActivityManager.PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK,
};
final Map<Integer, ChangeRecord> changeItems = new HashMap<>();
for (int i = 0; i < changesForPendingUidRecords.length; ++i) {
diff --git a/services/tests/servicestests/src/com/android/server/am/OomAdjusterTests.java b/services/tests/servicestests/src/com/android/server/am/OomAdjusterTests.java
index 4412cfe4a3b5..8cbed2c7ffb8 100644
--- a/services/tests/servicestests/src/com/android/server/am/OomAdjusterTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/OomAdjusterTests.java
@@ -305,60 +305,4 @@ public class OomAdjusterTests {
assertEquals("Interaction event time was not updated correctly.",
interactionEventTime, mProcessRecord.mState.getInteractionEventTime());
}
-
- private void updateShortFgsOwner(int uid, int pid, boolean add) {
- sService.mOomAdjuster.updateShortFgsOwner(uid, pid, add);
- }
-
- private void assertHasUidShortForegroundService(int uid, boolean expected) {
- assertEquals(expected, sService.mOomAdjuster.hasUidShortForegroundService(uid));
- }
-
- @Test
- public void testHasUidShortForegroundService() {
- assertHasUidShortForegroundService(1, false);
- assertHasUidShortForegroundService(2, false);
- assertHasUidShortForegroundService(3, false);
- assertHasUidShortForegroundService(100, false);
- assertHasUidShortForegroundService(101, false);
-
- updateShortFgsOwner(1, 100, true);
- assertHasUidShortForegroundService(1, true);
- assertHasUidShortForegroundService(100, false);
- assertHasUidShortForegroundService(2, false);
-
- updateShortFgsOwner(1, 101, true);
- assertHasUidShortForegroundService(1, true);
- assertHasUidShortForegroundService(101, false);
- assertHasUidShortForegroundService(2, false);
-
- updateShortFgsOwner(2, 200, true);
- assertHasUidShortForegroundService(1, true);
- assertHasUidShortForegroundService(2, true);
- assertHasUidShortForegroundService(200, false);
-
- updateShortFgsOwner(1, 101, false);
- assertHasUidShortForegroundService(1, true);
- assertHasUidShortForegroundService(2, true);
-
- updateShortFgsOwner(1, 99, false); // unused PID
- assertHasUidShortForegroundService(1, true);
- assertHasUidShortForegroundService(2, true);
-
- updateShortFgsOwner(1, 100, false);
- assertHasUidShortForegroundService(1, false);
- assertHasUidShortForegroundService(2, true);
-
- updateShortFgsOwner(1, 100, true);
- assertHasUidShortForegroundService(1, true);
- assertHasUidShortForegroundService(2, true);
-
- updateShortFgsOwner(2, 200, false);
- assertHasUidShortForegroundService(1, true);
- assertHasUidShortForegroundService(2, false);
-
- updateShortFgsOwner(2, 201, true);
- assertHasUidShortForegroundService(1, true);
- assertHasUidShortForegroundService(2, true);
- }
}
diff --git a/services/tests/servicestests/src/com/android/server/am/UidObserverControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UidObserverControllerTest.java
index 8a3f246fd656..f788c92b24b2 100644
--- a/services/tests/servicestests/src/com/android/server/am/UidObserverControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UidObserverControllerTest.java
@@ -18,8 +18,8 @@ package com.android.server.am;
import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
-import static android.app.ActivityManager.PROCESS_CAPABILITY_NETWORK;
import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
import static android.app.ActivityManager.PROCESS_STATE_CACHED_RECENT;
import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
@@ -185,10 +185,10 @@ public class UidObserverControllerTest {
verifyNoMoreInteractions(observer2);
addPendingChange(TEST_UID1, UidRecord.CHANGE_PROCSTATE | UidRecord.CHANGE_CAPABILITY,
- PROCESS_STATE_RECEIVER, 111, PROCESS_CAPABILITY_NETWORK, false);
+ PROCESS_STATE_RECEIVER, 111, PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK, false);
mUidObserverController.dispatchUidsChanged();
verify(observer2).onUidStateChanged(TEST_UID1, PROCESS_STATE_RECEIVER,
- 111, PROCESS_CAPABILITY_NETWORK);
+ 111, PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK);
verifyNoMoreInteractions(observer1);
verifyNoMoreInteractions(observer2);
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
index 4c898b0c4d58..e9d82696affc 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
@@ -37,9 +37,12 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
+import android.hardware.biometrics.AuthenticateOptions;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
+import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.IBiometricService;
+import android.hardware.fingerprint.Fingerprint;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
@@ -48,6 +51,7 @@ import android.platform.test.annotations.Presubmit;
import android.testing.AndroidTestingRunner;
import android.testing.TestableContext;
import android.testing.TestableLooper;
+import android.util.Slog;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -58,6 +62,8 @@ import com.android.server.biometrics.log.BiometricContext;
import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.nano.BiometricSchedulerProto;
import com.android.server.biometrics.nano.BiometricsProto;
+import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils;
+import com.android.server.biometrics.sensors.fingerprint.aidl.AidlSession;
import org.junit.Before;
import org.junit.Rule;
@@ -67,6 +73,9 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import java.util.function.Supplier;
@Presubmit
@@ -78,6 +87,9 @@ public class BiometricSchedulerTest {
private static final String TAG = "BiometricSchedulerTest";
private static final int TEST_SENSOR_ID = 1;
private static final int LOG_NUM_RECENT_OPERATIONS = 2;
+ private static final Fingerprint TEST_FINGERPRINT = new Fingerprint("" /* name */,
+ 1 /* fingerId */, TEST_SENSOR_ID);
+
@Rule
public final TestableContext mContext = new TestableContext(
InstrumentationRegistry.getContext(), null);
@@ -673,6 +685,56 @@ public class BiometricSchedulerTest {
}
+ @Test
+ public void testTwoInternalCleanupOps_withFirstFavorHalEnrollment() throws Exception {
+ final String owner = "test.owner";
+ final int userId = 1;
+ final Supplier<Object> daemon = () -> mock(AidlSession.class);
+ final FingerprintUtils utils = mock(FingerprintUtils.class);
+ final Map<Integer, Long> authenticatorIds = new HashMap<>();
+ final ClientMonitorCallback callback0 = mock(ClientMonitorCallback.class);
+ final ClientMonitorCallback callback1 = mock(ClientMonitorCallback.class);
+ final ClientMonitorCallback callback2 = mock(ClientMonitorCallback.class);
+
+ final TestInternalCleanupClient client1 = new
+ TestInternalCleanupClient(mContext, daemon, userId,
+ owner, TEST_SENSOR_ID, mock(BiometricLogger.class),
+ mBiometricContext, utils, authenticatorIds);
+ final TestInternalCleanupClient client2 = new
+ TestInternalCleanupClient(mContext, daemon, userId,
+ owner, TEST_SENSOR_ID, mock(BiometricLogger.class),
+ mBiometricContext, utils, authenticatorIds);
+
+ //add initial start client to scheduler, so later clients will be on pending operation queue
+ final TestHalClientMonitor startClient = new TestHalClientMonitor(mContext, mToken,
+ daemon);
+ mScheduler.scheduleClientMonitor(startClient, callback0);
+
+ //add first cleanup client which favors enrollments from HAL
+ client1.setFavorHalEnrollments();
+ mScheduler.scheduleClientMonitor(client1, callback1);
+ assertEquals(1, mScheduler.mPendingOperations.size());
+
+ when(utils.getBiometricsForUser(mContext, userId)).thenAnswer(i ->
+ new ArrayList<>(client1.getFingerprints()));
+
+ //add second cleanup client
+ mScheduler.scheduleClientMonitor(client2, callback2);
+
+ //finish the start client, so other pending clients are processed
+ startClient.getCallback().onClientFinished(startClient, true);
+
+ waitForIdle();
+
+ assertTrue(client1.isAlreadyDone());
+ assertTrue(client2.isAlreadyDone());
+ assertNull(mScheduler.mCurrentOperation);
+ verify(utils, never()).removeBiometricForUser(mContext, userId,
+ TEST_FINGERPRINT.getBiometricId());
+ assertEquals(1, client1.getFingerprints().size());
+ }
+
+
private BiometricSchedulerProto getDump(boolean clearSchedulerBuffer) throws Exception {
return BiometricSchedulerProto.parseFrom(mScheduler.dumpProtoState(clearSchedulerBuffer));
}
@@ -681,7 +743,37 @@ public class BiometricSchedulerTest {
TestableLooper.get(this).processAllMessages();
}
- private static class TestAuthenticationClient extends AuthenticationClient<Object> {
+ private static class TestAuthenticateOptions implements AuthenticateOptions {
+ @Override
+ public int getUserId() {
+ return 0;
+ }
+
+ @Override
+ public int getSensorId() {
+ return TEST_SENSOR_ID;
+ }
+
+ @Override
+ public int getDisplayState() {
+ return DISPLAY_STATE_UNKNOWN;
+ }
+
+ @NonNull
+ @Override
+ public String getOpPackageName() {
+ return "some.test.name";
+ }
+
+ @Nullable
+ @Override
+ public String getAttributionTag() {
+ return null;
+ }
+ }
+
+ private static class TestAuthenticationClient
+ extends AuthenticationClient<Object, TestAuthenticateOptions> {
boolean mStartedHal = false;
boolean mStoppedHal = false;
boolean mDestroyed = false;
@@ -700,12 +792,13 @@ public class BiometricSchedulerTest {
@NonNull Supplier<Object> lazyDaemon, @NonNull IBinder token,
@NonNull ClientMonitorCallbackConverter listener, int cookie,
@NonNull BiometricContext biometricContext) {
- super(context, lazyDaemon, token, listener, 0 /* targetUserId */, 0 /* operationId */,
- false /* restricted */, TAG, cookie, false /* requireConfirmation */,
- TEST_SENSOR_ID, mock(BiometricLogger.class), biometricContext,
+ super(context, lazyDaemon, token, listener, 0 /* operationId */,
+ false /* restricted */, new TestAuthenticateOptions(), cookie,
+ false /* requireConfirmation */,
+ mock(BiometricLogger.class), biometricContext,
true /* isStrongBiometric */, null /* taskStackListener */,
null /* lockoutTracker */, false /* isKeyguard */,
- true /* shouldVibrate */, false /* isKeyguardBypassEnabled */,
+ true /* shouldVibrate */,
0 /* sensorStrength */);
}
@@ -835,4 +928,90 @@ public class BiometricSchedulerTest {
mDestroyed = true;
}
}
+
+ private static class TestInternalEnumerateClient extends InternalEnumerateClient<Object> {
+ private static final String TAG = "TestInternalEnumerateClient";
+
+
+ protected TestInternalEnumerateClient(@NonNull Context context,
+ @NonNull Supplier<Object> lazyDaemon, @NonNull IBinder token, int userId,
+ @NonNull String owner, @NonNull List<Fingerprint> enrolledList,
+ @NonNull BiometricUtils<Fingerprint> utils, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext) {
+ super(context, lazyDaemon, token, userId, owner, enrolledList, utils, sensorId,
+ logger, biometricContext);
+ }
+
+ @Override
+ protected void startHalOperation() {
+ Slog.d(TAG, "TestInternalEnumerateClient#startHalOperation");
+ onEnumerationResult(TEST_FINGERPRINT, 0 /* remaining */);
+ }
+ }
+
+ private static class TestRemovalClient extends RemovalClient<Fingerprint, Object> {
+ private static final String TAG = "TestRemovalClient";
+
+ TestRemovalClient(@NonNull Context context,
+ @NonNull Supplier<Object> lazyDaemon, @NonNull IBinder token,
+ @Nullable ClientMonitorCallbackConverter listener, int[] biometricIds, int userId,
+ @NonNull String owner, @NonNull BiometricUtils<Fingerprint> utils, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
+ @NonNull Map<Integer, Long> authenticatorIds) {
+ super(context, lazyDaemon, token, listener, userId, owner, utils, sensorId,
+ logger, biometricContext, authenticatorIds);
+ }
+
+ @Override
+ protected void startHalOperation() {
+ Slog.d(TAG, "Removing template from hw");
+ onRemoved(TEST_FINGERPRINT, 0);
+ }
+ }
+
+ private static class TestInternalCleanupClient extends
+ InternalCleanupClient<Fingerprint, Object> {
+ private List<Fingerprint> mFingerprints = new ArrayList<>();
+
+ TestInternalCleanupClient(@NonNull Context context,
+ @NonNull Supplier<Object> lazyDaemon,
+ int userId, @NonNull String owner, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
+ @NonNull FingerprintUtils utils, @NonNull Map<Integer, Long> authenticatorIds) {
+ super(context, lazyDaemon, userId, owner, sensorId, logger, biometricContext,
+ utils, authenticatorIds);
+ }
+
+ @Override
+ protected InternalEnumerateClient<Object> getEnumerateClient(Context context,
+ Supplier<Object> lazyDaemon, IBinder token, int userId, String owner,
+ List<Fingerprint> enrolledList, BiometricUtils<Fingerprint> utils, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext) {
+ return new TestInternalEnumerateClient(context, lazyDaemon, token, userId, owner,
+ enrolledList, utils, sensorId,
+ logger.swapAction(context, BiometricsProtoEnums.ACTION_ENUMERATE),
+ biometricContext);
+ }
+
+ @Override
+ protected RemovalClient<Fingerprint, Object> getRemovalClient(Context context,
+ Supplier<Object> lazyDaemon, IBinder token, int biometricId, int userId,
+ String owner, BiometricUtils<Fingerprint> utils, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
+ Map<Integer, Long> authenticatorIds) {
+ return new TestRemovalClient(context, lazyDaemon, token, null,
+ new int[]{biometricId}, userId, owner, utils, sensorId, logger,
+ biometricContext, authenticatorIds);
+ }
+
+ @Override
+ protected void onAddUnknownTemplate(int userId,
+ @NonNull BiometricAuthenticator.Identifier identifier) {
+ mFingerprints.add((Fingerprint) identifier);
+ }
+
+ public List<Fingerprint> getFingerprints() {
+ return mFingerprints;
+ }
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java
index 139910ba8926..3ff802c0125c 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java
@@ -33,6 +33,7 @@ import android.content.ComponentName;
import android.hardware.biometrics.common.ICancellationSignal;
import android.hardware.biometrics.face.ISession;
import android.hardware.face.Face;
+import android.hardware.face.FaceAuthenticateOptions;
import android.os.IBinder;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
@@ -153,14 +154,18 @@ public class FaceAuthenticationClientTest {
when(mHal.getInterfaceVersion()).thenReturn(version);
final AidlSession aidl = new AidlSession(version, mHal, USER_ID, mHalSessionCallback);
+ final FaceAuthenticateOptions options = new FaceAuthenticateOptions.Builder()
+ .setOpPackageName("test-owner")
+ .setUserId(5)
+ .setSensorId(9)
+ .build();
return new FaceAuthenticationClient(mContext, () -> aidl, mToken,
- 2 /* requestId */, mClientMonitorCallbackConverter, 5 /* targetUserId */, OP_ID,
- false /* restricted */, "test-owner", 4 /* cookie */,
- false /* requireConfirmation */, 9 /* sensorId */,
+ 2 /* requestId */, mClientMonitorCallbackConverter, OP_ID,
+ false /* restricted */, options, 4 /* cookie */,
+ false /* requireConfirmation */,
mBiometricLogger, mBiometricContext, true /* isStrongBiometric */,
mUsageStats, null /* mLockoutCache */, false /* allowBackgroundAuthentication */,
- false /* isKeyguardBypassEnabled */, null /* sensorPrivacyManager */,
- 0 /* biometricStrength */) {
+ null /* sensorPrivacyManager */, 0 /* biometricStrength */) {
@Override
protected ActivityTaskManager getActivityTaskManager() {
return mActivityTaskManager;
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceDetectClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceDetectClientTest.java
index e0fdb8cfc74e..c4c550549f73 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceDetectClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceDetectClientTest.java
@@ -25,6 +25,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.hardware.biometrics.face.ISession;
+import android.hardware.face.FaceAuthenticateOptions;
import android.os.IBinder;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
@@ -112,8 +113,13 @@ public class FaceDetectClientTest {
final AidlSession aidl = new AidlSession(version, mHal, USER_ID, mHalSessionCallback);
return new FaceDetectClient(mContext, () -> aidl, mToken,
- 99 /* requestId */, mClientMonitorCallbackConverter, USER_ID,
- "own-it", 5 /* sensorId */, mBiometricLogger, mBiometricContext,
+ 99 /* requestId */, mClientMonitorCallbackConverter,
+ new FaceAuthenticateOptions.Builder()
+ .setUserId(USER_ID)
+ .setSensorId(5)
+ .setOpPackageName("own-it")
+ .build(),
+ mBiometricLogger, mBiometricContext,
false /* isStrongBiometric */, null /* sensorPrivacyManager */);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/BiometricStateCallbackTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/BiometricStateCallbackTest.java
index 3b66eaba6129..54d6478ecd4a 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/BiometricStateCallbackTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/BiometricStateCallbackTest.java
@@ -144,7 +144,7 @@ public class BiometricStateCallbackTest {
@Test
public void testAuthentication_enrollmentCallbackNeverNotified() {
- AuthenticationClient<?> client = mock(AuthenticationClient.class);
+ AuthenticationClient<?, ?> client = mock(AuthenticationClient.class);
mCallback.onClientFinished(client, true /* success */);
verify(mBiometricStateListener, never()).onEnrollmentsChanged(anyInt(), anyInt(),
anyBoolean());
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceTest.java
index a4048a27dfb5..25a700a5275f 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceTest.java
@@ -16,24 +16,35 @@
package com.android.server.biometrics.sensors.fingerprint;
+import static android.Manifest.permission.USE_BIOMETRIC;
import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
+import static android.app.AppOpsManager.OP_USE_BIOMETRIC;
+import static android.app.AppOpsManager.OP_USE_FINGERPRINT;
+import static android.hardware.biometrics.SensorProperties.STRENGTH_STRONG;
+import static android.hardware.fingerprint.FingerprintManager.SENSOR_ID_ANY;
+import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_REAR;
+import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_OPTICAL;
+
+import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.AppOpsManager;
import android.content.pm.PackageManager;
import android.hardware.biometrics.IBiometricService;
-import android.hardware.biometrics.common.CommonProps;
-import android.hardware.biometrics.common.SensorStrength;
-import android.hardware.biometrics.fingerprint.FingerprintSensorType;
-import android.hardware.biometrics.fingerprint.IFingerprint;
-import android.hardware.biometrics.fingerprint.SensorLocation;
-import android.hardware.biometrics.fingerprint.SensorProps;
+import android.hardware.fingerprint.FingerprintAuthenticateOptions;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
+import android.hardware.fingerprint.IFingerprintServiceReceiver;
+import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
import android.provider.Settings;
import android.testing.TestableContext;
@@ -44,10 +55,13 @@ import androidx.test.platform.app.InstrumentationRegistry;
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.internal.util.test.FakeSettingsProviderRule;
import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.sensors.fingerprint.aidl.FingerprintProvider;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
@@ -64,6 +78,8 @@ public class FingerprintServiceTest {
private static final int ID_VIRTUAL = 6;
private static final String NAME_DEFAULT = "default";
private static final String NAME_VIRTUAL = "virtual";
+ private static final List<FingerprintSensorPropertiesInternal> HIDL_AUTHENTICATORS =
+ List.of();
@Rule
public final MockitoRule mMockito = MockitoJUnit.rule();
@@ -74,47 +90,80 @@ public class FingerprintServiceTest {
public final FakeSettingsProviderRule mSettingsRule = FakeSettingsProvider.rule();
@Mock
+ private AppOpsManager mAppOpsManager;
+ @Mock
private BiometricContext mBiometricContext;
@Mock
private IBiometricService mIBiometricService;
@Mock
- private IFingerprint mIFingerprintDefault;
+ private FingerprintProvider mFingerprintDefault;
@Mock
- private IFingerprint mIFingerprintVirtual;
-
- private final SensorProps mSensorPropsDefault = createProps(ID_DEFAULT,
- SensorStrength.STRONG, FingerprintSensorType.POWER_BUTTON);
- private final SensorProps mSensorPropsVirtual = createProps(ID_VIRTUAL,
- SensorStrength.STRONG, FingerprintSensorType.UNDER_DISPLAY_OPTICAL);
+ private FingerprintProvider mFingerprintVirtual;
+ @Mock
+ private IFingerprintServiceReceiver mServiceReceiver;
+ @Mock
+ private IBinder mToken;
+
+ @Captor
+ private ArgumentCaptor<FingerprintAuthenticateOptions> mAuthenticateOptionsCaptor;
+
+ private final FingerprintSensorPropertiesInternal mSensorPropsDefault =
+ new FingerprintSensorPropertiesInternal(ID_DEFAULT, STRENGTH_STRONG,
+ 2 /* maxEnrollmentsPerUser */,
+ List.of(),
+ TYPE_REAR,
+ false /* resetLockoutRequiresHardwareAuthToken */);
+ private final FingerprintSensorPropertiesInternal mSensorPropsVirtual =
+ new FingerprintSensorPropertiesInternal(ID_VIRTUAL, STRENGTH_STRONG,
+ 2 /* maxEnrollmentsPerUser */,
+ List.of(),
+ TYPE_UDFPS_OPTICAL,
+ false /* resetLockoutRequiresHardwareAuthToken */);
private FingerprintService mService;
@Before
public void setup() throws Exception {
- when(mIFingerprintDefault.getSensorProps()).thenReturn(
- new SensorProps[]{mSensorPropsDefault});
- when(mIFingerprintVirtual.getSensorProps()).thenReturn(
- new SensorProps[]{mSensorPropsVirtual});
-
- mContext.getTestablePermissions().setPermission(
- USE_BIOMETRIC_INTERNAL, PackageManager.PERMISSION_GRANTED);
+ when(mFingerprintDefault.getSensorProperties()).thenReturn(List.of(mSensorPropsDefault));
+ when(mFingerprintVirtual.getSensorProperties()).thenReturn(List.of(mSensorPropsVirtual));
+ when(mFingerprintDefault.containsSensor(anyInt()))
+ .thenAnswer(i -> i.getArguments()[0].equals(ID_DEFAULT));
+ when(mFingerprintVirtual.containsSensor(anyInt()))
+ .thenAnswer(i -> i.getArguments()[0].equals(ID_VIRTUAL));
+
+ mContext.addMockSystemService(AppOpsManager.class, mAppOpsManager);
+ for (int permission : List.of(OP_USE_BIOMETRIC, OP_USE_FINGERPRINT)) {
+ when(mAppOpsManager.noteOp(eq(permission), anyInt(), any(), any(), any()))
+ .thenReturn(AppOpsManager.MODE_ALLOWED);
+ }
+
+ for (String permission : List.of(USE_BIOMETRIC, USE_BIOMETRIC_INTERNAL)) {
+ mContext.getTestablePermissions().setPermission(
+ permission, PackageManager.PERMISSION_GRANTED);
+ }
}
private void initServiceWith(String... aidlInstances) {
mService = new FingerprintService(mContext, mBiometricContext,
() -> mIBiometricService,
() -> aidlInstances,
- (fqName) -> {
- if (fqName.endsWith(NAME_DEFAULT)) return mIFingerprintDefault;
- if (fqName.endsWith(NAME_VIRTUAL)) return mIFingerprintVirtual;
+ (name) -> {
+ if (NAME_DEFAULT.equals(name)) return mFingerprintDefault;
+ if (NAME_VIRTUAL.equals(name)) return mFingerprintVirtual;
return null;
});
}
+ private void initServiceWithAndWait(String... aidlInstances) throws Exception {
+ initServiceWith(aidlInstances);
+ mService.mServiceWrapper.registerAuthenticators(HIDL_AUTHENTICATORS);
+ waitForRegistration();
+ }
+
@Test
public void registerAuthenticators_defaultOnly() throws Exception {
initServiceWith(NAME_DEFAULT, NAME_VIRTUAL);
- mService.mServiceWrapper.registerAuthenticators(List.of());
+ mService.mServiceWrapper.registerAuthenticators(HIDL_AUTHENTICATORS);
waitForRegistration();
verify(mIBiometricService).registerAuthenticator(eq(ID_DEFAULT), anyInt(), anyInt(), any());
@@ -126,7 +175,7 @@ public class FingerprintServiceTest {
Settings.Secure.putInt(mSettingsRule.mockContentResolver(mContext),
Settings.Secure.BIOMETRIC_VIRTUAL_ENABLED, 1);
- mService.mServiceWrapper.registerAuthenticators(List.of());
+ mService.mServiceWrapper.registerAuthenticators(HIDL_AUTHENTICATORS);
waitForRegistration();
verify(mIBiometricService).registerAuthenticator(eq(ID_VIRTUAL), anyInt(), anyInt(), any());
@@ -136,7 +185,7 @@ public class FingerprintServiceTest {
public void registerAuthenticators_virtualAlwaysWhenNoOther() throws Exception {
initServiceWith(NAME_VIRTUAL);
- mService.mServiceWrapper.registerAuthenticators(List.of());
+ mService.mServiceWrapper.registerAuthenticators(HIDL_AUTHENTICATORS);
waitForRegistration();
verify(mIBiometricService).registerAuthenticator(eq(ID_VIRTUAL), anyInt(), anyInt(), any());
@@ -155,13 +204,47 @@ public class FingerprintServiceTest {
latch.await(5, TimeUnit.SECONDS);
}
- private static SensorProps createProps(int id, byte strength, byte type) {
- final SensorProps props = new SensorProps();
- props.commonProps = new CommonProps();
- props.commonProps.sensorId = id;
- props.commonProps.sensorStrength = strength;
- props.sensorType = type;
- props.sensorLocations = new SensorLocation[]{new SensorLocation()};
- return props;
+ @Test
+ public void authenticateWithDefaultSensorId() throws Exception {
+ initServiceWithAndWait(NAME_DEFAULT, NAME_VIRTUAL);
+
+ final long operationId = 2;
+ mService.mServiceWrapper.authenticate(mToken, operationId, mServiceReceiver,
+ new FingerprintAuthenticateOptions.Builder()
+ .setSensorId(SENSOR_ID_ANY)
+ .build());
+
+ final FingerprintAuthenticateOptions options =
+ verifyAuthenticateWithNewRequestId(mFingerprintDefault, operationId);
+ assertThat(options.getSensorId()).isEqualTo(ID_DEFAULT);
+ verifyNoAuthenticate(mFingerprintVirtual);
+ }
+
+
+ private FingerprintAuthenticateOptions verifyAuthenticateWithNewRequestId(
+ FingerprintProvider provider, long operationId) {
+ return verifyAuthenticateWithNewRequestId(
+ provider, operationId, true /* shouldSchedule */);
+ }
+
+ private void verifyNoAuthenticate(FingerprintProvider provider) {
+ verifyAuthenticateWithNewRequestId(
+ provider, 0 /* operationId */, false /* shouldSchedule */);
+ }
+
+ private FingerprintAuthenticateOptions verifyAuthenticateWithNewRequestId(
+ FingerprintProvider provider, long operationId, boolean shouldSchedule) {
+ verify(provider, shouldSchedule ? times(1) : never())
+ .scheduleAuthenticate(eq(mToken), eq(operationId), anyInt(), any(),
+ mAuthenticateOptionsCaptor.capture(), anyBoolean(), anyInt(),
+ anyBoolean());
+ verify(provider, never()).scheduleAuthenticate(eq(mToken), anyLong(),
+ anyInt(), any(), mAuthenticateOptionsCaptor.capture(), anyLong(),
+ anyBoolean(), anyInt(), anyBoolean());
+
+ if (shouldSchedule) {
+ return mAuthenticateOptionsCaptor.getValue();
+ }
+ return null;
}
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
index 99f7905a9f70..f0f975ccf5ff 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
@@ -41,6 +41,7 @@ import android.hardware.biometrics.common.OperationContext;
import android.hardware.biometrics.fingerprint.ISession;
import android.hardware.biometrics.fingerprint.PointerContext;
import android.hardware.fingerprint.Fingerprint;
+import android.hardware.fingerprint.FingerprintAuthenticateOptions;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.ISidefpsController;
import android.hardware.fingerprint.IUdfpsOverlayController;
@@ -414,11 +415,16 @@ public class FingerprintAuthenticationClientTest {
when(mHal.getInterfaceVersion()).thenReturn(version);
final AidlSession aidl = new AidlSession(version, mHal, USER_ID, mHalSessionCallback);
+ final FingerprintAuthenticateOptions options = new FingerprintAuthenticateOptions.Builder()
+ .setOpPackageName("test-owner")
+ .setUserId(5)
+ .setSensorId(9)
+ .build();
return new FingerprintAuthenticationClient(mContext, () -> aidl, mToken,
- REQUEST_ID, mClientMonitorCallbackConverter, 5 /* targetUserId */, OP_ID,
- false /* restricted */, "test-owner", 4 /* cookie */,
+ REQUEST_ID, mClientMonitorCallbackConverter, OP_ID,
+ false /* restricted */, options, 4 /* cookie */,
false /* requireConfirmation */,
- 9 /* sensorId */, mBiometricLogger, mBiometricContext,
+ mBiometricLogger, mBiometricContext,
true /* isStrongBiometric */,
null /* taskStackListener */, null /* lockoutCache */,
mUdfpsOverlayController, mSideFpsController, null, allowBackgroundAuthentication,
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClientTest.java
index 2dbd8f69d694..e741e446da85 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClientTest.java
@@ -25,6 +25,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.hardware.biometrics.fingerprint.ISession;
+import android.hardware.fingerprint.FingerprintAuthenticateOptions;
import android.hardware.fingerprint.IUdfpsOverlayController;
import android.os.IBinder;
import android.os.RemoteException;
@@ -117,8 +118,13 @@ public class FingerprintDetectClientTest {
final AidlSession aidl = new AidlSession(version, mHal, USER_ID, mHalSessionCallback);
return new FingerprintDetectClient(mContext, () -> aidl, mToken,
- 6 /* requestId */, mClientMonitorCallbackConverter, 2 /* userId */,
- "a-test", 1 /* sensorId */, mBiometricLogger, mBiometricContext,
+ 6 /* requestId */, mClientMonitorCallbackConverter,
+ new FingerprintAuthenticateOptions.Builder()
+ .setUserId(2)
+ .setSensorId(1)
+ .setOpPackageName("a-test")
+ .build(),
+ mBiometricLogger, mBiometricContext,
mUdfpsOverlayController, null, true /* isStrongBiometric */);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java
index 26524d7df7c3..7646c401193f 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java
@@ -273,16 +273,6 @@ public class FingerprintEnrollClientTest {
showHideOverlay(c -> c.onEnrollResult(new Fingerprint("", 1, 1), 0));
}
- @Test
- public void testPowerPressForwardsAcquireMessage() throws RemoteException {
- final FingerprintEnrollClient client = createClient();
- client.start(mCallback);
- client.onPowerPressed();
-
- verify(mClientMonitorCallbackConverter).onAcquired(anyInt(),
- eq(FINGERPRINT_ACQUIRED_POWER_PRESSED), anyInt());
- }
-
private void showHideOverlay(Consumer<FingerprintEnrollClient> block)
throws RemoteException {
final FingerprintEnrollClient client = createClient();
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClientTest.java
index f0d8616ece9f..580644347c84 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClientTest.java
@@ -164,10 +164,9 @@ public class FingerprintInternalCleanupClientTest {
}
protected FingerprintInternalCleanupClient createClient() {
- final List<Fingerprint> enrollments = new ArrayList<>();
final Map<Integer, Long> authenticatorIds = new HashMap<>();
return new FingerprintInternalCleanupClient(mContext, () -> mAidlSession, 2 /* userId */,
- "the.test.owner", SENSOR_ID, mLogger, mBiometricContext, enrollments,
+ "the.test.owner", SENSOR_ID, mLogger, mBiometricContext,
mFingerprintUtils, authenticatorIds) {
@Override
protected void onAddUnknownTemplate(int userId,
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java
index 760ed9be6234..7642e7bc3b91 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java
@@ -87,7 +87,7 @@ public class InputControllerTest {
// Allow virtual devices to be created on the looper thread for testing.
final InputController.DeviceCreationThreadVerifier threadVerifier = () -> true;
- mInputController = new InputController(new Object(), mNativeWrapperMock,
+ mInputController = new InputController(mNativeWrapperMock,
new Handler(TestableLooper.get(this).getLooper()),
InstrumentationRegistry.getTargetContext().getSystemService(WindowManager.class),
threadVerifier);
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/SensorControllerTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/SensorControllerTest.java
index 6431e88b1acb..1259d7189a6d 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/SensorControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/SensorControllerTest.java
@@ -81,7 +81,7 @@ public class SensorControllerTest {
@Test
public void createSensor_invalidHandle_throwsException() {
doReturn(/* handle= */0).when(mSensorManagerInternalMock).createRuntimeSensor(
- anyInt(), anyInt(), anyString(), anyString(), any());
+ anyInt(), anyInt(), anyString(), anyString(), anyInt(), any());
Throwable thrown = assertThrows(
RuntimeException.class,
@@ -138,7 +138,7 @@ public class SensorControllerTest {
private void doCreateSensorSuccessfully() {
doReturn(SENSOR_HANDLE).when(mSensorManagerInternalMock).createRuntimeSensor(
- anyInt(), anyInt(), anyString(), anyString(), any());
+ anyInt(), anyInt(), anyString(), anyString(), anyInt(), any());
assertThat(mSensorController.createSensor(mSensorToken, mVirtualSensorConfig))
.isEqualTo(SENSOR_HANDLE);
}
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
index 0cd50f03fbfa..2967c5c53e8a 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
@@ -16,11 +16,12 @@
package com.android.server.companion.virtual;
-import static android.companion.virtual.VirtualDeviceManager.DEVICE_ID_DEFAULT;
-import static android.companion.virtual.VirtualDeviceManager.DEVICE_ID_INVALID;
import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_CUSTOM;
import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT;
+import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_RECENTS;
import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_SENSORS;
+import static android.content.Context.DEVICE_ID_DEFAULT;
+import static android.content.Context.DEVICE_ID_INVALID;
import static android.content.Intent.ACTION_VIEW;
import static android.content.pm.ActivityInfo.FLAG_CAN_DISPLAY_ON_REMOTE_DEVICES;
@@ -35,6 +36,7 @@ import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.argThat;
+import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@@ -67,7 +69,11 @@ import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.hardware.Sensor;
+import android.hardware.display.DisplayManagerGlobal;
import android.hardware.display.DisplayManagerInternal;
+import android.hardware.display.IDisplayManager;
+import android.hardware.display.IVirtualDisplayCallback;
+import android.hardware.display.VirtualDisplayConfig;
import android.hardware.input.IInputManager;
import android.hardware.input.VirtualDpadConfig;
import android.hardware.input.VirtualKeyEvent;
@@ -112,6 +118,7 @@ import com.android.server.sensors.SensorManagerInternal;
import com.google.android.collect.Sets;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -144,6 +151,7 @@ public class VirtualDeviceManagerServiceTest {
private static final String DEVICE_NAME_3 = "device name 3";
private static final int DISPLAY_ID_1 = 2;
private static final int DISPLAY_ID_2 = 3;
+ private static final int NON_EXISTENT_DISPLAY_ID = 42;
private static final int DEVICE_OWNER_UID_1 = 50;
private static final int DEVICE_OWNER_UID_2 = 51;
private static final int UID_1 = 0;
@@ -162,6 +170,8 @@ public class VirtualDeviceManagerServiceTest {
private static final int FLAG_CANNOT_DISPLAY_ON_REMOTE_DEVICES = 0x00000;
private static final int VIRTUAL_DEVICE_ID_1 = 42;
private static final int VIRTUAL_DEVICE_ID_2 = 43;
+ private static final VirtualDisplayConfig VIRTUAL_DISPLAY_CONFIG =
+ new VirtualDisplayConfig.Builder("virtual_display", 640, 480, 400).build();
private static final VirtualDpadConfig DPAD_CONFIG =
new VirtualDpadConfig.Builder()
.setVendorId(VENDOR_ID)
@@ -221,6 +231,8 @@ public class VirtualDeviceManagerServiceTest {
@Mock
private DisplayManagerInternal mDisplayManagerInternalMock;
@Mock
+ private IDisplayManager mIDisplayManager;
+ @Mock
private VirtualDeviceImpl.PendingTrampolineCallback mPendingTrampolineCallback;
@Mock
private DevicePolicyManager mDevicePolicyManagerMock;
@@ -237,6 +249,8 @@ public class VirtualDeviceManagerServiceTest {
@Mock
private IVirtualDeviceSoundEffectListener mSoundEffectListener;
@Mock
+ private IVirtualDisplayCallback mVirtualDisplayCallback;
+ @Mock
private Consumer<ArraySet<Integer>> mRunningAppsChangedCallback;
@Mock
private VirtualDeviceManagerInternal.VirtualDisplayListener mDisplayListener;
@@ -271,9 +285,13 @@ public class VirtualDeviceManagerServiceTest {
private Intent createRestrictedActivityBlockedIntent(List displayCategories,
String targetDisplayCategory) {
- mDeviceImpl.onVirtualDisplayCreatedLocked(
- mDeviceImpl.createWindowPolicyController(displayCategories), DISPLAY_ID_1);
- GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
+ when(mDisplayManagerInternalMock.createVirtualDisplay(any(), any(), any(), any(),
+ eq(NONBLOCKED_APP_PACKAGE_NAME))).thenReturn(DISPLAY_ID_1);
+ VirtualDisplayConfig config = new VirtualDisplayConfig.Builder("display", 640, 480,
+ 420).setDisplayCategories(displayCategories).build();
+ mDeviceImpl.createVirtualDisplay(config, mVirtualDisplayCallback,
+ NONBLOCKED_APP_PACKAGE_NAME);
+ GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest(
DISPLAY_ID_1);
doNothing().when(mContext).startActivityAsUser(any(), any(), any());
@@ -327,6 +345,7 @@ public class VirtualDeviceManagerServiceTest {
mContext = Mockito.spy(new ContextWrapper(
InstrumentationRegistry.getInstrumentation().getTargetContext()));
doReturn(mContext).when(mContext).createContextAsUser(eq(Process.myUserHandle()), anyInt());
+ doNothing().when(mContext).sendBroadcastAsUser(any(), any());
when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE)).thenReturn(
mDevicePolicyManagerMock);
@@ -338,7 +357,7 @@ public class VirtualDeviceManagerServiceTest {
TestableLooper.get(this), mNativeWrapperMock, mIInputManagerMock);
// Allow virtual devices to be created on the looper thread for testing.
final InputController.DeviceCreationThreadVerifier threadVerifier = () -> true;
- mInputController = new InputController(new Object(), mNativeWrapperMock,
+ mInputController = new InputController(mNativeWrapperMock,
new Handler(TestableLooper.get(this).getLooper()),
mContext.getSystemService(WindowManager.class), threadVerifier);
mSensorController =
@@ -355,6 +374,11 @@ public class VirtualDeviceManagerServiceTest {
mDeviceImpl = createVirtualDevice(VIRTUAL_DEVICE_ID_1, DEVICE_OWNER_UID_1);
}
+ @After
+ public void tearDown() {
+ mDeviceImpl.close();
+ }
+
@Test
public void getDeviceIdForDisplayId_invalidDisplayId_returnsDefault() {
assertThat(mVdm.getDeviceIdForDisplayId(Display.INVALID_DISPLAY))
@@ -369,15 +393,13 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void getDeviceIdForDisplayId_nonExistentDisplayId_returnsDefault() {
- mDeviceImpl.mVirtualDisplayIds.remove(DISPLAY_ID_1);
-
- assertThat(mVdm.getDeviceIdForDisplayId(DISPLAY_ID_1))
+ assertThat(mVdm.getDeviceIdForDisplayId(NON_EXISTENT_DISPLAY_ID))
.isEqualTo(DEVICE_ID_DEFAULT);
}
@Test
public void getDeviceIdForDisplayId_withValidVirtualDisplayId_returnsDeviceId() {
- mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID_1);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
assertThat(mVdm.getDeviceIdForDisplayId(DISPLAY_ID_1))
.isEqualTo(mDeviceImpl.getDeviceId());
@@ -429,6 +451,7 @@ public class VirtualDeviceManagerServiceTest {
.setBlockedActivities(getBlockedActivities())
.setDevicePolicy(POLICY_TYPE_SENSORS, DEVICE_POLICY_CUSTOM)
.build();
+ mDeviceImpl.close();
mDeviceImpl = createVirtualDevice(VIRTUAL_DEVICE_ID_1, DEVICE_OWNER_UID_1, params);
assertThat(mVdm.getDevicePolicy(mDeviceImpl.getDeviceId(), POLICY_TYPE_SENSORS))
@@ -436,6 +459,35 @@ public class VirtualDeviceManagerServiceTest {
}
@Test
+ public void getDevicePolicy_defaultRecentsPolicy_gwpcCanShowRecentsOnHostDevice() {
+ VirtualDeviceParams params = new VirtualDeviceParams
+ .Builder()
+ .build();
+ mDeviceImpl.close();
+ mDeviceImpl = createVirtualDevice(VIRTUAL_DEVICE_ID_1, DEVICE_OWNER_UID_1, params);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
+
+ GenericWindowPolicyController gwpc =
+ mDeviceImpl.getDisplayWindowPolicyControllerForTest(DISPLAY_ID_1);
+ assertThat(gwpc.canShowTasksInHostDeviceRecents()).isTrue();
+ }
+
+ @Test
+ public void getDevicePolicy_customRecentsPolicy_gwpcCannotShowRecentsOnHostDevice() {
+ VirtualDeviceParams params = new VirtualDeviceParams
+ .Builder()
+ .setDevicePolicy(POLICY_TYPE_RECENTS, DEVICE_POLICY_CUSTOM)
+ .build();
+ mDeviceImpl.close();
+ mDeviceImpl = createVirtualDevice(VIRTUAL_DEVICE_ID_1, DEVICE_OWNER_UID_1, params);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
+
+ GenericWindowPolicyController gwpc =
+ mDeviceImpl.getDisplayWindowPolicyControllerForTest(DISPLAY_ID_1);
+ assertThat(gwpc.canShowTasksInHostDeviceRecents()).isFalse();
+ }
+
+ @Test
public void getDeviceOwnerUid_oneDevice_returnsCorrectId() {
int ownerUid = mLocalService.getDeviceOwnerUid(mDeviceImpl.getDeviceId());
assertThat(ownerUid).isEqualTo(mDeviceImpl.getOwnerUid());
@@ -485,7 +537,8 @@ public class VirtualDeviceManagerServiceTest {
.build();
doReturn(SENSOR_HANDLE).when(mSensorManagerInternalMock).createRuntimeSensor(
- anyInt(), anyInt(), anyString(), anyString(), any());
+ anyInt(), anyInt(), anyString(), anyString(), anyInt(), any());
+ mDeviceImpl.close();
mDeviceImpl = createVirtualDevice(VIRTUAL_DEVICE_ID_1, DEVICE_OWNER_UID_1, params);
VirtualSensor sensor = mLocalService.getVirtualSensor(VIRTUAL_DEVICE_ID_1, SENSOR_HANDLE);
@@ -503,10 +556,9 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void getDeviceIdsForUid_differentUidOnDevice_returnsNull() {
- GenericWindowPolicyController gwpc =
- mDeviceImpl.createWindowPolicyController(new ArrayList<>());
- mDeviceImpl.onVirtualDisplayCreatedLocked(gwpc, DISPLAY_ID_1);
- gwpc.onRunningAppsChanged(Sets.newArraySet(UID_2));
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
+ mDeviceImpl.getDisplayWindowPolicyControllerForTest(DISPLAY_ID_1).onRunningAppsChanged(
+ Sets.newArraySet(UID_2));
Set<Integer> deviceIds = mLocalService.getDeviceIdsForUid(UID_1);
assertThat(deviceIds).isEmpty();
@@ -514,10 +566,9 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void getDeviceIdsForUid_oneUidOnDevice_returnsCorrectId() {
- GenericWindowPolicyController gwpc =
- mDeviceImpl.createWindowPolicyController(new ArrayList<>());
- mDeviceImpl.onVirtualDisplayCreatedLocked(gwpc, DISPLAY_ID_1);
- gwpc.onRunningAppsChanged(Sets.newArraySet(UID_1));
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
+ mDeviceImpl.getDisplayWindowPolicyControllerForTest(DISPLAY_ID_1).onRunningAppsChanged(
+ Sets.newArraySet(UID_1));
Set<Integer> deviceIds = mLocalService.getDeviceIdsForUid(UID_1);
assertThat(deviceIds).containsExactly(mDeviceImpl.getDeviceId());
@@ -525,10 +576,10 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void getDeviceIdsForUid_twoUidsOnDevice_returnsCorrectId() {
- GenericWindowPolicyController gwpc =
- mDeviceImpl.createWindowPolicyController(new ArrayList<>());
- mDeviceImpl.onVirtualDisplayCreatedLocked(gwpc, DISPLAY_ID_1);
- gwpc.onRunningAppsChanged(Sets.newArraySet(UID_1, UID_2));
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
+
+ mDeviceImpl.getDisplayWindowPolicyControllerForTest(DISPLAY_ID_1).onRunningAppsChanged(
+ Sets.newArraySet(UID_1, UID_2));
Set<Integer> deviceIds = mLocalService.getDeviceIdsForUid(UID_1);
assertThat(deviceIds).containsExactly(mDeviceImpl.getDeviceId());
@@ -538,11 +589,10 @@ public class VirtualDeviceManagerServiceTest {
public void getDeviceIdsForUid_twoDevicesUidOnOne_returnsCorrectId() {
VirtualDeviceImpl secondDevice = createVirtualDevice(VIRTUAL_DEVICE_ID_2,
DEVICE_OWNER_UID_2);
+ addVirtualDisplay(secondDevice, DISPLAY_ID_2);
- GenericWindowPolicyController gwpc =
- secondDevice.createWindowPolicyController(new ArrayList<>());
- secondDevice.onVirtualDisplayCreatedLocked(gwpc, DISPLAY_ID_2);
- gwpc.onRunningAppsChanged(Sets.newArraySet(UID_1));
+ secondDevice.getDisplayWindowPolicyControllerForTest(DISPLAY_ID_2).onRunningAppsChanged(
+ Sets.newArraySet(UID_1));
Set<Integer> deviceIds = mLocalService.getDeviceIdsForUid(UID_1);
assertThat(deviceIds).containsExactly(secondDevice.getDeviceId());
@@ -550,16 +600,16 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void getDeviceIdsForUid_twoDevicesUidOnBoth_returnsCorrectId() {
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
VirtualDeviceImpl secondDevice = createVirtualDevice(VIRTUAL_DEVICE_ID_2,
DEVICE_OWNER_UID_2);
- GenericWindowPolicyController gwpc1 =
- mDeviceImpl.createWindowPolicyController(new ArrayList<>());
- GenericWindowPolicyController gwpc2 =
- secondDevice.createWindowPolicyController(new ArrayList<>());
- mDeviceImpl.onVirtualDisplayCreatedLocked(gwpc1, DISPLAY_ID_1);
- secondDevice.onVirtualDisplayCreatedLocked(gwpc2, DISPLAY_ID_2);
- gwpc1.onRunningAppsChanged(Sets.newArraySet(UID_1));
- gwpc2.onRunningAppsChanged(Sets.newArraySet(UID_1, UID_2));
+ addVirtualDisplay(secondDevice, DISPLAY_ID_2);
+
+
+ mDeviceImpl.getDisplayWindowPolicyControllerForTest(DISPLAY_ID_1).onRunningAppsChanged(
+ Sets.newArraySet(UID_1));
+ secondDevice.getDisplayWindowPolicyControllerForTest(DISPLAY_ID_2).onRunningAppsChanged(
+ Sets.newArraySet(UID_1, UID_2));
Set<Integer> deviceIds = mLocalService.getDeviceIdsForUid(UID_1);
assertThat(deviceIds).containsExactly(
@@ -568,8 +618,7 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void getPreferredLocaleListForApp_keyboardAttached_returnLocaleHints() {
- mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID_1);
-
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
mDeviceImpl.createVirtualKeyboard(KEYBOARD_CONFIG, BINDER);
mVdms.notifyRunningAppsChanged(mDeviceImpl.getDeviceId(), Sets.newArraySet(UID_1));
@@ -609,8 +658,8 @@ public class VirtualDeviceManagerServiceTest {
.setLanguageTag("fr-FR")
.build();
- mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID_1);
- secondDevice.mVirtualDisplayIds.add(DISPLAY_ID_2);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
+ addVirtualDisplay(secondDevice, DISPLAY_ID_2);
mDeviceImpl.createVirtualKeyboard(firstKeyboardConfig, BINDER);
secondDevice.createVirtualKeyboard(secondKeyboardConfig, secondBinder);
@@ -640,10 +689,9 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void onVirtualDisplayRemovedLocked_doesNotThrowException() {
- mDeviceImpl.onVirtualDisplayCreatedLocked(
- mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID_1);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
// This call should not throw any exceptions.
- mDeviceImpl.onVirtualDisplayRemovedLocked(DISPLAY_ID_1);
+ mDeviceImpl.onVirtualDisplayRemoved(DISPLAY_ID_1);
}
@Test
@@ -659,8 +707,8 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void onVirtualDisplayRemovedLocked_listenersNotified() {
mLocalService.registerVirtualDisplayListener(mDisplayListener);
- mDeviceImpl.onVirtualDisplayCreatedLocked(
- mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID_1);
+
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
mLocalService.onVirtualDisplayRemoved(mDeviceImpl, DISPLAY_ID_1);
TestableLooper.get(this).processAllMessages();
@@ -723,8 +771,7 @@ public class VirtualDeviceManagerServiceTest {
verify(mIPowerManagerMock, never()).acquireWakeLock(any(Binder.class), anyInt(),
nullable(String.class), nullable(String.class), nullable(WorkSource.class),
nullable(String.class), anyInt(), eq(null));
- mDeviceImpl.onVirtualDisplayCreatedLocked(
- mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID_1);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
verify(mIPowerManagerMock).acquireWakeLock(any(Binder.class), anyInt(),
nullable(String.class), nullable(String.class), nullable(WorkSource.class),
nullable(String.class), eq(DISPLAY_ID_1), eq(null));
@@ -733,12 +780,9 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void onVirtualDisplayCreatedLocked_duplicateCalls_onlyOneWakeLockIsAcquired()
throws RemoteException {
- GenericWindowPolicyController gwpc = mDeviceImpl.createWindowPolicyController(
- new ArrayList<>());
- mDeviceImpl.onVirtualDisplayCreatedLocked(
- mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID_1);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
assertThrows(IllegalStateException.class,
- () -> mDeviceImpl.onVirtualDisplayCreatedLocked(gwpc, DISPLAY_ID_1));
+ () -> addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1));
TestableLooper.get(this).processAllMessages();
verify(mIPowerManagerMock).acquireWakeLock(any(Binder.class), anyInt(),
nullable(String.class), nullable(String.class), nullable(WorkSource.class),
@@ -749,13 +793,12 @@ public class VirtualDeviceManagerServiceTest {
public void onVirtualDisplayRemovedLocked_unknownDisplayId_throwsException() {
final int unknownDisplayId = 999;
assertThrows(IllegalStateException.class,
- () -> mDeviceImpl.onVirtualDisplayRemovedLocked(unknownDisplayId));
+ () -> mDeviceImpl.onVirtualDisplayRemoved(unknownDisplayId));
}
@Test
public void onVirtualDisplayRemovedLocked_wakeLockIsReleased() throws RemoteException {
- mDeviceImpl.onVirtualDisplayCreatedLocked(
- mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID_1);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
ArgumentCaptor<IBinder> wakeLockCaptor = ArgumentCaptor.forClass(IBinder.class);
TestableLooper.get(this).processAllMessages();
verify(mIPowerManagerMock).acquireWakeLock(wakeLockCaptor.capture(),
@@ -764,14 +807,13 @@ public class VirtualDeviceManagerServiceTest {
nullable(String.class), eq(DISPLAY_ID_1), eq(null));
IBinder wakeLock = wakeLockCaptor.getValue();
- mDeviceImpl.onVirtualDisplayRemovedLocked(DISPLAY_ID_1);
+ mDeviceImpl.onVirtualDisplayRemoved(DISPLAY_ID_1);
verify(mIPowerManagerMock).releaseWakeLock(eq(wakeLock), anyInt());
}
@Test
public void addVirtualDisplay_displayNotReleased_wakeLockIsReleased() throws RemoteException {
- mDeviceImpl.onVirtualDisplayCreatedLocked(
- mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID_1);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
ArgumentCaptor<IBinder> wakeLockCaptor = ArgumentCaptor.forClass(IBinder.class);
TestableLooper.get(this).processAllMessages();
verify(mIPowerManagerMock).acquireWakeLock(wakeLockCaptor.capture(),
@@ -825,7 +867,7 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void createVirtualTouchscreen_positiveDisplayDimension_successful() {
- mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID_1);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
VirtualTouchscreenConfig positiveConfig =
new VirtualTouchscreenConfig.Builder(
/* touchscrenWidth= */ 600, /* touchscreenHeight= */ 800)
@@ -863,7 +905,7 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void createVirtualNavigationTouchpad_positiveDisplayDimension_successful() {
- mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID_1);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
VirtualNavigationTouchpadConfig positiveConfig =
new VirtualNavigationTouchpadConfig.Builder(
/* touchpadHeight= */ 50, /* touchpadWidth= */ 50)
@@ -888,7 +930,7 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void createVirtualDpad_noPermission_failsSecurityException() {
- mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID_1);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
try (DropShellPermissionsTemporarily drop = new DropShellPermissionsTemporarily()) {
assertThrows(SecurityException.class,
() -> mDeviceImpl.createVirtualDpad(DPAD_CONFIG, BINDER));
@@ -897,7 +939,7 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void createVirtualKeyboard_noPermission_failsSecurityException() {
- mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID_1);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
try (DropShellPermissionsTemporarily drop = new DropShellPermissionsTemporarily()) {
assertThrows(SecurityException.class,
() -> mDeviceImpl.createVirtualKeyboard(KEYBOARD_CONFIG, BINDER));
@@ -906,7 +948,7 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void createVirtualMouse_noPermission_failsSecurityException() {
- mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID_1);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
try (DropShellPermissionsTemporarily drop = new DropShellPermissionsTemporarily()) {
assertThrows(SecurityException.class,
() -> mDeviceImpl.createVirtualMouse(MOUSE_CONFIG, BINDER));
@@ -915,7 +957,7 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void createVirtualTouchscreen_noPermission_failsSecurityException() {
- mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID_1);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
try (DropShellPermissionsTemporarily drop = new DropShellPermissionsTemporarily()) {
assertThrows(SecurityException.class,
() -> mDeviceImpl.createVirtualTouchscreen(TOUCHSCREEN_CONFIG, BINDER));
@@ -924,7 +966,7 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void createVirtualNavigationTouchpad_noPermission_failsSecurityException() {
- mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID_1);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
try (DropShellPermissionsTemporarily drop = new DropShellPermissionsTemporarily()) {
assertThrows(SecurityException.class,
() -> mDeviceImpl.createVirtualNavigationTouchpad(NAVIGATION_TOUCHPAD_CONFIG,
@@ -934,7 +976,7 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void onAudioSessionStarting_noPermission_failsSecurityException() {
- mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID_1);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
try (DropShellPermissionsTemporarily drop = new DropShellPermissionsTemporarily()) {
assertThrows(SecurityException.class,
() -> mDeviceImpl.onAudioSessionStarting(
@@ -951,7 +993,7 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void createVirtualDpad_hasDisplay_obtainFileDescriptor() {
- mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID_1);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
mDeviceImpl.createVirtualDpad(DPAD_CONFIG, BINDER);
assertWithMessage("Virtual dpad should register fd when the display matches").that(
mInputController.getInputDeviceDescriptors()).isNotEmpty();
@@ -961,7 +1003,7 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void createVirtualKeyboard_hasDisplay_obtainFileDescriptor() {
- mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID_1);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
mDeviceImpl.createVirtualKeyboard(KEYBOARD_CONFIG, BINDER);
assertWithMessage("Virtual keyboard should register fd when the display matches").that(
mInputController.getInputDeviceDescriptors()).isNotEmpty();
@@ -971,7 +1013,7 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void createVirtualKeyboard_keyboardCreated_localeUpdated() {
- mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID_1);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
mDeviceImpl.createVirtualKeyboard(KEYBOARD_CONFIG, BINDER);
assertWithMessage("Virtual keyboard should register fd when the display matches")
.that(mInputController.getInputDeviceDescriptors())
@@ -992,7 +1034,7 @@ public class VirtualDeviceManagerServiceTest {
.setAssociatedDisplayId(DISPLAY_ID_1)
.build();
- mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID_1);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
mDeviceImpl.createVirtualKeyboard(configWithoutExplicitLayoutInfo, BINDER);
assertWithMessage("Virtual keyboard should register fd when the display matches")
.that(mInputController.getInputDeviceDescriptors())
@@ -1005,7 +1047,7 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void virtualDeviceWithoutKeyboard_noLocaleUpdate() {
- mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID_1);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
// no preceding call to createVirtualKeyboard()
assertThat(mDeviceImpl.getDeviceLocaleList()).isNull();
@@ -1013,7 +1055,7 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void createVirtualMouse_hasDisplay_obtainFileDescriptor() {
- mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID_1);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
mDeviceImpl.createVirtualMouse(MOUSE_CONFIG, BINDER);
assertWithMessage("Virtual mouse should register fd when the display matches").that(
mInputController.getInputDeviceDescriptors()).isNotEmpty();
@@ -1023,7 +1065,7 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void createVirtualTouchscreen_hasDisplay_obtainFileDescriptor() {
- mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID_1);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
mDeviceImpl.createVirtualTouchscreen(TOUCHSCREEN_CONFIG, BINDER);
assertWithMessage("Virtual touchscreen should register fd when the display matches").that(
mInputController.getInputDeviceDescriptors()).isNotEmpty();
@@ -1033,7 +1075,7 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void createVirtualNavigationTouchpad_hasDisplay_obtainFileDescriptor() {
- mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID_1);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
mDeviceImpl.createVirtualNavigationTouchpad(NAVIGATION_TOUCHPAD_CONFIG, BINDER);
assertWithMessage("Virtual navigation touchpad should register fd when the display matches")
.that(
@@ -1055,8 +1097,7 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void onAudioSessionStarting_hasVirtualAudioController() {
- mDeviceImpl.onVirtualDisplayCreatedLocked(
- mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID_1);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
mDeviceImpl.onAudioSessionStarting(DISPLAY_ID_1, mRoutingCallback, mConfigChangedCallback);
@@ -1065,8 +1106,7 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void onAudioSessionEnded_noVirtualAudioController() {
- mDeviceImpl.onVirtualDisplayCreatedLocked(
- mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID_1);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
mDeviceImpl.onAudioSessionStarting(DISPLAY_ID_1, mRoutingCallback, mConfigChangedCallback);
mDeviceImpl.onAudioSessionEnded();
@@ -1076,8 +1116,7 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void close_cleanVirtualAudioController() {
- mDeviceImpl.onVirtualDisplayCreatedLocked(
- mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID_1);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
mDeviceImpl.onAudioSessionStarting(DISPLAY_ID_1, mRoutingCallback, mConfigChangedCallback);
mDeviceImpl.close();
@@ -1321,9 +1360,9 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void setShowPointerIcon_setsValueForAllDisplays() {
- mDeviceImpl.mVirtualDisplayIds.add(1);
- mDeviceImpl.mVirtualDisplayIds.add(2);
- mDeviceImpl.mVirtualDisplayIds.add(3);
+ addVirtualDisplay(mDeviceImpl, 1);
+ addVirtualDisplay(mDeviceImpl, 2);
+ addVirtualDisplay(mDeviceImpl, 3);
VirtualMouseConfig config1 = new VirtualMouseConfig.Builder()
.setAssociatedDisplayId(1)
.setInputDeviceName(DEVICE_NAME_1)
@@ -1346,7 +1385,9 @@ public class VirtualDeviceManagerServiceTest {
mDeviceImpl.createVirtualMouse(config1, BINDER);
mDeviceImpl.createVirtualMouse(config2, BINDER);
mDeviceImpl.createVirtualMouse(config3, BINDER);
+ clearInvocations(mInputManagerInternalMock);
mDeviceImpl.setShowPointerIcon(false);
+
verify(mInputManagerInternalMock, times(3)).setPointerIconVisible(eq(false), anyInt());
verify(mInputManagerInternalMock, never()).setPointerIconVisible(eq(true), anyInt());
mDeviceImpl.setShowPointerIcon(true);
@@ -1355,9 +1396,8 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void openNonBlockedAppOnVirtualDisplay_doesNotStartBlockedAlertActivity() {
- mDeviceImpl.onVirtualDisplayCreatedLocked(
- mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID_1);
- GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
+ GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest(
DISPLAY_ID_1);
doNothing().when(mContext).startActivityAsUser(any(), any(), any());
@@ -1376,9 +1416,8 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void openPermissionControllerOnVirtualDisplay_startBlockedAlertActivity() {
- mDeviceImpl.onVirtualDisplayCreatedLocked(
- mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID_1);
- GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
+ GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest(
DISPLAY_ID_1);
doNothing().when(mContext).startActivityAsUser(any(), any(), any());
@@ -1397,9 +1436,8 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void openSettingsOnVirtualDisplay_startBlockedAlertActivity() {
- mDeviceImpl.onVirtualDisplayCreatedLocked(
- mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID_1);
- GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
+ GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest(
DISPLAY_ID_1);
doNothing().when(mContext).startActivityAsUser(any(), any(), any());
@@ -1418,9 +1456,8 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void openVendingOnVirtualDisplay_startBlockedAlertActivity() {
- mDeviceImpl.onVirtualDisplayCreatedLocked(
- mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID_1);
- GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
+ GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest(
DISPLAY_ID_1);
doNothing().when(mContext).startActivityAsUser(any(), any(), any());
@@ -1439,9 +1476,8 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void openGoogleDialerOnVirtualDisplay_startBlockedAlertActivity() {
- mDeviceImpl.onVirtualDisplayCreatedLocked(
- mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID_1);
- GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
+ GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest(
DISPLAY_ID_1);
doNothing().when(mContext).startActivityAsUser(any(), any(), any());
@@ -1460,9 +1496,8 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void openGoogleMapsOnVirtualDisplay_startBlockedAlertActivity() {
- mDeviceImpl.onVirtualDisplayCreatedLocked(
- mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID_1);
- GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
+ GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest(
DISPLAY_ID_1);
doNothing().when(mContext).startActivityAsUser(any(), any(), any());
@@ -1482,9 +1517,8 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void registerRunningAppsChangedListener_onRunningAppsChanged_listenersNotified() {
ArraySet<Integer> uids = new ArraySet<>(Arrays.asList(UID_1, UID_2));
- mDeviceImpl.onVirtualDisplayCreatedLocked(
- mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID_1);
- GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
+ GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest(
DISPLAY_ID_1);
gwpc.onRunningAppsChanged(uids);
@@ -1497,11 +1531,10 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void noRunningAppsChangedListener_onRunningAppsChanged_doesNotThrowException() {
ArraySet<Integer> uids = new ArraySet<>(Arrays.asList(UID_1, UID_2));
- mDeviceImpl.onVirtualDisplayCreatedLocked(
- mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID_1);
- GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
+ GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest(
DISPLAY_ID_1);
- mDeviceImpl.onVirtualDisplayRemovedLocked(DISPLAY_ID_1);
+ gwpc.unregisterRunningAppsChangedListener(mDeviceImpl);
// This call should not throw any exceptions.
gwpc.onRunningAppsChanged(uids);
@@ -1512,9 +1545,8 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void canActivityBeLaunched_activityCanLaunch() {
Intent intent = new Intent(ACTION_VIEW, Uri.parse(TEST_SITE));
- mDeviceImpl.onVirtualDisplayCreatedLocked(
- mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID_1);
- GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
+ GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest(
DISPLAY_ID_1);
ArrayList<ActivityInfo> activityInfos = getActivityInfoList(
NONBLOCKED_APP_PACKAGE_NAME,
@@ -1537,9 +1569,8 @@ public class VirtualDeviceManagerServiceTest {
doReturn(interceptor).when(interceptor).asBinder();
doReturn(interceptor).when(interceptor).queryLocalInterface(anyString());
- mDeviceImpl.onVirtualDisplayCreatedLocked(
- mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID_1);
- GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
+ GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest(
DISPLAY_ID_1);
ArrayList<ActivityInfo> activityInfos = getActivityInfoList(
NONBLOCKED_APP_PACKAGE_NAME,
@@ -1581,9 +1612,8 @@ public class VirtualDeviceManagerServiceTest {
doReturn(interceptor).when(interceptor).asBinder();
doReturn(interceptor).when(interceptor).queryLocalInterface(anyString());
- mDeviceImpl.onVirtualDisplayCreatedLocked(
- mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID_1);
- GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
+ GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest(
DISPLAY_ID_1);
ArrayList<ActivityInfo> activityInfos = getActivityInfoList(
NONBLOCKED_APP_PACKAGE_NAME,
@@ -1626,8 +1656,7 @@ public class VirtualDeviceManagerServiceTest {
}
@Test
- public void
- restrictedActivityOnNonMatchingRestrictedVirtualDisplay_startBlockedAlertActivity() {
+ public void restrictedActivityNonMatchingRestrictedVirtualDisplay_startBlockedAlertActivity() {
Intent blockedAppIntent = createRestrictedActivityBlockedIntent(List.of("abc"), "def");
verify(mContext).startActivityAsUser(argThat(intent ->
intent.filterEquals(blockedAppIntent)), any(), any());
@@ -1654,15 +1683,15 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void getDisplayIdsForDevice_oneDisplay_resultContainsCorrectDisplayId() {
- mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID_1);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
ArraySet<Integer> displayIds = mLocalService.getDisplayIdsForDevice(VIRTUAL_DEVICE_ID_1);
assertThat(displayIds).containsExactly(DISPLAY_ID_1);
}
@Test
public void getDisplayIdsForDevice_twoDisplays_resultContainsCorrectDisplayIds() {
- mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID_1);
- mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID_2);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_2);
ArraySet<Integer> displayIds = mLocalService.getDisplayIdsForDevice(VIRTUAL_DEVICE_ID_1);
assertThat(displayIds).containsExactly(DISPLAY_ID_1, DISPLAY_ID_2);
}
@@ -1677,15 +1706,22 @@ public class VirtualDeviceManagerServiceTest {
private VirtualDeviceImpl createVirtualDevice(int virtualDeviceId, int ownerUid,
VirtualDeviceParams params) {
VirtualDeviceImpl virtualDeviceImpl = new VirtualDeviceImpl(mContext,
- mAssociationInfo, new Binder(), ownerUid, virtualDeviceId,
- mInputController, mSensorController, mCameraAccessController,
- /* onDeviceCloseListener= */ deviceId -> mVdms.removeVirtualDevice(deviceId),
+ mAssociationInfo, mVdms, new Binder(), ownerUid, virtualDeviceId,
+ mInputController, mSensorController, mCameraAccessController
+ /* onDeviceCloseListener= */ /*deviceId -> mVdms.removeVirtualDevice(deviceId)*/,
mPendingTrampolineCallback, mActivityListener, mSoundEffectListener,
- mRunningAppsChangedCallback, params);
+ mRunningAppsChangedCallback, params, new DisplayManagerGlobal(mIDisplayManager));
mVdms.addVirtualDevice(virtualDeviceImpl);
return virtualDeviceImpl;
}
+ private void addVirtualDisplay(VirtualDeviceImpl virtualDevice, int displayId) {
+ when(mDisplayManagerInternalMock.createVirtualDisplay(any(), eq(mVirtualDisplayCallback),
+ eq(virtualDevice), any(), any())).thenReturn(displayId);
+ virtualDevice.createVirtualDisplay(VIRTUAL_DISPLAY_CONFIG, mVirtualDisplayCallback,
+ NONBLOCKED_APP_PACKAGE_NAME);
+ }
+
/** Helper class to drop permissions temporarily and restore them at the end of a test. */
static final class DropShellPermissionsTemporarily implements AutoCloseable {
DropShellPermissionsTemporarily() {
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceTest.java
index bb28a3689f68..a2e204d89424 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceTest.java
@@ -16,8 +16,8 @@
package com.android.server.companion.virtual;
-import static android.companion.virtual.VirtualDeviceManager.DEVICE_ID_DEFAULT;
-import static android.companion.virtual.VirtualDeviceManager.DEVICE_ID_INVALID;
+import static android.content.Context.DEVICE_ID_DEFAULT;
+import static android.content.Context.DEVICE_ID_INVALID;
import static com.google.common.truth.Truth.assertThat;
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
index 7b5af1e0fe98..d9e4da73c1c3 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
@@ -90,8 +90,7 @@ public class VirtualAudioControllerTest {
/* secureWindowCallback= */ null,
/* intentListenerCallback= */ null,
/* displayCategories= */ new ArrayList<>(),
- /* recentsPolicy= */
- VirtualDeviceParams.RECENTS_POLICY_ALLOW_IN_HOST_DEVICE_RECENTS);
+ /* showTasksInHostDeviceRecents= */ true);
}
diff --git a/services/tests/servicestests/src/com/android/server/credentials/CredentialDescriptionRegistryTest.java b/services/tests/servicestests/src/com/android/server/credentials/CredentialDescriptionRegistryTest.java
new file mode 100644
index 000000000000..b7085f152fa0
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/credentials/CredentialDescriptionRegistryTest.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2023 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.credentials;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.credentials.CredentialDescription;
+import android.credentials.RegisterCredentialDescriptionRequest;
+import android.service.credentials.CredentialEntry;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Tests for CredentialDescriptionRegistry.
+ *
+ * atest FrameworksServicesTests:com.android.server.credentials.CredentialDescriptionRegistryTest
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class CredentialDescriptionRegistryTest {
+
+ private static final int USER_ID_1 = 1;
+ private static final int USER_ID_2 = 2;
+ private static final String CALLING_PACKAGE_NAME = "com.credman.app";
+ private static final String CALLING_PACKAGE_NAME_2 = "com.credman.app2";
+ private static final String MDOC_CREDENTIAL_TYPE = "MDOC";
+ private static final String PASSKEY_CREDENTIAL_TYPE = "PASSKEY";
+ private static final String FLATTENED_REQUEST = "FLATTENED_REQ";
+ private static final String FLATTENED_REQUEST_2 = "FLATTENED_REQ_2";
+
+ private CredentialDescriptionRegistry mCredentialDescriptionRegistry;
+ private CredentialEntry mEntry;
+ private CredentialEntry mEntry2;
+ private CredentialEntry mEntry3;
+
+ @SuppressWarnings("GuardedBy")
+ @Before
+ public void setUp() {
+ CredentialDescriptionRegistry.clearAllSessions();
+ mEntry = mock(CredentialEntry.class);
+ mEntry2 = mock(CredentialEntry.class);
+ mEntry3 = mock(CredentialEntry.class);
+ when(mEntry.getType()).thenReturn(MDOC_CREDENTIAL_TYPE);
+ when(mEntry2.getType()).thenReturn(MDOC_CREDENTIAL_TYPE);
+ when(mEntry3.getType()).thenReturn(PASSKEY_CREDENTIAL_TYPE);
+ mCredentialDescriptionRegistry = CredentialDescriptionRegistry.forUser(USER_ID_1);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testForUser_createsUniqueInstanceForEachUserID() {
+ final CredentialDescriptionRegistry secondRegistry = CredentialDescriptionRegistry
+ .forUser(USER_ID_2);
+
+ assertThat(mCredentialDescriptionRegistry).isNotSameInstanceAs(secondRegistry);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testForUser_returnsSameInstanceForSameUserID() {
+ final CredentialDescriptionRegistry secondRegistry = CredentialDescriptionRegistry
+ .forUser(USER_ID_1);
+
+ assertThat(mCredentialDescriptionRegistry).isSameInstanceAs(secondRegistry);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testClearUserSession_removesExistingSessionForUserID() {
+ CredentialDescriptionRegistry.clearUserSession(USER_ID_1);
+ final CredentialDescriptionRegistry secondRegistry = CredentialDescriptionRegistry
+ .forUser(USER_ID_1);
+
+ assertThat(mCredentialDescriptionRegistry).isNotSameInstanceAs(secondRegistry);
+ }
+
+ @Test
+ public void testEvictProvider_existingProviders_succeeds() {
+ final CredentialDescription credentialDescription =
+ new CredentialDescription(MDOC_CREDENTIAL_TYPE, FLATTENED_REQUEST,
+ Collections.emptyList());
+ final RegisterCredentialDescriptionRequest registerCredentialDescriptionRequest =
+ new RegisterCredentialDescriptionRequest(credentialDescription);
+ final CredentialDescription credentialDescription2 =
+ new CredentialDescription(MDOC_CREDENTIAL_TYPE, FLATTENED_REQUEST_2,
+ Collections.emptyList());
+ final RegisterCredentialDescriptionRequest registerCredentialDescriptionRequest2 =
+ new RegisterCredentialDescriptionRequest(credentialDescription2);
+
+
+ mCredentialDescriptionRegistry
+ .executeRegisterRequest(registerCredentialDescriptionRequest, CALLING_PACKAGE_NAME);
+ mCredentialDescriptionRegistry
+ .executeRegisterRequest(registerCredentialDescriptionRequest2,
+ CALLING_PACKAGE_NAME);
+ mCredentialDescriptionRegistry.evictProviderWithPackageName(CALLING_PACKAGE_NAME);
+ Set<CredentialDescriptionRegistry.FilterResult> providers = mCredentialDescriptionRegistry
+ .getMatchingProviders(Set.of(FLATTENED_REQUEST));
+
+ assertThat(providers).isEmpty();
+ }
+
+ @Test
+ public void testGetMatchingProviders_existingProviders_succeeds() {
+ final CredentialDescription credentialDescription =
+ new CredentialDescription(MDOC_CREDENTIAL_TYPE, FLATTENED_REQUEST,
+ Collections.emptyList());
+ final RegisterCredentialDescriptionRequest registerCredentialDescriptionRequest =
+ new RegisterCredentialDescriptionRequest(credentialDescription);
+ final CredentialDescription credentialDescription2 =
+ new CredentialDescription(MDOC_CREDENTIAL_TYPE, FLATTENED_REQUEST,
+ Collections.emptyList());
+ final RegisterCredentialDescriptionRequest registerCredentialDescriptionRequest2 =
+ new RegisterCredentialDescriptionRequest(credentialDescription2);
+
+
+ mCredentialDescriptionRegistry
+ .executeRegisterRequest(registerCredentialDescriptionRequest,
+ CALLING_PACKAGE_NAME);
+ mCredentialDescriptionRegistry
+ .executeRegisterRequest(registerCredentialDescriptionRequest2,
+ CALLING_PACKAGE_NAME_2);
+
+ Set<CredentialDescriptionRegistry.FilterResult> providers = mCredentialDescriptionRegistry
+ .getMatchingProviders(Set.of(FLATTENED_REQUEST));
+ Set<String> packageNames = providers.stream().map(
+ filterResult -> filterResult.mPackageName).collect(Collectors.toSet());
+
+ assertThat(providers).hasSize(2);
+ assertThat(packageNames).contains(CALLING_PACKAGE_NAME);
+ assertThat(packageNames).contains(CALLING_PACKAGE_NAME_2);
+ }
+
+ @Test
+ public void testExecuteRegisterRequest_noProviders_filterSucceedsWithNoResults() {
+ List<CredentialDescriptionRegistry.FilterResult> results = mCredentialDescriptionRegistry
+ .getFilteredResultForProvider(CALLING_PACKAGE_NAME,
+ FLATTENED_REQUEST).stream().toList();
+
+ assertThat(results).isEmpty();
+ }
+
+ @Test
+ public void testExecuteRegisterRequest_existingProviders_filterSucceeds() {
+ final CredentialDescription credentialDescription =
+ new CredentialDescription(MDOC_CREDENTIAL_TYPE,
+ FLATTENED_REQUEST,
+ List.of(mEntry, mEntry2));
+ final CredentialDescription credentialDescription2 =
+ new CredentialDescription(PASSKEY_CREDENTIAL_TYPE,
+ FLATTENED_REQUEST_2,
+ List.of(mEntry3));
+ final RegisterCredentialDescriptionRequest registerCredentialDescriptionRequest =
+ new RegisterCredentialDescriptionRequest(Set.of(credentialDescription,
+ credentialDescription2));
+
+ mCredentialDescriptionRegistry
+ .executeRegisterRequest(registerCredentialDescriptionRequest, CALLING_PACKAGE_NAME);
+
+ List<CredentialDescriptionRegistry.FilterResult> results = mCredentialDescriptionRegistry
+ .getFilteredResultForProvider(CALLING_PACKAGE_NAME, FLATTENED_REQUEST)
+ .stream().toList();
+
+ assertThat(results).hasSize(1);
+ assertThat(results.get(0).mCredentialEntries).hasSize(2);
+ assertThat(results.get(0).mCredentialEntries.get(0)).isSameInstanceAs(mEntry);
+ assertThat(results.get(0).mCredentialEntries.get(1)).isSameInstanceAs(mEntry2);
+ }
+
+}
diff --git a/services/tests/servicestests/src/com/android/server/credentials/OWNERS b/services/tests/servicestests/src/com/android/server/credentials/OWNERS
new file mode 100644
index 000000000000..cc73854c665e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/credentials/OWNERS
@@ -0,0 +1 @@
+include platform/frameworks/base:/core/java/android/credentials/OWNERS \ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessThrottlerTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessThrottlerTest.java
index 800f60bec828..ffe2fec380a8 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessThrottlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessThrottlerTest.java
@@ -43,6 +43,7 @@ import com.android.internal.os.BackgroundThread;
import com.android.server.display.BrightnessThrottler.Injector;
import com.android.server.display.DisplayDeviceConfig.BrightnessThrottlingData;
import com.android.server.display.DisplayDeviceConfig.BrightnessThrottlingData.ThrottlingLevel;
+import com.android.server.display.mode.DisplayModeDirectorTest;
import org.junit.Before;
import org.junit.Test;
diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
index 6def7b1c8c35..8981160d1f25 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
@@ -176,21 +176,18 @@ public class BrightnessTrackerTest {
assertFalse(mInjector.mColorSamplingEnabled);
// Update brightness config to enabled color sampling.
- mTracker.setBrightnessConfiguration(buildBrightnessConfiguration(
- /* collectColorSamples= */ true));
+ mTracker.setShouldCollectColorSample(/* collectColorSamples= */ true);
mInjector.waitForHandler();
assertTrue(mInjector.mColorSamplingEnabled);
// Update brightness config to disable color sampling.
- mTracker.setBrightnessConfiguration(buildBrightnessConfiguration(
- /* collectColorSamples= */ false));
+ mTracker.setShouldCollectColorSample(/* collectColorSamples= */ false);
mInjector.waitForHandler();
assertFalse(mInjector.mColorSamplingEnabled);
// Pretend screen is off, update config to turn on color sampling.
mInjector.sendScreenChange(/* screenOn= */ false);
- mTracker.setBrightnessConfiguration(buildBrightnessConfiguration(
- /* collectColorSamples= */ true));
+ mTracker.setShouldCollectColorSample(/* collectColorSamples= */ true);
mInjector.waitForHandler();
assertFalse(mInjector.mColorSamplingEnabled);
@@ -883,7 +880,7 @@ public class BrightnessTrackerTest {
private void startTracker(BrightnessTracker tracker, float initialBrightness,
boolean collectColorSamples) {
tracker.start(initialBrightness);
- tracker.setBrightnessConfiguration(buildBrightnessConfiguration(collectColorSamples));
+ tracker.setShouldCollectColorSample(collectColorSamples);
mInjector.waitForHandler();
}
diff --git a/services/tests/servicestests/src/com/android/server/display/DeviceStateToLayoutMapTest.java b/services/tests/servicestests/src/com/android/server/display/DeviceStateToLayoutMapTest.java
index a380efffb62f..e74b278bd904 100644
--- a/services/tests/servicestests/src/com/android/server/display/DeviceStateToLayoutMapTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DeviceStateToLayoutMapTest.java
@@ -157,6 +157,26 @@ public class DeviceStateToLayoutMapTest {
assertEquals(testLayout, configLayout);
}
+ @Test
+ public void testRefreshRateThermalThrottlingMapId() {
+ Layout configLayout = mDeviceStateToLayoutMap.get(4);
+
+ Layout testLayout = new Layout();
+ Layout.Display display1 = testLayout.createDisplayLocked(
+ DisplayAddress.fromPhysicalDisplayId(345L), /* isDefault= */ true,
+ /* isEnabled= */ true, /* displayGroup= */ null, mDisplayIdProducerMock,
+ /* brightnessThrottlingMapId= */ null,
+ /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
+ display1.setRefreshRateThermalThrottlingMapId("test2");
+ testLayout.createDisplayLocked(
+ DisplayAddress.fromPhysicalDisplayId(678L), /* isDefault= */ false,
+ /* isEnabled= */ true, /* displayGroup= */ null, mDisplayIdProducerMock,
+ /* brightnessThrottlingMapId= */ null,
+ /* leadDisplayId= */ Display.DEFAULT_DISPLAY);
+
+ assertEquals(testLayout, configLayout);
+ }
+
////////////////////
// Helper Methods //
////////////////////
@@ -221,6 +241,19 @@ public class DeviceStateToLayoutMapTest {
+ "<address>678</address>\n"
+ "</display>\n"
+ "</layout>\n"
+
+ + "<layout>\n"
+ + "<state>4</state> \n"
+ + "<display enabled=\"true\" defaultDisplay=\"true\" >\n"
+ + "<address>345</address>\n"
+ + "<refreshRateThermalThrottlingMapId>"
+ + "test2"
+ + "</refreshRateThermalThrottlingMapId>"
+ + "</display>\n"
+ + "<display enabled=\"true\">\n"
+ + "<address>678</address>\n"
+ + "</display>\n"
+ + "</layout>\n"
+ "</layouts>\n";
}
}
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java
index fdfcd81cbef9..45f103718602 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java
@@ -20,6 +20,7 @@ package com.android.server.display;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
@@ -28,6 +29,9 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
+import android.os.Temperature;
+import android.util.SparseArray;
+import android.view.SurfaceControl;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -82,6 +86,7 @@ public final class DisplayDeviceConfigTest {
public void testConfigValuesFromDisplayConfig() throws IOException {
setupDisplayDeviceConfigFromDisplayConfigFile();
+ assertEquals(mDisplayDeviceConfig.getName(), "Example Display");
assertEquals(mDisplayDeviceConfig.getAmbientHorizonLong(), 5000);
assertEquals(mDisplayDeviceConfig.getAmbientHorizonShort(), 50);
assertEquals(mDisplayDeviceConfig.getBrightnessRampDecreaseMaxMillis(), 3000);
@@ -237,6 +242,7 @@ public final class DisplayDeviceConfigTest {
@Test
public void testConfigValuesFromConfigResource() {
setupDisplayDeviceConfigFromConfigResourceFile();
+ assertNull(mDisplayDeviceConfig.getName());
assertArrayEquals(mDisplayDeviceConfig.getAutoBrightnessBrighteningLevelsNits(), new
float[]{2.0f, 200.0f, 600.0f}, ZERO_DELTA);
assertArrayEquals(mDisplayDeviceConfig.getAutoBrightnessBrighteningLevelsLux(), new
@@ -315,9 +321,59 @@ public final class DisplayDeviceConfigTest {
// HighBrightnessModeData AmbientLightSensor, RefreshRateLimitations and ProximitySensor.
}
+ @Test
+ public void testRefreshRateThermalThrottlingFromDisplayConfig() throws IOException {
+ setupDisplayDeviceConfigFromDisplayConfigFile();
+
+ SparseArray<SurfaceControl.RefreshRateRange> defaultMap =
+ mDisplayDeviceConfig.getRefreshRateThrottlingData(null);
+ assertNotNull(defaultMap);
+ assertEquals(2, defaultMap.size());
+ assertEquals(30, defaultMap.get(Temperature.THROTTLING_CRITICAL).min, SMALL_DELTA);
+ assertEquals(60, defaultMap.get(Temperature.THROTTLING_CRITICAL).max, SMALL_DELTA);
+ assertEquals(0, defaultMap.get(Temperature.THROTTLING_SHUTDOWN).min, SMALL_DELTA);
+ assertEquals(30, defaultMap.get(Temperature.THROTTLING_SHUTDOWN).max, SMALL_DELTA);
+
+ SparseArray<SurfaceControl.RefreshRateRange> testMap =
+ mDisplayDeviceConfig.getRefreshRateThrottlingData("test");
+ assertNotNull(testMap);
+ assertEquals(1, testMap.size());
+ assertEquals(60, testMap.get(Temperature.THROTTLING_EMERGENCY).min, SMALL_DELTA);
+ assertEquals(90, testMap.get(Temperature.THROTTLING_EMERGENCY).max, SMALL_DELTA);
+ }
+
+ private String getRefreshThermalThrottlingMaps() {
+ return "<refreshRateThrottlingMap>\n"
+ + " <refreshRateThrottlingPoint>\n"
+ + " <thermalStatus>critical</thermalStatus>\n"
+ + " <refreshRateRange>\n"
+ + " <minimum>30</minimum>\n"
+ + " <maximum>60</maximum>\n"
+ + " </refreshRateRange>\n"
+ + " </refreshRateThrottlingPoint>\n"
+ + " <refreshRateThrottlingPoint>\n"
+ + " <thermalStatus>shutdown</thermalStatus>\n"
+ + " <refreshRateRange>\n"
+ + " <minimum>0</minimum>\n"
+ + " <maximum>30</maximum>\n"
+ + " </refreshRateRange>\n"
+ + " </refreshRateThrottlingPoint>\n"
+ + "</refreshRateThrottlingMap>\n"
+ + "<refreshRateThrottlingMap id=\"test\">\n"
+ + " <refreshRateThrottlingPoint>\n"
+ + " <thermalStatus>emergency</thermalStatus>\n"
+ + " <refreshRateRange>\n"
+ + " <minimum>60</minimum>\n"
+ + " <maximum>90</maximum>\n"
+ + " </refreshRateRange>\n"
+ + " </refreshRateThrottlingPoint>\n"
+ + "</refreshRateThrottlingMap>\n";
+ }
+
private String getContent() {
return "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+ "<displayConfiguration>\n"
+ + "<name>Example Display</name>"
+ "<screenBrightnessMap>\n"
+ "<point>\n"
+ "<value>0.0</value>\n"
@@ -557,6 +613,7 @@ public final class DisplayDeviceConfigTest {
+ "<brightness>0.0125</brightness>\n"
+ "</brightnessThrottlingPoint>\n"
+ "</brightnessThrottlingMap>\n"
+ + getRefreshThermalThrottlingMaps()
+ "</thermalThrottling>\n"
+ "<refreshRate>\n"
+ "<defaultRefreshRate>45</defaultRefreshRate>\n"
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
index 1b6b1430ee45..7971fd71ea09 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -28,6 +28,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.anyLong;
@@ -127,6 +128,10 @@ public class DisplayManagerServiceTest {
private Context mContext;
+ private int mHdrConversionMode;
+
+ private int mPreferredHdrOutputType;
+
private final DisplayManagerService.Injector mShortMockedInjector =
new DisplayManagerService.Injector() {
@Override
@@ -176,6 +181,8 @@ public class DisplayManagerServiceTest {
@Override
int setHdrConversionMode(int conversionMode, int preferredHdrOutputType,
int[] autoHdrTypes) {
+ mHdrConversionMode = conversionMode;
+ mPreferredHdrOutputType = preferredHdrOutputType;
return Display.HdrCapabilities.HDR_TYPE_INVALID;
}
@@ -185,7 +192,7 @@ public class DisplayManagerServiceTest {
}
boolean getHdrOutputConversionSupport() {
- return false;
+ return true;
}
}
@@ -1541,6 +1548,40 @@ public class DisplayManagerServiceTest {
new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_SYSTEM));
}
+ @Test
+ public void testCreateHdrConversionMode_withInvalidArguments_throwsException() {
+ assertThrows(
+ "preferredHdrOutputType must not be set if the conversion mode is "
+ + "HDR_CONVERSION_PASSTHROUGH",
+ IllegalArgumentException.class,
+ () -> new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_PASSTHROUGH,
+ Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION));
+ }
+
+ @Test
+ public void testSetHdrConversionModeInternal_withInvalidArguments_throwsException() {
+ DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
+ assertThrows("Expected DisplayManager to throw IllegalArgumentException when "
+ + "preferredHdrOutputType is set and the conversion mode is "
+ + "HDR_CONVERSION_SYSTEM",
+ IllegalArgumentException.class,
+ () -> displayManager.setHdrConversionModeInternal(new HdrConversionMode(
+ HdrConversionMode.HDR_CONVERSION_SYSTEM,
+ Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION)));
+ }
+
+ @Test
+ public void testSetAndGetHdrConversionModeInternal() {
+ DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
+ final HdrConversionMode mode = new HdrConversionMode(
+ HdrConversionMode.HDR_CONVERSION_FORCE,
+ Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION);
+ displayManager.setHdrConversionModeInternal(mode);
+ assertEquals(mode, displayManager.getHdrConversionModeSettingInternal());
+ assertEquals(mode.getConversionMode(), mHdrConversionMode);
+ assertEquals(mode.getPreferredHdrOutputType(), mPreferredHdrOutputType);
+ }
+
private void testDisplayInfoFrameRateOverrideModeCompat(boolean compatChangeEnabled)
throws Exception {
DisplayManagerService displayManager =
diff --git a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
index b698cdf10816..9eb600304f98 100644
--- a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
@@ -687,10 +687,10 @@ public class LogicalDisplayMapperTest {
assertTrue(mLogicalDisplayMapper.getDisplayLocked(device2).isEnabledLocked());
assertFalse(mLogicalDisplayMapper.getDisplayLocked(device1).isInTransitionLocked());
assertFalse(mLogicalDisplayMapper.getDisplayLocked(device2).isInTransitionLocked());
- assertEquals(DisplayDeviceConfig.DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID,
+ assertEquals(DisplayDeviceConfig.DEFAULT_ID,
mLogicalDisplayMapper.getDisplayLocked(device1)
.getBrightnessThrottlingDataIdLocked());
- assertEquals(DisplayDeviceConfig.DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID,
+ assertEquals(DisplayDeviceConfig.DEFAULT_ID,
mLogicalDisplayMapper.getDisplayLocked(device2)
.getBrightnessThrottlingDataIdLocked());
@@ -700,10 +700,10 @@ public class LogicalDisplayMapperTest {
assertTrue(mLogicalDisplayMapper.getDisplayLocked(device2).isEnabledLocked());
assertFalse(mLogicalDisplayMapper.getDisplayLocked(device1).isInTransitionLocked());
assertFalse(mLogicalDisplayMapper.getDisplayLocked(device2).isInTransitionLocked());
- assertEquals(DisplayDeviceConfig.DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID,
+ assertEquals(DisplayDeviceConfig.DEFAULT_ID,
mLogicalDisplayMapper.getDisplayLocked(device1)
.getBrightnessThrottlingDataIdLocked());
- assertEquals(DisplayDeviceConfig.DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID,
+ assertEquals(DisplayDeviceConfig.DEFAULT_ID,
mLogicalDisplayMapper.getDisplayLocked(device2)
.getBrightnessThrottlingDataIdLocked());
}
diff --git a/services/tests/servicestests/src/com/android/server/display/color/ColorDisplayServiceTest.java b/services/tests/servicestests/src/com/android/server/display/color/ColorDisplayServiceTest.java
index bbed1b60f8bf..618ab1b75587 100644
--- a/services/tests/servicestests/src/com/android/server/display/color/ColorDisplayServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/color/ColorDisplayServiceTest.java
@@ -34,6 +34,7 @@ import android.content.Context;
import android.content.ContextWrapper;
import android.content.res.Resources;
import android.hardware.display.ColorDisplayManager;
+import android.hardware.display.DisplayManagerInternal;
import android.hardware.display.Time;
import android.os.Handler;
import android.os.UserHandle;
@@ -77,6 +78,7 @@ public class ColorDisplayServiceTest {
private MockTwilightManager mTwilightManager;
private DisplayTransformManager mDisplayTransformManager;
+ private DisplayManagerInternal mDisplayManagerInternal;
private ColorDisplayService mCds;
private ColorDisplayService.BinderService mBinderService;
@@ -116,6 +118,10 @@ public class ColorDisplayServiceTest {
doReturn(true).when(mDisplayTransformManager).needsLinearColorMatrix();
LocalServices.addService(DisplayTransformManager.class, mDisplayTransformManager);
+ mDisplayManagerInternal = Mockito.mock(DisplayManagerInternal.class);
+ LocalServices.removeServiceForTest(DisplayManagerInternal.class);
+ LocalServices.addService(DisplayManagerInternal.class, mDisplayManagerInternal);
+
mCds = new ColorDisplayService(mContext);
mBinderService = mCds.new BinderService();
LocalServices.addService(ColorDisplayService.ColorDisplayServiceInternal.class,
@@ -142,6 +148,7 @@ public class ColorDisplayServiceTest {
FakeSettingsProvider.clearSettingsProvider();
LocalServices.removeServiceForTest(ColorDisplayService.ColorDisplayServiceInternal.class);
+ LocalServices.removeServiceForTest(DisplayManagerInternal.class);
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java b/services/tests/servicestests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
index 7e6eeee9e713..1b02799e1da4 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.display;
+package com.android.server.display.mode;
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_BRIGHTNESS_THROTTLING_DATA;
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_HIGH_AMBIENT_BRIGHTNESS_THRESHOLDS;
@@ -27,8 +27,7 @@ import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_R
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.INVALID_SIZE;
-import static com.android.server.display.HighBrightnessModeController.HBM_TRANSITION_POINT_INVALID;
+import static com.android.server.display.mode.DisplayModeDirector.Vote.INVALID_SIZE;
import static com.google.common.truth.Truth.assertThat;
@@ -60,12 +59,12 @@ import android.hardware.SensorManager;
import android.hardware.display.BrightnessInfo;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.DisplayListener;
+import android.hardware.display.DisplayManagerGlobal;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.display.DisplayManagerInternal.RefreshRateLimitation;
import android.hardware.fingerprint.IUdfpsRefreshRateRequestCallback;
import android.os.Handler;
import android.os.IThermalEventListener;
-import android.os.IThermalService;
import android.os.Looper;
import android.os.RemoteException;
import android.os.Temperature;
@@ -76,6 +75,7 @@ import android.util.Slog;
import android.util.SparseArray;
import android.util.TypedValue;
import android.view.Display;
+import android.view.DisplayInfo;
import android.view.SurfaceControl.RefreshRateRange;
import android.view.SurfaceControl.RefreshRateRanges;
@@ -84,13 +84,16 @@ import androidx.test.filters.SmallTest;
import com.android.internal.R;
import com.android.internal.display.BrightnessSynchronizer;
+import com.android.internal.os.BackgroundThread;
import com.android.internal.util.Preconditions;
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.internal.util.test.FakeSettingsProviderRule;
import com.android.server.LocalServices;
-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.display.DisplayDeviceConfig;
+import com.android.server.display.TestUtils;
+import com.android.server.display.mode.DisplayModeDirector.BrightnessObserver;
+import com.android.server.display.mode.DisplayModeDirector.DesiredDisplayModeSpecs;
+import com.android.server.display.mode.DisplayModeDirector.Vote;
import com.android.server.sensors.SensorManagerInternal;
import com.android.server.sensors.SensorManagerInternal.ProximityActiveListener;
import com.android.server.statusbar.StatusBarManagerInternal;
@@ -126,6 +129,8 @@ public class DisplayModeDirectorTest {
private static final int DISPLAY_ID = 0;
private static final float TRANSITION_POINT = 0.763f;
+ private static final float HBM_TRANSITION_POINT_INVALID = Float.POSITIVE_INFINITY;
+
private Context mContext;
private FakesInjector mInjector;
private Handler mHandler;
@@ -137,8 +142,6 @@ public class DisplayModeDirectorTest {
public SensorManagerInternal mSensorManagerInternalMock;
@Mock
public DisplayManagerInternal mDisplayManagerInternalMock;
- @Mock
- public IThermalService mThermalServiceMock;
@Before
public void setUp() throws Exception {
@@ -147,7 +150,6 @@ public class DisplayModeDirectorTest {
final MockContentResolver resolver = mSettingsProviderRule.mockContentResolver(mContext);
when(mContext.getContentResolver()).thenReturn(resolver);
mInjector = spy(new FakesInjector());
- when(mInjector.getThermalService()).thenReturn(mThermalServiceMock);
mHandler = new Handler(Looper.getMainLooper());
LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
@@ -1770,11 +1772,12 @@ public class DisplayModeDirectorTest {
ArgumentCaptor<DisplayListener> DisplayCaptor =
ArgumentCaptor.forClass(DisplayListener.class);
- verify(mInjector).registerDisplayListener(DisplayCaptor.capture(), any(Handler.class),
+ verify(mInjector, times(2)).registerDisplayListener(DisplayCaptor.capture(),
+ any(Handler.class),
eq(DisplayManager.EVENT_FLAG_DISPLAY_ADDED
| DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
| DisplayManager.EVENT_FLAG_DISPLAY_REMOVED));
- DisplayListener displayListener = DisplayCaptor.getValue();
+ DisplayListener displayListener = DisplayCaptor.getAllValues().get(0);
// Verify that there is no proximity vote initially
Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY);
@@ -2233,8 +2236,7 @@ public class DisplayModeDirectorTest {
ArgumentCaptor<IThermalEventListener> thermalEventListener =
ArgumentCaptor.forClass(IThermalEventListener.class);
- verify(mThermalServiceMock).registerThermalEventListenerWithType(
- thermalEventListener.capture(), eq(Temperature.TYPE_SKIN));
+ verify(mInjector).registerThermalServiceListener(thermalEventListener.capture());
final IThermalEventListener listener = thermalEventListener.getValue();
// Verify that there is no skin temperature vote initially.
@@ -2243,11 +2245,13 @@ public class DisplayModeDirectorTest {
// Set the skin temperature to critical and verify that we added a vote.
listener.notifyThrottling(getSkinTemp(Temperature.THROTTLING_CRITICAL));
+ BackgroundThread.getHandler().runWithScissors(() -> { }, 500 /*timeout*/);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_SKIN_TEMPERATURE);
assertVoteForRenderFrameRateRange(vote, 0f, 60.f);
// Set the skin temperature to severe and verify that the vote is gone.
listener.notifyThrottling(getSkinTemp(Temperature.THROTTLING_SEVERE));
+ BackgroundThread.getHandler().runWithScissors(() -> { }, 500 /*timeout*/);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_SKIN_TEMPERATURE);
assertNull(vote);
}
@@ -2548,7 +2552,7 @@ public class DisplayModeDirectorTest {
KEY_REFRESH_RATE_IN_HBM_HDR, String.valueOf(fps));
}
- void setBrightnessThrottlingData(String brightnessThrottlingData) {
+ public void setBrightnessThrottlingData(String brightnessThrottlingData) {
putPropertyAndNotify(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
KEY_BRIGHTNESS_THROTTLING_DATA, brightnessThrottlingData);
}
@@ -2706,6 +2710,16 @@ public class DisplayModeDirectorTest {
public void registerDisplayListener(DisplayListener listener, Handler handler, long flag) {}
@Override
+ public Display[] getDisplays() {
+ return new Display[] { createDisplay(DISPLAY_ID) };
+ }
+
+ @Override
+ public boolean getDisplayInfo(int displayId, DisplayInfo displayInfo) {
+ return false;
+ }
+
+ @Override
public BrightnessInfo getBrightnessInfo(int displayId) {
return null;
}
@@ -2716,8 +2730,8 @@ public class DisplayModeDirectorTest {
}
@Override
- public IThermalService getThermalService() {
- return null;
+ public boolean registerThermalServiceListener(IThermalEventListener listener) {
+ return true;
}
@Override
@@ -2725,6 +2739,11 @@ public class DisplayModeDirectorTest {
return true;
}
+ protected Display createDisplay(int id) {
+ return new Display(DisplayManagerGlobal.getInstance(), id, new DisplayInfo(),
+ ApplicationProvider.getApplicationContext().getResources());
+ }
+
void notifyPeakRefreshRateChanged() {
if (mPeakRefreshRateObserver != null) {
mPeakRefreshRateObserver.dispatchChange(false /*selfChange*/,
diff --git a/services/tests/servicestests/src/com/android/server/display/mode/SkinThermalStatusObserverTest.java b/services/tests/servicestests/src/com/android/server/display/mode/SkinThermalStatusObserverTest.java
new file mode 100644
index 000000000000..dd0cd965b8a0
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/display/mode/SkinThermalStatusObserverTest.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display.mode;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import android.hardware.display.DisplayManager;
+import android.os.Handler;
+import android.os.IThermalEventListener;
+import android.os.Temperature;
+import android.util.SparseArray;
+import android.view.Display;
+import android.view.DisplayInfo;
+import android.view.SurfaceControl;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.server.testutils.TestHandler;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+/**
+ * Tests for DisplayModeDirector.SkinThermalStatusObserver. Comply with changes described in
+ * b/266789924
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class SkinThermalStatusObserverTest {
+ private static final float FLOAT_TOLERANCE = 0.01f;
+ private static final int DISPLAY_ID = 1;
+ private static final int DISPLAY_ID_OTHER = 2;
+
+ SkinThermalStatusObserver mObserver;
+
+ private RegisteringFakesInjector mInjector = new RegisteringFakesInjector();
+
+ private final TestHandler mHandler = new TestHandler(null);
+ private final FakeVoteStorage mStorage = new FakeVoteStorage();
+
+ @Before
+ public void setUp() {
+ mObserver = new SkinThermalStatusObserver(mInjector, mStorage, mHandler);
+ }
+
+ @Test
+ public void testRegisterListenersOnObserve() {
+ // GIVEN thermal sensor is available
+ assertNull(mInjector.mThermalEventListener);
+ assertNull(mInjector.mDisplayListener);
+ // WHEN observe is called
+ mObserver.observe();
+ // THEN thermal and display listeners are registered
+ assertEquals(mObserver, mInjector.mThermalEventListener);
+ assertEquals(mObserver, mInjector.mDisplayListener);
+ }
+
+ @Test
+ public void testFailToRegisterThermalListenerOnObserve() {
+ // GIVEN thermal sensor is not available
+ mInjector = new RegisteringFakesInjector(false);
+ mObserver = new SkinThermalStatusObserver(mInjector, mStorage, mHandler);
+ // WHEN observe is called
+ mObserver.observe();
+ // THEN nothing is registered
+ assertNull(mInjector.mThermalEventListener);
+ assertNull(mInjector.mDisplayListener);
+ }
+
+ @Test
+ public void testNotifyWithDefaultVotesForCritical() {
+ // GIVEN 2 displays with no thermalThrottling config
+ mObserver.observe();
+ assertEquals(0, mStorage.mVoteRegistry.size());
+
+ // WHEN thermal sensor notifies CRITICAL
+ mObserver.notifyThrottling(createTemperature(Temperature.THROTTLING_CRITICAL));
+ mHandler.flush();
+
+ // THEN 2 votes are added to storage with (0,60) render refresh rate(default behaviour)
+ assertEquals(2, mStorage.mVoteRegistry.size());
+
+ SparseArray<DisplayModeDirector.Vote> displayVotes = mStorage.mVoteRegistry.get(DISPLAY_ID);
+ assertEquals(1, displayVotes.size());
+
+ DisplayModeDirector.Vote vote = displayVotes.get(
+ DisplayModeDirector.Vote.PRIORITY_SKIN_TEMPERATURE);
+ assertEquals(0, vote.refreshRateRanges.render.min, FLOAT_TOLERANCE);
+ assertEquals(60, vote.refreshRateRanges.render.max, FLOAT_TOLERANCE);
+
+ SparseArray<DisplayModeDirector.Vote> otherDisplayVotes = mStorage.mVoteRegistry.get(
+ DISPLAY_ID_OTHER);
+ assertEquals(1, otherDisplayVotes.size());
+
+ vote = otherDisplayVotes.get(DisplayModeDirector.Vote.PRIORITY_SKIN_TEMPERATURE);
+ assertEquals(0, vote.refreshRateRanges.render.min, FLOAT_TOLERANCE);
+ assertEquals(60, vote.refreshRateRanges.render.max, FLOAT_TOLERANCE);
+ }
+
+ @Test
+ public void testNotifyWithDefaultVotesChangeFromCriticalToSevere() {
+ // GIVEN 2 displays with no thermalThrottling config AND temperature level CRITICAL
+ mObserver.observe();
+ assertEquals(0, mStorage.mVoteRegistry.size());
+ mObserver.notifyThrottling(createTemperature(Temperature.THROTTLING_CRITICAL));
+ // WHEN thermal sensor notifies SEVERE
+ mObserver.notifyThrottling(createTemperature(Temperature.THROTTLING_SEVERE));
+ mHandler.flush();
+ // THEN all votes with PRIORITY_SKIN_TEMPERATURE are removed from the storage
+ assertEquals(0, mStorage.mVoteRegistry.size());
+ }
+
+ @Test
+ public void testNotifyWithDefaultVotesForSevere() {
+ // GIVEN 2 displays with no thermalThrottling config
+ mObserver.observe();
+ assertEquals(0, mStorage.mVoteRegistry.size());
+ // WHEN thermal sensor notifies CRITICAL
+ mObserver.notifyThrottling(createTemperature(Temperature.THROTTLING_SEVERE));
+ mHandler.flush();
+ // THEN nothing is added to the storage
+ assertEquals(0, mStorage.mVoteRegistry.size());
+ }
+
+ @Test
+ public void testNotifiesWithConfigVotes() {
+ // GIVEN 2 displays AND one has thermalThrottling config defined
+ SparseArray<SurfaceControl.RefreshRateRange> displayConfig = new SparseArray<>();
+ displayConfig.put(Temperature.THROTTLING_MODERATE,
+ new SurfaceControl.RefreshRateRange(90.0f, 120.0f));
+ SparseArray<SparseArray<SurfaceControl.RefreshRateRange>> config = new SparseArray<>();
+ config.put(DISPLAY_ID, displayConfig);
+ mInjector = new RegisteringFakesInjector(true, config);
+ mObserver = new SkinThermalStatusObserver(mInjector, mStorage, mHandler);
+ mObserver.observe();
+ mObserver.onDisplayChanged(DISPLAY_ID);
+ assertEquals(0, mStorage.mVoteRegistry.size());
+ // WHEN thermal sensor notifies temperature above configured
+ mObserver.notifyThrottling(createTemperature(Temperature.THROTTLING_SEVERE));
+ mHandler.flush();
+ // THEN vote with refreshRate from config is added to the storage
+ assertEquals(1, mStorage.mVoteRegistry.size());
+ SparseArray<DisplayModeDirector.Vote> displayVotes = mStorage.mVoteRegistry.get(DISPLAY_ID);
+ assertEquals(1, displayVotes.size());
+ DisplayModeDirector.Vote vote = displayVotes.get(
+ DisplayModeDirector.Vote.PRIORITY_SKIN_TEMPERATURE);
+ assertEquals(90, vote.refreshRateRanges.render.min, FLOAT_TOLERANCE);
+ assertEquals(120, vote.refreshRateRanges.render.max, FLOAT_TOLERANCE);
+ }
+
+ private static Temperature createTemperature(@Temperature.ThrottlingStatus int status) {
+ return new Temperature(40.0f, Temperature.TYPE_SKIN, "test_temp", status);
+ }
+
+
+ private static class RegisteringFakesInjector extends DisplayModeDirectorTest.FakesInjector {
+ private IThermalEventListener mThermalEventListener;
+ private DisplayManager.DisplayListener mDisplayListener;
+
+ private final boolean mRegisterThermalListener;
+ private final SparseArray<SparseArray<SurfaceControl.RefreshRateRange>> mOverriddenConfig;
+
+
+ private RegisteringFakesInjector() {
+ this(true);
+ }
+
+ private RegisteringFakesInjector(boolean registerThermalListener) {
+ this(registerThermalListener, new SparseArray<>());
+ }
+
+ private RegisteringFakesInjector(boolean registerThermalListener,
+ SparseArray<SparseArray<SurfaceControl.RefreshRateRange>> overriddenConfig) {
+ mRegisterThermalListener = registerThermalListener;
+ mOverriddenConfig = overriddenConfig;
+ }
+
+ @Override
+ public boolean registerThermalServiceListener(IThermalEventListener listener) {
+ mThermalEventListener = (mRegisterThermalListener ? listener : null);
+ return mRegisterThermalListener;
+ }
+
+ @Override
+ public void registerDisplayListener(DisplayManager.DisplayListener listener,
+ Handler handler, long flag) {
+ mDisplayListener = listener;
+ }
+
+ @Override
+ public Display[] getDisplays() {
+ return new Display[] {createDisplay(DISPLAY_ID), createDisplay(DISPLAY_ID_OTHER)};
+ }
+
+ @Override
+ public boolean getDisplayInfo(int displayId, DisplayInfo displayInfo) {
+ SparseArray<SurfaceControl.RefreshRateRange> config = mOverriddenConfig.get(displayId);
+ if (config != null) {
+ displayInfo.refreshRateThermalThrottling = config;
+ return true;
+ }
+ return false;
+ }
+ }
+
+
+ private static class FakeVoteStorage implements DisplayModeDirector.BallotBox {
+ private final SparseArray<SparseArray<DisplayModeDirector.Vote>> mVoteRegistry =
+ new SparseArray<>();
+
+ @Override
+ public void vote(int displayId, int priority, DisplayModeDirector.Vote vote) {
+ SparseArray<DisplayModeDirector.Vote> votesPerDisplay = mVoteRegistry.get(displayId);
+ if (votesPerDisplay == null) {
+ votesPerDisplay = new SparseArray<>();
+ mVoteRegistry.put(displayId, votesPerDisplay);
+ }
+ if (vote == null) {
+ votesPerDisplay.remove(priority);
+ } else {
+ votesPerDisplay.put(priority, vote);
+ }
+ if (votesPerDisplay.size() == 0) {
+ mVoteRegistry.remove(displayId);
+ }
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/input/KeyboardLayoutManagerTests.kt b/services/tests/servicestests/src/com/android/server/input/KeyboardLayoutManagerTests.kt
index 34540c398deb..b2bfd2bf720c 100644
--- a/services/tests/servicestests/src/com/android/server/input/KeyboardLayoutManagerTests.kt
+++ b/services/tests/servicestests/src/com/android/server/input/KeyboardLayoutManagerTests.kt
@@ -167,8 +167,8 @@ class KeyboardLayoutManagerTests {
Mockito.`when`(context.packageManager).thenReturn(packageManager)
val info = createMockReceiver()
- Mockito.`when`(packageManager.queryBroadcastReceivers(Mockito.any(), Mockito.anyInt()))
- .thenReturn(listOf(info))
+ Mockito.`when`(packageManager.queryBroadcastReceiversAsUser(Mockito.any(), Mockito.anyInt(),
+ Mockito.anyInt())).thenReturn(listOf(info))
Mockito.`when`(packageManager.getReceiverInfo(Mockito.any(), Mockito.anyInt()))
.thenReturn(info.activityInfo)
diff --git a/services/tests/servicestests/src/com/android/server/job/PendingJobQueueTest.java b/services/tests/servicestests/src/com/android/server/job/PendingJobQueueTest.java
index 23d708227e4f..be1375310704 100644
--- a/services/tests/servicestests/src/com/android/server/job/PendingJobQueueTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/PendingJobQueueTest.java
@@ -16,6 +16,9 @@
package com.android.server.job;
+import static android.app.job.JobInfo.NETWORK_TYPE_ANY;
+import static android.app.job.JobInfo.NETWORK_TYPE_NONE;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -525,7 +528,9 @@ public class PendingJobQueueTest {
final boolean ui = random.nextBoolean();
final boolean ej = !ui && random.nextBoolean();
JobStatus job = createJobStatus("testPendingJobSorting_Random",
- createJobInfo(i).setExpedited(ej).setUserInitiated(ui), random.nextInt(250));
+ createJobInfo(i).setExpedited(ej).setUserInitiated(ui)
+ .setRequiredNetworkType(ui ? NETWORK_TYPE_ANY : NETWORK_TYPE_NONE),
+ random.nextInt(250));
job.enqueueTime = random.nextInt(1_000_000);
jobQueue.add(job);
}
@@ -562,7 +567,9 @@ public class PendingJobQueueTest {
final boolean ui = random.nextBoolean();
final boolean ej = !ui && random.nextBoolean();
JobStatus job = createJobStatus("testPendingJobSortingTransitivity",
- createJobInfo(i).setExpedited(ej).setUserInitiated(ui), random.nextInt(50));
+ createJobInfo(i).setExpedited(ej).setUserInitiated(ui)
+ .setRequiredNetworkType(ui ? NETWORK_TYPE_ANY : NETWORK_TYPE_NONE),
+ random.nextInt(50));
job.enqueueTime = random.nextInt(1_000_000);
job.overrideState = random.nextInt(4);
jobQueue.add(job);
@@ -586,7 +593,8 @@ public class PendingJobQueueTest {
final boolean ui = random.nextFloat() < .02;
final boolean ej = !ui && random.nextFloat() < .03;
JobStatus job = createJobStatus("testPendingJobSortingTransitivity_Concentrated",
- createJobInfo(i).setExpedited(ej).setUserInitiated(ui),
+ createJobInfo(i).setExpedited(ej).setUserInitiated(ui)
+ .setRequiredNetworkType(ui ? NETWORK_TYPE_ANY : NETWORK_TYPE_NONE),
random.nextInt(20));
job.enqueueTime = random.nextInt(250);
job.overrideState = random.nextFloat() < .01
diff --git a/services/tests/servicestests/src/com/android/server/location/contexthub/ContextHubServiceTest.java b/services/tests/servicestests/src/com/android/server/location/contexthub/ContextHubServiceTest.java
index fb1a8f87a50b..c0a994ba340a 100644
--- a/services/tests/servicestests/src/com/android/server/location/contexthub/ContextHubServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/location/contexthub/ContextHubServiceTest.java
@@ -40,6 +40,9 @@ import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.io.StringWriter;
import java.util.Arrays;
import java.util.List;
@@ -49,7 +52,8 @@ public class ContextHubServiceTest {
private static final int CONTEXT_HUB_ID = 3;
private static final String CONTEXT_HUB_STRING = "Context Hub Info Test";
- private Context mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ private final Context mContext =
+ InstrumentationRegistry.getInstrumentation().getTargetContext();
@Mock private IContextHubWrapper mMockContextHubWrapper;
@Mock private ContextHubInfo mMockContextHubInfo;
@Rule public final MockitoRule mockito = MockitoJUnit.rule();
@@ -62,20 +66,29 @@ public class ContextHubServiceTest {
when(mMockContextHubInfo.toString()).thenReturn(CONTEXT_HUB_STRING);
when(mMockContextHubWrapper.getHubs()).thenReturn(hubInfo);
- when(mMockContextHubWrapper.supportsLocationSettingNotifications())
- .thenReturn(true);
+ when(mMockContextHubWrapper.supportsLocationSettingNotifications()).thenReturn(true);
when(mMockContextHubWrapper.supportsWifiSettingNotifications()).thenReturn(true);
- when(mMockContextHubWrapper.supportsAirplaneModeSettingNotifications())
- .thenReturn(true);
- when(mMockContextHubWrapper.supportsMicrophoneSettingNotifications())
- .thenReturn(true);
+ when(mMockContextHubWrapper.supportsAirplaneModeSettingNotifications()).thenReturn(true);
+ when(mMockContextHubWrapper.supportsMicrophoneSettingNotifications()).thenReturn(true);
when(mMockContextHubWrapper.supportsBtSettingNotifications()).thenReturn(true);
}
-// TODO (b/254290317): These existing tests are to setup the testing infra for the ContextHub
-// service and verify the constructor correctly registers a context hub.
-// We need to augment these tests to cover the full behavior of the
-// ContextHub service
+ @Test
+ public void testDump_emptyPreloadedNanoappList() {
+ when(mMockContextHubWrapper.getPreloadedNanoappIds()).thenReturn(null);
+ StringWriter stringWriter = new StringWriter();
+
+ ContextHubService service = new ContextHubService(mContext, mMockContextHubWrapper);
+ service.dump(
+ new FileDescriptor(), new PrintWriter(stringWriter), /* args= */ new String[0]);
+
+ assertThat(stringWriter.toString()).isNotEmpty();
+ }
+
+ // TODO (b/254290317): These existing tests are to setup the testing infra for the ContextHub
+ // service and verify the constructor correctly registers a context hub.
+ // We need to augment these tests to cover the full behavior of the
+ // ContextHub service
@Test
public void testConstructorRegistersContextHub() throws RemoteException {
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
index 9686c385e91e..1c33d0de4568 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
@@ -165,10 +165,11 @@ public class LockSettingsServiceTestable extends LockSettingsService {
}
@Override
- protected void tieProfileLockToParent(int userId, LockscreenCredential password) {
+ protected void tieProfileLockToParent(int profileUserId, int parentUserId,
+ LockscreenCredential password) {
Parcel parcel = Parcel.obtain();
parcel.writeParcelable(password, 0);
- mStorage.writeChildProfileLock(userId, parcel.marshall());
+ mStorage.writeChildProfileLock(profileUserId, parcel.marshall());
parcel.recycle();
}
diff --git a/services/tests/servicestests/src/com/android/server/media/LegacyDeviceRouteControllerTest.java b/services/tests/servicestests/src/com/android/server/media/LegacyDeviceRouteControllerTest.java
new file mode 100644
index 000000000000..24e48517f280
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/media/LegacyDeviceRouteControllerTest.java
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) 2023 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.media;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+
+import android.annotation.IdRes;
+import android.content.Context;
+import android.content.res.Resources;
+import android.media.AudioManager;
+import android.media.AudioRoutesInfo;
+import android.media.IAudioRoutesObserver;
+import android.media.MediaRoute2Info;
+import android.os.RemoteException;
+import android.text.TextUtils;
+
+import com.android.internal.R;
+import com.android.server.audio.AudioService;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.runners.Enclosed;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.junit.runners.Parameterized;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+@RunWith(Enclosed.class)
+public class LegacyDeviceRouteControllerTest {
+
+ private static final String DEFAULT_ROUTE_NAME = "default_route";
+ private static final String DEFAULT_HEADPHONES_NAME = "headphone";
+ private static final String DEFAULT_HEADSET_NAME = "headset";
+ private static final String DEFAULT_DOCK_NAME = "dock";
+ private static final String DEFAULT_HDMI_NAME = "hdmi";
+ private static final String DEFAULT_USB_NAME = "usb";
+ private static final int VOLUME_DEFAULT_VALUE = 0;
+ private static final int VOLUME_VALUE_SAMPLE_1 = 10;
+
+ private static AudioRoutesInfo createFakeBluetoothAudioRoute() {
+ AudioRoutesInfo btRouteInfo = new AudioRoutesInfo();
+ btRouteInfo.mainType = AudioRoutesInfo.MAIN_SPEAKER;
+ btRouteInfo.bluetoothName = "bt_device";
+ return btRouteInfo;
+ }
+
+ @RunWith(JUnit4.class)
+ public static class DefaultDeviceRouteValueTest {
+ @Mock
+ private Context mContext;
+ @Mock
+ private Resources mResources;
+ @Mock
+ private AudioManager mAudioManager;
+ @Mock
+ private AudioService mAudioService;
+ @Mock
+ private DeviceRouteController.OnDeviceRouteChangedListener mOnDeviceRouteChangedListener;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ when(mContext.getResources()).thenReturn(mResources);
+ }
+
+ @Test
+ public void initialize_noRoutesInfo_defaultRouteIsNotNull() {
+ // Mocking default_audio_route_name.
+ when(mResources.getText(R.string.default_audio_route_name))
+ .thenReturn(DEFAULT_ROUTE_NAME);
+
+ // Default route should be initialized even when AudioService returns null.
+ when(mAudioService.startWatchingRoutes(any())).thenReturn(null);
+
+ LegacyDeviceRouteController deviceRouteController = new LegacyDeviceRouteController(
+ mContext,
+ mAudioManager,
+ mAudioService,
+ mOnDeviceRouteChangedListener
+ );
+
+ MediaRoute2Info actualMediaRoute = deviceRouteController.getDeviceRoute();
+
+ assertThat(actualMediaRoute.getType()).isEqualTo(MediaRoute2Info.TYPE_BUILTIN_SPEAKER);
+ assertThat(TextUtils.equals(actualMediaRoute.getName(), DEFAULT_ROUTE_NAME))
+ .isTrue();
+ assertThat(actualMediaRoute.getVolume()).isEqualTo(VOLUME_DEFAULT_VALUE);
+ }
+
+ @Test
+ public void initialize_bluetoothRouteAvailable_deviceRouteReturnsDefaultRoute() {
+ // Mocking default_audio_route_name.
+ when(mResources.getText(R.string.default_audio_route_name))
+ .thenReturn(DEFAULT_ROUTE_NAME);
+
+ // This route should be ignored.
+ AudioRoutesInfo fakeBluetoothAudioRoute = createFakeBluetoothAudioRoute();
+ when(mAudioService.startWatchingRoutes(any())).thenReturn(fakeBluetoothAudioRoute);
+
+ LegacyDeviceRouteController deviceRouteController = new LegacyDeviceRouteController(
+ mContext,
+ mAudioManager,
+ mAudioService,
+ mOnDeviceRouteChangedListener
+ );
+
+ MediaRoute2Info actualMediaRoute = deviceRouteController.getDeviceRoute();
+
+ assertThat(actualMediaRoute.getType()).isEqualTo(MediaRoute2Info.TYPE_BUILTIN_SPEAKER);
+ assertThat(TextUtils.equals(actualMediaRoute.getName(), DEFAULT_ROUTE_NAME))
+ .isTrue();
+ assertThat(actualMediaRoute.getVolume()).isEqualTo(VOLUME_DEFAULT_VALUE);
+ }
+ }
+
+ @RunWith(Parameterized.class)
+ public static class DeviceRouteInitializationTest {
+
+ @Parameterized.Parameters
+ public static Collection<Object[]> data() {
+ return Arrays.asList(new Object[][] {
+ { /* expected res */
+ com.android.internal.R.string.default_audio_route_name_headphones,
+ /* expected name */
+ DEFAULT_HEADPHONES_NAME,
+ /* expected type */
+ MediaRoute2Info.TYPE_WIRED_HEADPHONES,
+ /* actual audio route type */
+ AudioRoutesInfo.MAIN_HEADPHONES },
+ { /* expected res */
+ com.android.internal.R.string.default_audio_route_name_headphones,
+ /* expected name */
+ DEFAULT_HEADSET_NAME,
+ /* expected type */
+ MediaRoute2Info.TYPE_WIRED_HEADSET,
+ /* actual audio route type */
+ AudioRoutesInfo.MAIN_HEADSET },
+ { /* expected res */
+ R.string.default_audio_route_name_dock_speakers,
+ /* expected name */
+ DEFAULT_DOCK_NAME,
+ /* expected type */
+ MediaRoute2Info.TYPE_DOCK,
+ /* actual audio route type */
+ AudioRoutesInfo.MAIN_DOCK_SPEAKERS },
+ { /* expected res */
+ R.string.default_audio_route_name_external_device,
+ /* expected name */
+ DEFAULT_HDMI_NAME,
+ /* expected type */
+ MediaRoute2Info.TYPE_HDMI,
+ /* actual audio route type */
+ AudioRoutesInfo.MAIN_HDMI },
+ { /* expected res */
+ R.string.default_audio_route_name_usb,
+ /* expected name */
+ DEFAULT_USB_NAME,
+ /* expected type */
+ MediaRoute2Info.TYPE_USB_DEVICE,
+ /* actual audio route type */
+ AudioRoutesInfo.MAIN_USB }
+ });
+ }
+
+ @Mock
+ private Context mContext;
+ @Mock
+ private Resources mResources;
+ @Mock
+ private AudioManager mAudioManager;
+ @Mock
+ private AudioService mAudioService;
+ @Mock
+ private DeviceRouteController.OnDeviceRouteChangedListener mOnDeviceRouteChangedListener;
+
+ @IdRes
+ private final int mExpectedRouteNameResource;
+ private final String mExpectedRouteNameValue;
+ private final int mExpectedRouteType;
+ private final int mActualAudioRouteType;
+
+ public DeviceRouteInitializationTest(int expectedRouteNameResource,
+ String expectedRouteNameValue,
+ int expectedMediaRouteType,
+ int actualAudioRouteType) {
+ this.mExpectedRouteNameResource = expectedRouteNameResource;
+ this.mExpectedRouteNameValue = expectedRouteNameValue;
+ this.mExpectedRouteType = expectedMediaRouteType;
+ this.mActualAudioRouteType = actualAudioRouteType;
+ }
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ when(mContext.getResources()).thenReturn(mResources);
+ }
+
+ @Test
+ public void initialize_wiredRouteAvailable_deviceRouteReturnsWiredRoute() {
+ // Mocking default_audio_route_name.
+ when(mResources.getText(R.string.default_audio_route_name))
+ .thenReturn(DEFAULT_ROUTE_NAME);
+
+ // At first, WiredRouteController should initialize device
+ // route based on AudioService response.
+ AudioRoutesInfo audioRoutesInfo = new AudioRoutesInfo();
+ audioRoutesInfo.mainType = mActualAudioRouteType;
+ when(mAudioService.startWatchingRoutes(any())).thenReturn(audioRoutesInfo);
+
+ when(mResources.getText(mExpectedRouteNameResource))
+ .thenReturn(mExpectedRouteNameValue);
+
+ LegacyDeviceRouteController deviceRouteController = new LegacyDeviceRouteController(
+ mContext,
+ mAudioManager,
+ mAudioService,
+ mOnDeviceRouteChangedListener
+ );
+
+ MediaRoute2Info actualMediaRoute = deviceRouteController.getDeviceRoute();
+
+ assertThat(actualMediaRoute.getType()).isEqualTo(mExpectedRouteType);
+ assertThat(TextUtils.equals(actualMediaRoute.getName(), mExpectedRouteNameValue))
+ .isTrue();
+ // Volume did not change, so it should be set to default value (0).
+ assertThat(actualMediaRoute.getVolume()).isEqualTo(VOLUME_DEFAULT_VALUE);
+ }
+ }
+
+ @RunWith(JUnit4.class)
+ public static class VolumeAndDeviceRoutesChangesTest {
+ @Mock
+ private Context mContext;
+ @Mock
+ private Resources mResources;
+ @Mock
+ private AudioManager mAudioManager;
+ @Mock
+ private AudioService mAudioService;
+ @Mock
+ private DeviceRouteController.OnDeviceRouteChangedListener mOnDeviceRouteChangedListener;
+
+ @Captor
+ private ArgumentCaptor<IAudioRoutesObserver.Stub> mAudioRoutesObserverCaptor;
+
+ private LegacyDeviceRouteController mDeviceRouteController;
+ private IAudioRoutesObserver.Stub mAudioRoutesObserver;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ when(mContext.getResources()).thenReturn(mResources);
+
+ when(mResources.getText(R.string.default_audio_route_name))
+ .thenReturn(DEFAULT_ROUTE_NAME);
+
+ // Setting built-in speaker as default speaker.
+ AudioRoutesInfo audioRoutesInfo = new AudioRoutesInfo();
+ audioRoutesInfo.mainType = AudioRoutesInfo.MAIN_SPEAKER;
+ when(mAudioService.startWatchingRoutes(mAudioRoutesObserverCaptor.capture()))
+ .thenReturn(audioRoutesInfo);
+
+ mDeviceRouteController = new LegacyDeviceRouteController(
+ mContext,
+ mAudioManager,
+ mAudioService,
+ mOnDeviceRouteChangedListener
+ );
+
+ mAudioRoutesObserver = mAudioRoutesObserverCaptor.getValue();
+ }
+
+ @Test
+ public void newDeviceConnects_wiredDevice_deviceRouteReturnsWiredDevice() {
+ // Connecting wired headset
+ AudioRoutesInfo audioRoutesInfo = new AudioRoutesInfo();
+ audioRoutesInfo.mainType = AudioRoutesInfo.MAIN_HEADPHONES;
+
+ when(mResources.getText(
+ com.android.internal.R.string.default_audio_route_name_headphones))
+ .thenReturn(DEFAULT_HEADPHONES_NAME);
+
+ // Simulating wired device being connected.
+ callAudioRoutesObserver(audioRoutesInfo);
+
+ MediaRoute2Info actualMediaRoute = mDeviceRouteController.getDeviceRoute();
+
+ assertThat(actualMediaRoute.getType()).isEqualTo(MediaRoute2Info.TYPE_WIRED_HEADPHONES);
+ assertThat(TextUtils.equals(actualMediaRoute.getName(), DEFAULT_HEADPHONES_NAME))
+ .isTrue();
+ assertThat(actualMediaRoute.getVolume()).isEqualTo(VOLUME_DEFAULT_VALUE);
+ }
+
+ @Test
+ public void newDeviceConnects_bluetoothDevice_deviceRouteReturnsBluetoothDevice() {
+ // Simulating bluetooth speaker being connected.
+ AudioRoutesInfo fakeBluetoothAudioRoute = createFakeBluetoothAudioRoute();
+ callAudioRoutesObserver(fakeBluetoothAudioRoute);
+
+ MediaRoute2Info actualMediaRoute = mDeviceRouteController.getDeviceRoute();
+
+ assertThat(actualMediaRoute.getType()).isEqualTo(MediaRoute2Info.TYPE_BUILTIN_SPEAKER);
+ assertThat(TextUtils.equals(actualMediaRoute.getName(), DEFAULT_ROUTE_NAME))
+ .isTrue();
+ assertThat(actualMediaRoute.getVolume()).isEqualTo(VOLUME_DEFAULT_VALUE);
+ }
+
+ @Test
+ public void updateVolume_differentValue_updatesDeviceRouteVolume() {
+ MediaRoute2Info actualMediaRoute = mDeviceRouteController.getDeviceRoute();
+ assertThat(actualMediaRoute.getVolume()).isEqualTo(VOLUME_DEFAULT_VALUE);
+
+ assertThat(mDeviceRouteController.updateVolume(VOLUME_VALUE_SAMPLE_1)).isTrue();
+
+ actualMediaRoute = mDeviceRouteController.getDeviceRoute();
+ assertThat(actualMediaRoute.getVolume()).isEqualTo(VOLUME_VALUE_SAMPLE_1);
+ }
+
+ @Test
+ public void updateVolume_sameValue_returnsFalse() {
+ assertThat(mDeviceRouteController.updateVolume(VOLUME_VALUE_SAMPLE_1)).isTrue();
+ assertThat(mDeviceRouteController.updateVolume(VOLUME_VALUE_SAMPLE_1)).isFalse();
+ }
+
+ /**
+ * Simulates {@link IAudioRoutesObserver.Stub#dispatchAudioRoutesChanged(AudioRoutesInfo)}
+ * from {@link AudioService}. This happens when there is a wired route change,
+ * like a wired headset being connected.
+ *
+ * @param audioRoutesInfo updated state of connected wired device
+ */
+ private void callAudioRoutesObserver(AudioRoutesInfo audioRoutesInfo) {
+ try {
+ // this is a captured observer implementation
+ // from WiredRoutesController's AudioService#startWatchingRoutes call
+ mAudioRoutesObserver.dispatchAudioRoutesChanged(audioRoutesInfo);
+ } catch (RemoteException exception) {
+ // Should not happen since the object is mocked.
+ assertWithMessage("An unexpected RemoteException happened.").fail();
+ }
+ }
+ }
+
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index b20c63ca504f..e65f8cf2a199 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -118,10 +118,12 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
+import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
+import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
@@ -4005,6 +4007,169 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
// TODO Check all other fields
}
+ public void testLoadCorruptedShortcuts() throws Exception {
+ initService();
+
+ addPackage("com.android.chrome", 0, 0);
+
+ ShortcutUser user = new ShortcutUser(mService, 0);
+
+ File corruptedShortcutPackage = new File("/data/local/tmp/cts/content/",
+ "broken_shortcut.xml");
+ assertNull(ShortcutPackage.loadFromFile(mService, user, corruptedShortcutPackage, false));
+ }
+
+ public void testSaveCorruptAndLoadUser() throws Exception {
+ // First, create some shortcuts and save.
+ runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+ final Icon icon1 = Icon.createWithResource(getTestContext(), R.drawable.black_64x16);
+ final Icon icon2 = Icon.createWithBitmap(BitmapFactory.decodeResource(
+ getTestContext().getResources(), R.drawable.icon2));
+
+ final ShortcutInfo si1 = makeShortcut(
+ "s1",
+ "title1-1",
+ makeComponent(ShortcutActivity.class),
+ icon1,
+ makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
+ "key1", "val1", "nest", makeBundle("key", 123)),
+ /* weight */ 10);
+
+ final ShortcutInfo si2 = makeShortcut(
+ "s2",
+ "title1-2",
+ /* activity */ null,
+ icon2,
+ makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
+ /* weight */ 12);
+
+ assertTrue(mManager.setDynamicShortcuts(list(si1, si2)));
+
+ assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
+ assertEquals(2, mManager.getRemainingCallCount());
+ });
+ runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
+ final Icon icon1 = Icon.createWithResource(getTestContext(), R.drawable.black_16x64);
+ final Icon icon2 = Icon.createWithBitmap(BitmapFactory.decodeResource(
+ getTestContext().getResources(), R.drawable.icon2));
+
+ final ShortcutInfo si1 = makeShortcut(
+ "s1",
+ "title2-1",
+ makeComponent(ShortcutActivity.class),
+ icon1,
+ makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
+ "key1", "val1", "nest", makeBundle("key", 123)),
+ /* weight */ 10);
+
+ final ShortcutInfo si2 = makeShortcut(
+ "s2",
+ "title2-2",
+ /* activity */ null,
+ icon2,
+ makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
+ /* weight */ 12);
+
+ assertTrue(mManager.setDynamicShortcuts(list(si1, si2)));
+
+ assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
+ assertEquals(2, mManager.getRemainingCallCount());
+ });
+
+ mRunningUsers.put(USER_10, true);
+
+ runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+ final Icon icon1 = Icon.createWithResource(getTestContext(), R.drawable.black_64x64);
+ final Icon icon2 = Icon.createWithBitmap(BitmapFactory.decodeResource(
+ getTestContext().getResources(), R.drawable.icon2));
+
+ final ShortcutInfo si1 = makeShortcut(
+ "s1",
+ "title10-1-1",
+ makeComponent(ShortcutActivity.class),
+ icon1,
+ makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
+ "key1", "val1", "nest", makeBundle("key", 123)),
+ /* weight */ 10);
+
+ final ShortcutInfo si2 = makeShortcut(
+ "s2",
+ "title10-1-2",
+ /* activity */ null,
+ icon2,
+ makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
+ /* weight */ 12);
+
+ assertTrue(mManager.setDynamicShortcuts(list(si1, si2)));
+
+ assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
+ assertEquals(2, mManager.getRemainingCallCount());
+ });
+
+ // Save and corrupt the primary files.
+ mService.saveDirtyInfo();
+ try (Writer os = new FileWriter(
+ mService.getUserFile(UserHandle.USER_SYSTEM).getBaseFile())) {
+ os.write("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+ + "<user locales=\"en\" last-app-scan-time2=\"14400000");
+ }
+ try (Writer os = new FileWriter(mService.getUserFile(USER_10).getBaseFile())) {
+ os.write("<?xml version='1.0' encoding='utf");
+ }
+
+ // Restore.
+ initService();
+
+ // Before the load, the map should be empty.
+ assertEquals(0, mService.getShortcutsForTest().size());
+
+ // this will pre-load the per-user info.
+ mService.handleUnlockUser(UserHandle.USER_SYSTEM);
+
+ // Now it's loaded.
+ assertEquals(1, mService.getShortcutsForTest().size());
+
+ runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+ assertShortcutIds(assertAllDynamic(assertAllHaveIntents(assertAllHaveIcon(
+ mManager.getDynamicShortcuts()))), "s1", "s2");
+ assertEquals(2, mManager.getRemainingCallCount());
+
+ assertEquals("title1-1", getCallerShortcut("s1").getTitle());
+ assertEquals("title1-2", getCallerShortcut("s2").getTitle());
+ });
+ runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
+ assertShortcutIds(assertAllDynamic(assertAllHaveIntents(assertAllHaveIcon(
+ mManager.getDynamicShortcuts()))), "s1", "s2");
+ assertEquals(2, mManager.getRemainingCallCount());
+
+ assertEquals("title2-1", getCallerShortcut("s1").getTitle());
+ assertEquals("title2-2", getCallerShortcut("s2").getTitle());
+ });
+
+ // Start another user
+ mService.handleUnlockUser(USER_10);
+
+ // Now the size is 2.
+ assertEquals(2, mService.getShortcutsForTest().size());
+
+ runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+ assertShortcutIds(assertAllDynamic(assertAllHaveIntents(assertAllHaveIcon(
+ mManager.getDynamicShortcuts()))), "s1", "s2");
+ assertEquals(2, mManager.getRemainingCallCount());
+
+ assertEquals("title10-1-1", getCallerShortcut("s1").getTitle());
+ assertEquals("title10-1-2", getCallerShortcut("s2").getTitle());
+ });
+
+ // Try stopping the user
+ mService.handleStopUser(USER_10);
+
+ // Now it's unloaded.
+ assertEquals(1, mService.getShortcutsForTest().size());
+
+ // TODO Check all other fields
+ }
+
public void testCleanupPackage() {
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertTrue(mManager.setDynamicShortcuts(list(
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index 15fd73cf4674..01e56a0ddae6 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -2349,7 +2349,7 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
* can still be read.
*/
public void testLoadLegacySavedFile() throws Exception {
- final File path = mService.getUserFile(USER_0);
+ final File path = mService.getUserFile(USER_0).getBaseFile();
path.getParentFile().mkdirs();
try (Writer w = new FileWriter(path)) {
w.write(readTestAsset("shortcut/shortcut_legacy_file.xml"));
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceShellCommandTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceShellCommandTest.java
index 4434a32f733b..32c9e75e1288 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceShellCommandTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceShellCommandTest.java
@@ -121,4 +121,31 @@ public class UserManagerServiceShellCommandTest {
assertEquals("Couldn't get main user.", mOutStream.toString().trim());
}
+ @Test
+ public void testCanSwitchToHeadlessSystemUser() {
+ doReturn(true).when(mUserManagerService).canSwitchToHeadlessSystemUser();
+ doReturn(mWriter).when(mCommand).getOutPrintWriter();
+
+ assertEquals(0, mCommand.exec(mBinder, in, out, err,
+ new String[]{"can-switch-to-headless-system-user"},
+ mShellCallback, mResultReceiver));
+
+ mWriter.flush();
+ assertEquals("true", mOutStream.toString().trim());
+ }
+
+
+ @Test
+ public void testIsMainUserPermanentAdmin() {
+ doReturn(false).when(mUserManagerService).isMainUserPermanentAdmin();
+ doReturn(mWriter).when(mCommand).getOutPrintWriter();
+
+ assertEquals(0, mCommand.exec(mBinder, in, out, err,
+ new String[]{"is-main-user-permanent-admin"}, mShellCallback, mResultReceiver));
+
+ mWriter.flush();
+ assertEquals("false", mOutStream.toString().trim());
+ }
+
+
}
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 d71deaf3a88d..a0fb3deeb131 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -16,7 +16,6 @@
package com.android.server.power;
-import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
import static android.app.AppOpsManager.MODE_ALLOWED;
@@ -30,8 +29,6 @@ import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import static org.mockito.AdditionalMatchers.gt;
-import static org.mockito.AdditionalMatchers.leq;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -153,9 +150,6 @@ public class PowerManagerServiceTest {
@Mock
private InattentiveSleepWarningController mInattentiveSleepWarningControllerMock;
- @Mock
- private ActivityManagerInternal mActivityManagerInternal;
-
private PowerManagerService mService;
private ContextWrapper mContextSpy;
private BatteryReceiver mBatteryReceiver;
@@ -211,7 +205,6 @@ public class PowerManagerServiceTest {
addLocalServiceMock(ActivityManagerInternal.class, mActivityManagerInternalMock);
addLocalServiceMock(AttentionManagerInternal.class, mAttentionManagerInternalMock);
addLocalServiceMock(DreamManagerInternal.class, mDreamManagerInternalMock);
- addLocalServiceMock(ActivityManagerInternal.class, mActivityManagerInternal);
mContextSpy = spy(new ContextWrapper(ApplicationProvider.getApplicationContext()));
mResourcesSpy = spy(mContextSpy.getResources());
@@ -228,14 +221,6 @@ public class PowerManagerServiceTest {
mClock = new OffsettableClock.Stopped();
mTestLooper = new TestLooper(mClock::now);
-
- // Set up canHoldWakeLocksInDeepDoze.
- // - procstate <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE -> true
- // - procstate > PROCESS_STATE_BOUND_FOREGROUND_SERVICE -> false
- when(mActivityManagerInternal.canHoldWakeLocksInDeepDoze(
- anyInt(), leq(PROCESS_STATE_BOUND_FOREGROUND_SERVICE))).thenReturn(true);
- when(mActivityManagerInternal.canHoldWakeLocksInDeepDoze(
- anyInt(), gt(PROCESS_STATE_BOUND_FOREGROUND_SERVICE))).thenReturn(false);
}
private PowerManagerService createService() {
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/CpuWakeupStatsTest.java b/services/tests/servicestests/src/com/android/server/power/stats/CpuWakeupStatsTest.java
index 34e45c2096ea..178670e678f0 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/CpuWakeupStatsTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/stats/CpuWakeupStatsTest.java
@@ -18,6 +18,7 @@ package com.android.server.power.stats;
import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_ALARM;
import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_UNKNOWN;
+import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_WIFI;
import static com.android.server.power.stats.CpuWakeupStats.WAKEUP_REASON_HALF_WINDOW_MS;
import static com.android.server.power.stats.CpuWakeupStats.WAKEUP_RETENTION_MS;
@@ -45,6 +46,7 @@ import java.util.concurrent.ThreadLocalRandom;
@RunWith(AndroidJUnit4.class)
public class CpuWakeupStatsTest {
private static final String KERNEL_REASON_ALARM_IRQ = "120 test.alarm.device";
+ private static final String KERNEL_REASON_WIFI_IRQ = "120 test.wifi.device";
private static final String KERNEL_REASON_UNKNOWN_IRQ = "140 test.unknown.device";
private static final String KERNEL_REASON_UNKNOWN = "free-form-reason test.alarm.device";
private static final String KERNEL_REASON_UNSUPPORTED = "-1 test.alarm.device";
@@ -68,22 +70,23 @@ public class CpuWakeupStatsTest {
final Set<Long> timestamps = new HashSet<>();
final long firstWakeup = 453192;
- obj.noteWakeupTimeAndReason(firstWakeup, 32, "unused");
+ obj.noteWakeupTimeAndReason(firstWakeup, 32, KERNEL_REASON_UNKNOWN_IRQ);
timestamps.add(firstWakeup);
for (int i = 1; i < 1000; i++) {
final long delta = mRandom.nextLong(WAKEUP_RETENTION_MS);
if (timestamps.add(firstWakeup + delta)) {
- obj.noteWakeupTimeAndReason(firstWakeup + delta, i, "unused");
+ obj.noteWakeupTimeAndReason(firstWakeup + delta, i, KERNEL_REASON_UNKNOWN_IRQ);
}
}
assertThat(obj.mWakeupEvents.size()).isEqualTo(timestamps.size());
- obj.noteWakeupTimeAndReason(firstWakeup + WAKEUP_RETENTION_MS + 1242, 231, "unused");
+ obj.noteWakeupTimeAndReason(firstWakeup + WAKEUP_RETENTION_MS + 1242, 231,
+ KERNEL_REASON_UNKNOWN_IRQ);
assertThat(obj.mWakeupEvents.size()).isEqualTo(timestamps.size());
for (int i = 0; i < 100; i++) {
final long now = mRandom.nextLong(WAKEUP_RETENTION_MS + 1, 100 * WAKEUP_RETENTION_MS);
- obj.noteWakeupTimeAndReason(now, i, "unused");
+ obj.noteWakeupTimeAndReason(now, i, KERNEL_REASON_UNKNOWN_IRQ);
assertThat(obj.mWakeupEvents.closestIndexOnOrBefore(now - WAKEUP_RETENTION_MS))
.isLessThan(0);
}
@@ -111,17 +114,45 @@ public class CpuWakeupStatsTest {
assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_ALARM).get(TEST_UID_1)).isEqualTo(false);
assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_ALARM).get(TEST_UID_2)).isEqualTo(false);
assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_ALARM).get(TEST_UID_3)).isEqualTo(true);
+ assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_ALARM).get(TEST_UID_4)).isEqualTo(false);
assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_ALARM).get(TEST_UID_5)).isEqualTo(true);
}
@Test
- public void alarmIrqAttributionCombined() {
+ public void wifiIrqAttributionSolo() {
+ final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_3, mHandler);
+ final long wakeupTime = 12423121;
+
+ obj.noteWakeupTimeAndReason(wakeupTime, 1, KERNEL_REASON_WIFI_IRQ);
+
+ // Outside the window, so should be ignored.
+ obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI,
+ wakeupTime - WAKEUP_REASON_HALF_WINDOW_MS - 1, TEST_UID_1);
+ obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI,
+ wakeupTime + WAKEUP_REASON_HALF_WINDOW_MS + 1, TEST_UID_2);
+ // Should be attributed
+ obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI, wakeupTime + 3, TEST_UID_4, TEST_UID_5);
+
+ final SparseArray<SparseBooleanArray> attribution = obj.mWakeupAttribution.get(wakeupTime);
+ assertThat(attribution).isNotNull();
+ assertThat(attribution.size()).isEqualTo(1);
+ assertThat(attribution.contains(CPU_WAKEUP_SUBSYSTEM_WIFI)).isTrue();
+ assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_1)).isEqualTo(false);
+ assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_2)).isEqualTo(false);
+ assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_3)).isEqualTo(false);
+ assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_4)).isEqualTo(true);
+ assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_5)).isEqualTo(true);
+ }
+
+ @Test
+ public void alarmAndWifiIrqAttribution() {
final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_3, mHandler);
final long wakeupTime = 92123210;
obj.noteWakeupTimeAndReason(wakeupTime, 4,
- KERNEL_REASON_UNKNOWN_IRQ + ":" + KERNEL_REASON_ALARM_IRQ);
+ KERNEL_REASON_WIFI_IRQ + ":" + KERNEL_REASON_ALARM_IRQ);
+ // Alarm activity
// Outside the window, so should be ignored.
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM,
wakeupTime - WAKEUP_REASON_HALF_WINDOW_MS - 1, TEST_UID_1);
@@ -132,16 +163,34 @@ public class CpuWakeupStatsTest {
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime - 3, TEST_UID_4,
TEST_UID_5);
+ // Wifi activity
+ // Outside the window, so should be ignored.
+ obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI,
+ wakeupTime - WAKEUP_REASON_HALF_WINDOW_MS - 1, TEST_UID_4);
+ obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI,
+ wakeupTime + WAKEUP_REASON_HALF_WINDOW_MS + 1, TEST_UID_3);
+ // Should be attributed
+ obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI, wakeupTime + 2, TEST_UID_1);
+ obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI, wakeupTime - 1, TEST_UID_2,
+ TEST_UID_5);
+
final SparseArray<SparseBooleanArray> attribution = obj.mWakeupAttribution.get(wakeupTime);
assertThat(attribution).isNotNull();
assertThat(attribution.size()).isEqualTo(2);
+
assertThat(attribution.contains(CPU_WAKEUP_SUBSYSTEM_ALARM)).isTrue();
assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_ALARM).get(TEST_UID_1)).isEqualTo(false);
assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_ALARM).get(TEST_UID_2)).isEqualTo(false);
assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_ALARM).get(TEST_UID_3)).isEqualTo(true);
assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_ALARM).get(TEST_UID_4)).isEqualTo(true);
assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_ALARM).get(TEST_UID_5)).isEqualTo(true);
- assertThat(attribution.contains(CPU_WAKEUP_SUBSYSTEM_UNKNOWN)).isTrue();
+
+ assertThat(attribution.contains(CPU_WAKEUP_SUBSYSTEM_WIFI)).isTrue();
+ assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_1)).isEqualTo(true);
+ assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_2)).isEqualTo(true);
+ assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_3)).isEqualTo(false);
+ assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_4)).isEqualTo(false);
+ assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_5)).isEqualTo(true);
}
@Test
@@ -151,9 +200,11 @@ public class CpuWakeupStatsTest {
obj.noteWakeupTimeAndReason(wakeupTime, 24, KERNEL_REASON_UNKNOWN_IRQ);
+ assertThat(obj.mWakeupEvents.size()).isEqualTo(1);
+
// Unrelated subsystems, should not be attributed
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime + 5, TEST_UID_3);
- obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime - 3, TEST_UID_4,
+ obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI, wakeupTime - 3, TEST_UID_4,
TEST_UID_5);
final SparseArray<SparseBooleanArray> attribution = obj.mWakeupAttribution.get(wakeupTime);
@@ -165,42 +216,48 @@ public class CpuWakeupStatsTest {
}
@Test
- public void unknownAttribution() {
+ public void unknownWakeupIgnored() {
final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_3, mHandler);
final long wakeupTime = 72123210;
obj.noteWakeupTimeAndReason(wakeupTime, 34, KERNEL_REASON_UNKNOWN);
- // Should be ignored as this type of wakeup is unsupported.
+ // Should be ignored as this type of wakeup is not known.
+ assertThat(obj.mWakeupEvents.size()).isEqualTo(0);
+
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime + 5, TEST_UID_3);
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime - 3, TEST_UID_4);
- // There should be nothing in the attribution map.
+ // Any nearby activity should not end up in the attribution map.
assertThat(obj.mWakeupAttribution.size()).isEqualTo(0);
}
@Test
- public void unsupportedAttribution() {
+ public void unsupportedWakeupIgnored() {
final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_3, mHandler);
long wakeupTime = 970934;
obj.noteWakeupTimeAndReason(wakeupTime, 34, KERNEL_REASON_UNSUPPORTED);
// Should be ignored as this type of wakeup is unsupported.
+ assertThat(obj.mWakeupEvents.size()).isEqualTo(0);
+
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime + 5, TEST_UID_3);
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime - 3, TEST_UID_4);
- // There should be nothing in the attribution map.
+ // Any nearby activity should not end up in the attribution map.
assertThat(obj.mWakeupAttribution.size()).isEqualTo(0);
wakeupTime = 883124;
obj.noteWakeupTimeAndReason(wakeupTime, 3, KERNEL_REASON_ABORT);
// Should be ignored as this type of wakeup is unsupported.
- obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime + 2, TEST_UID_1, TEST_UID_4);
- obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime - 5, TEST_UID_3);
+ assertThat(obj.mWakeupEvents.size()).isEqualTo(0);
+
+ obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI, wakeupTime + 2, TEST_UID_1, TEST_UID_4);
+ obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI, wakeupTime - 5, TEST_UID_3);
- // There should be nothing in the attribution map.
+ // Any nearby activity should not end up in the attribution map.
assertThat(obj.mWakeupAttribution.size()).isEqualTo(0);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/MockBatteryStatsImpl.java b/services/tests/servicestests/src/com/android/server/power/stats/MockBatteryStatsImpl.java
index f8033557f0f0..d78ab8677800 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/MockBatteryStatsImpl.java
+++ b/services/tests/servicestests/src/com/android/server/power/stats/MockBatteryStatsImpl.java
@@ -231,6 +231,10 @@ public class MockBatteryStatsImpl extends BatteryStatsImpl {
setExternalStatsSyncLocked(mExternalStatsSync);
}
+ @Override
+ public void writeSyncLocked() {
+ }
+
public static class DummyExternalStatsSync implements ExternalStatsSync {
public int flags = 0;
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/NetworkTimeUpdateServiceTest.java b/services/tests/servicestests/src/com/android/server/timedetector/NetworkTimeUpdateServiceTest.java
index 2f431bd8a416..d91ee92e005e 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/NetworkTimeUpdateServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/NetworkTimeUpdateServiceTest.java
@@ -111,12 +111,11 @@ public class NetworkTimeUpdateServiceTest {
verify(mMockNtpTrustedTime).forceRefresh(mDummyNetwork);
// Check everything happened that was supposed to.
+ NetworkTimeSuggestion expectedSuggestion = createExpectedSuggestion(timeResult);
+ verify(mockCallback).submitSuggestion(expectedSuggestion);
long expectedDelayMillis = normalPollingIntervalMillis;
verify(mockCallback).scheduleNextRefresh(
timeResult.getElapsedRealtimeMillis() + expectedDelayMillis);
-
- NetworkTimeSuggestion expectedSuggestion = createExpectedSuggestion(timeResult);
- verify(mockCallback).submitSuggestion(expectedSuggestion);
}
@Test
@@ -148,6 +147,7 @@ public class NetworkTimeUpdateServiceTest {
verify(mMockNtpTrustedTime).forceRefresh(mDummyNetwork);
// Check everything happened that was supposed to.
+ verify(mockCallback, never()).submitSuggestion(any());
long expectedDelayMillis;
if (i < tryAgainTimesMax) {
expectedDelayMillis = shortPollingIntervalMillis;
@@ -156,7 +156,6 @@ public class NetworkTimeUpdateServiceTest {
}
verify(mockCallback).scheduleNextRefresh(
mFakeElapsedRealtimeClock.getElapsedRealtimeMillis() + expectedDelayMillis);
- verify(mockCallback, never()).submitSuggestion(any());
reset(mMockNtpTrustedTime);
}
@@ -196,10 +195,10 @@ public class NetworkTimeUpdateServiceTest {
// initially.
verify(mMockNtpTrustedTime).forceRefresh(mDummyNetwork);
+ verify(mockCallback, times(1)).submitSuggestion(expectedSuggestion);
long expectedDelayMillis = normalPollingIntervalMillis;
verify(mockCallback).scheduleNextRefresh(
timeResult.getElapsedRealtimeMillis() + expectedDelayMillis);
- verify(mockCallback, times(1)).submitSuggestion(expectedSuggestion);
reset(mMockNtpTrustedTime);
}
@@ -222,6 +221,9 @@ public class NetworkTimeUpdateServiceTest {
// Expect a refresh attempt each time as the cached network time is too old.
verify(mMockNtpTrustedTime).forceRefresh(mDummyNetwork);
+ // No valid time, no suggestion.
+ verify(mockCallback, never()).submitSuggestion(any());
+
// Check the scheduling.
long expectedDelayMillis;
if (i < tryAgainTimesMax) {
@@ -232,9 +234,6 @@ public class NetworkTimeUpdateServiceTest {
verify(mockCallback).scheduleNextRefresh(
mFakeElapsedRealtimeClock.getElapsedRealtimeMillis() + expectedDelayMillis);
- // No valid time, no suggestion.
- verify(mockCallback, never()).submitSuggestion(any());
-
reset(mMockNtpTrustedTime);
// Simulate the passage of time for realism.
@@ -276,10 +275,10 @@ public class NetworkTimeUpdateServiceTest {
// initially.
verify(mMockNtpTrustedTime).forceRefresh(mDummyNetwork);
+ verify(mockCallback, times(1)).submitSuggestion(expectedSuggestion);
long expectedDelayMillis = normalPollingIntervalMillis;
verify(mockCallback).scheduleNextRefresh(
timeResult.getElapsedRealtimeMillis() + expectedDelayMillis);
- verify(mockCallback, times(1)).submitSuggestion(expectedSuggestion);
reset(mMockNtpTrustedTime);
}
@@ -302,15 +301,14 @@ public class NetworkTimeUpdateServiceTest {
// Expect a refresh attempt each time as the cached network time is too old.
verify(mMockNtpTrustedTime).forceRefresh(mDummyNetwork);
- // Check the scheduling. tryAgainTimesMax == 0, so the algorithm should start with
+ // No valid time, no suggestion.
+ verify(mockCallback, never()).submitSuggestion(any());
+ // Check the scheduling. tryAgainTimesMax == 0, so the algorithm should start with
long expectedDelayMillis = normalPollingIntervalMillis;
verify(mockCallback).scheduleNextRefresh(
mFakeElapsedRealtimeClock.getElapsedRealtimeMillis() + expectedDelayMillis);
- // No valid time, no suggestion.
- verify(mockCallback, never()).submitSuggestion(any());
-
reset(mMockNtpTrustedTime);
// Simulate the passage of time for realism.
@@ -352,10 +350,10 @@ public class NetworkTimeUpdateServiceTest {
// initially.
verify(mMockNtpTrustedTime).forceRefresh(mDummyNetwork);
+ verify(mockCallback, times(1)).submitSuggestion(expectedSuggestion);
long expectedDelayMillis = normalPollingIntervalMillis;
verify(mockCallback).scheduleNextRefresh(
timeResult.getElapsedRealtimeMillis() + expectedDelayMillis);
- verify(mockCallback, times(1)).submitSuggestion(expectedSuggestion);
reset(mMockNtpTrustedTime);
}
@@ -378,15 +376,15 @@ public class NetworkTimeUpdateServiceTest {
// Expect a refresh attempt each time as the cached network time is too old.
verify(mMockNtpTrustedTime).forceRefresh(mDummyNetwork);
+ // No valid time, no suggestion.
+ verify(mockCallback, never()).submitSuggestion(any());
+
// Check the scheduling. tryAgainTimesMax == -1, so it should always be
// shortPollingIntervalMillis.
long expectedDelayMillis = shortPollingIntervalMillis;
verify(mockCallback).scheduleNextRefresh(
mFakeElapsedRealtimeClock.getElapsedRealtimeMillis() + expectedDelayMillis);
- // No valid time, no suggestion.
- verify(mockCallback, never()).submitSuggestion(any());
-
reset(mMockNtpTrustedTime);
// Simulate the passage of time for realism.
@@ -426,11 +424,11 @@ public class NetworkTimeUpdateServiceTest {
// initially.
verify(mMockNtpTrustedTime).forceRefresh(mDummyNetwork);
+ NetworkTimeSuggestion expectedSuggestion = createExpectedSuggestion(timeResult1);
+ verify(mockCallback, times(1)).submitSuggestion(expectedSuggestion);
long expectedDelayMillis = normalPollingIntervalMillis;
verify(mockCallback).scheduleNextRefresh(
timeResult1.getElapsedRealtimeMillis() + expectedDelayMillis);
- NetworkTimeSuggestion expectedSuggestion = createExpectedSuggestion(timeResult1);
- verify(mockCallback, times(1)).submitSuggestion(expectedSuggestion);
reset(mMockNtpTrustedTime);
}
@@ -453,12 +451,13 @@ public class NetworkTimeUpdateServiceTest {
// Expect the refresh attempt to have been made: the timeResult is too old.
verify(mMockNtpTrustedTime).forceRefresh(mDummyNetwork);
+ // No valid time, no suggestion.
+ verify(mockCallback, never()).submitSuggestion(any());
+
long expectedDelayMillis = shortPollingIntervalMillis;
verify(mockCallback).scheduleNextRefresh(
mFakeElapsedRealtimeClock.getElapsedRealtimeMillis() + expectedDelayMillis);
- // No valid time, no suggestion.
- verify(mockCallback, never()).submitSuggestion(any());
reset(mMockNtpTrustedTime);
}
@@ -485,11 +484,11 @@ public class NetworkTimeUpdateServiceTest {
// Expect the refresh attempt to have been made: the timeResult is too old.
verify(mMockNtpTrustedTime).forceRefresh(mDummyNetwork);
+ NetworkTimeSuggestion expectedSuggestion = createExpectedSuggestion(timeResult2);
+ verify(mockCallback, times(1)).submitSuggestion(expectedSuggestion);
long expectedDelayMillis = normalPollingIntervalMillis;
verify(mockCallback).scheduleNextRefresh(
timeResult2.getElapsedRealtimeMillis() + expectedDelayMillis);
- NetworkTimeSuggestion expectedSuggestion = createExpectedSuggestion(timeResult2);
- verify(mockCallback, times(1)).submitSuggestion(expectedSuggestion);
reset(mMockNtpTrustedTime);
}
}
@@ -525,16 +524,16 @@ public class NetworkTimeUpdateServiceTest {
// Expect no refresh attempt to have been made.
verify(mMockNtpTrustedTime, never()).forceRefresh(any());
+ // Suggestions must be made every time if the cached time value is not too old in case it
+ // was refreshed by a different component.
+ NetworkTimeSuggestion expectedSuggestion = createExpectedSuggestion(timeResult);
+ verify(mockCallback, times(1)).submitSuggestion(expectedSuggestion);
+
// The next wake-up should be rescheduled for when the cached time value will become too
// old.
long expectedDelayMillis = normalPollingIntervalMillis;
verify(mockCallback).scheduleNextRefresh(
timeResult.getElapsedRealtimeMillis() + expectedDelayMillis);
-
- // Suggestions must be made every time if the cached time value is not too old in case it
- // was refreshed by a different component.
- NetworkTimeSuggestion expectedSuggestion = createExpectedSuggestion(timeResult);
- verify(mockCallback, times(1)).submitSuggestion(expectedSuggestion);
}
/**
@@ -568,13 +567,13 @@ public class NetworkTimeUpdateServiceTest {
// Expect a refresh attempt to have been made.
verify(mMockNtpTrustedTime, times(1)).forceRefresh(mDummyNetwork);
+ // Suggestions should not be made if the cached time value is too old.
+ verify(mockCallback, never()).submitSuggestion(any());
+
// The next wake-up should be rescheduled using the short polling interval.
long expectedDelayMillis = shortPollingIntervalMillis;
verify(mockCallback).scheduleNextRefresh(
mFakeElapsedRealtimeClock.getElapsedRealtimeMillis() + expectedDelayMillis);
-
- // Suggestions should not be made if the cached time value is too old.
- verify(mockCallback, never()).submitSuggestion(any());
}
/**
@@ -614,6 +613,9 @@ public class NetworkTimeUpdateServiceTest {
verify(mMockNtpTrustedTime, times(1)).forceRefresh(mDummyNetwork);
lastRefreshAttemptElapsedMillis = mFakeElapsedRealtimeClock.getElapsedRealtimeMillis();
+ // Suggestions should not be made if the cached time value is too old.
+ verify(mockCallback, never()).submitSuggestion(any());
+
// The next wake-up should be rescheduled using the normalPollingIntervalMillis.
// Because the time signal age > normalPollingIntervalMillis, the last refresh attempt
// time will be used.
@@ -622,9 +624,6 @@ public class NetworkTimeUpdateServiceTest {
lastRefreshAttemptElapsedMillis + expectedDelayMillis;
verify(mockCallback).scheduleNextRefresh(expectedNextRefreshElapsedMillis);
- // Suggestions should not be made if the cached time value is too old.
- verify(mockCallback, never()).submitSuggestion(any());
-
reset(mMockNtpTrustedTime);
}
@@ -646,6 +645,9 @@ public class NetworkTimeUpdateServiceTest {
// Expect no refresh attempt to have been made: time elapsed isn't enough.
verify(mMockNtpTrustedTime, never()).forceRefresh(any());
+ // Suggestions should not be made if the cached time value is too old.
+ verify(mockCallback, never()).submitSuggestion(any());
+
// The next wake-up should be rescheduled using the normal polling interval and the last
// refresh attempt time.
long expectedDelayMillis = normalPollingIntervalMillis;
@@ -653,11 +655,110 @@ public class NetworkTimeUpdateServiceTest {
lastRefreshAttemptElapsedMillis + expectedDelayMillis;
verify(mockCallback).scheduleNextRefresh(expectedNextRefreshElapsedMillis);
+ reset(mMockNtpTrustedTime);
+ }
+ }
+
+ /**
+ * Confirms that if a refreshAndRescheduleIfRequired() call is made and there was a recently
+ * failed refresh, then another won't be scheduled too soon.
+ */
+ @Test
+ public void engineImpl_refreshAndRescheduleIfRequired_minimumRefreshTimeEnforced_b269425914() {
+ mFakeElapsedRealtimeClock.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS);
+
+ int normalPollingIntervalMillis = 7777777;
+ int shortPollingIntervalMillis = 3333;
+ int tryAgainTimesMax = 3;
+ NetworkTimeUpdateService.Engine engine = new NetworkTimeUpdateService.EngineImpl(
+ mFakeElapsedRealtimeClock,
+ normalPollingIntervalMillis, shortPollingIntervalMillis, tryAgainTimesMax,
+ mMockNtpTrustedTime);
+
+ NtpTrustedTime.TimeResult timeResult1;
+
+ // Start out with a successful refresh.
+ long lastRefreshAttemptElapsedMillis;
+ {
+ mFakeElapsedRealtimeClock.incrementMillis(normalPollingIntervalMillis);
+ timeResult1 = createNtpTimeResult(mFakeElapsedRealtimeClock.getElapsedRealtimeMillis());
+ when(mMockNtpTrustedTime.getCachedTimeResult()).thenReturn(null, timeResult1);
+ when(mMockNtpTrustedTime.forceRefresh(mDummyNetwork)).thenReturn(true);
+
+ RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
+ // Trigger the engine's logic.
+ engine.refreshAndRescheduleIfRequired(mDummyNetwork, "Test", mockCallback);
+
+ // Expect a refresh attempt to have been made.
+ verify(mMockNtpTrustedTime, times(1)).forceRefresh(mDummyNetwork);
+ lastRefreshAttemptElapsedMillis = mFakeElapsedRealtimeClock.getElapsedRealtimeMillis();
+
+ NetworkTimeSuggestion expectedSuggestion = createExpectedSuggestion(timeResult1);
+ verify(mockCallback, times(1)).submitSuggestion(expectedSuggestion);
+
+ // The next wake-up should be rescheduled using the normalPollingIntervalMillis.
+ // Because the time signal age > normalPollingIntervalMillis, the last refresh attempt
+ // time will be used.
+ long expectedDelayMillis = normalPollingIntervalMillis;
+ long expectedNextRefreshElapsedMillis =
+ lastRefreshAttemptElapsedMillis + expectedDelayMillis;
+ verify(mockCallback).scheduleNextRefresh(expectedNextRefreshElapsedMillis);
+
+ reset(mMockNtpTrustedTime);
+ }
+
+ // Now fail: This should result in the next refresh using a short polling interval.
+ {
+ mFakeElapsedRealtimeClock.incrementMillis(normalPollingIntervalMillis);
+ when(mMockNtpTrustedTime.getCachedTimeResult()).thenReturn(timeResult1);
+ when(mMockNtpTrustedTime.forceRefresh(mDummyNetwork)).thenReturn(false);
+
+ RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
+ // Trigger the engine's logic.
+ engine.refreshAndRescheduleIfRequired(mDummyNetwork, "Test", mockCallback);
+
+ verify(mMockNtpTrustedTime, times(1)).forceRefresh(mDummyNetwork);
+ lastRefreshAttemptElapsedMillis = mFakeElapsedRealtimeClock.getElapsedRealtimeMillis();
+
// Suggestions should not be made if the cached time value is too old.
verify(mockCallback, never()).submitSuggestion(any());
+ // The next wake-up should be rescheduled using the last refresh attempt time (because
+ // the latest time result is too old) and the short polling interval.
+ long expectedDelayMillis = shortPollingIntervalMillis;
+ long expectedNextRefreshElapsedMillis =
+ lastRefreshAttemptElapsedMillis + expectedDelayMillis;
+ verify(mockCallback).scheduleNextRefresh(expectedNextRefreshElapsedMillis);
+
reset(mMockNtpTrustedTime);
}
+
+ // Simulate some other thread successfully refreshing the value held by NtpTrustedTime and
+ // confirm it is handled correctly.
+ {
+ mFakeElapsedRealtimeClock.incrementMillis(shortPollingIntervalMillis / 2);
+ NtpTrustedTime.TimeResult timeResult2 = createNtpTimeResult(
+ mFakeElapsedRealtimeClock.getElapsedRealtimeMillis());
+ when(mMockNtpTrustedTime.getCachedTimeResult()).thenReturn(timeResult2);
+
+ mFakeElapsedRealtimeClock.incrementMillis(shortPollingIntervalMillis / 2);
+
+ RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
+ // Trigger the engine's logic.
+ engine.refreshAndRescheduleIfRequired(mDummyNetwork, "Test", mockCallback);
+
+ verify(mMockNtpTrustedTime, never()).forceRefresh(any());
+
+ NetworkTimeSuggestion expectedSuggestion = createExpectedSuggestion(timeResult2);
+ verify(mockCallback, times(1)).submitSuggestion(expectedSuggestion);
+
+ // The next wake-up should be rescheduled using the normal polling interval and the
+ // latest time result.
+ long expectedDelayMillis = normalPollingIntervalMillis;
+ long expectedNextRefreshElapsedMillis =
+ timeResult2.getElapsedRealtimeMillis() + expectedDelayMillis;
+ verify(mockCallback).scheduleNextRefresh(expectedNextRefreshElapsedMillis);
+ }
}
private static NetworkTimeSuggestion createExpectedSuggestion(
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
index 5a0867f8f584..daa682342836 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
@@ -386,16 +386,16 @@ public class TimeDetectorServiceTest {
.when(mMockContext).enforceCallingPermission(anyString(), any());
assertThrows(SecurityException.class,
- () -> mTimeDetectorService.clearNetworkTime());
+ () -> mTimeDetectorService.clearLatestNetworkTime());
verify(mMockContext).enforceCallingPermission(
eq(android.Manifest.permission.SET_TIME), anyString());
}
@Test
- public void testClearNetworkTime() throws Exception {
+ public void testClearLatestNetworkSuggestion() throws Exception {
doNothing().when(mMockContext).enforceCallingPermission(anyString(), any());
- mTimeDetectorService.clearNetworkTime();
+ mTimeDetectorService.clearLatestNetworkTime();
verify(mMockContext).enforceCallingPermission(
eq(android.Manifest.permission.SET_TIME), anyString());
@@ -403,53 +403,48 @@ public class TimeDetectorServiceTest {
}
@Test
- public void testLatestNetworkTime() {
- NtpTrustedTime.TimeResult latestNetworkTime = new NtpTrustedTime.TimeResult(
- 1234L, 54321L, 999, InetSocketAddress.createUnresolved("test.timeserver", 123));
- when(mMockNtpTrustedTime.getCachedTimeResult())
- .thenReturn(latestNetworkTime);
- UnixEpochTime expected = new UnixEpochTime(
- latestNetworkTime.getElapsedRealtimeMillis(), latestNetworkTime.getTimeMillis());
- assertEquals(expected, mTimeDetectorService.latestNetworkTime());
+ public void testGetLatestNetworkSuggestion() {
+ NetworkTimeSuggestion latestNetworkSuggestion = createNetworkTimeSuggestion();
+ mFakeTimeDetectorStrategySpy.setLatestNetworkTime(latestNetworkSuggestion);
+
+ assertEquals(latestNetworkSuggestion, mTimeDetectorService.getLatestNetworkSuggestion());
}
@Test
- public void testLatestNetworkTime_noTimeAvailable() {
- when(mMockNtpTrustedTime.getCachedTimeResult()).thenReturn(null);
- assertThrows(ParcelableException.class, () -> mTimeDetectorService.latestNetworkTime());
+ public void testGetLatestNetworkSuggestion_noTimeAvailable() {
+ mFakeTimeDetectorStrategySpy.setLatestNetworkTime(null);
+
+ assertNull(mTimeDetectorService.getLatestNetworkSuggestion());
}
@Test
- public void testGetLatestNetworkSuggestion() {
+ public void testLatestNetworkTime() {
if (TimeDetectorNetworkTimeHelper.isInUse()) {
- NetworkTimeSuggestion latestNetworkTime = createNetworkTimeSuggestion();
- mFakeTimeDetectorStrategySpy.setLatestNetworkTime(latestNetworkTime);
+ NetworkTimeSuggestion latestNetworkSuggestion = createNetworkTimeSuggestion();
+ mFakeTimeDetectorStrategySpy.setLatestNetworkTime(latestNetworkSuggestion);
- assertEquals(latestNetworkTime, mTimeDetectorService.getLatestNetworkSuggestion());
+ assertEquals(latestNetworkSuggestion.getUnixEpochTime(),
+ mTimeDetectorService.latestNetworkTime());
} else {
NtpTrustedTime.TimeResult latestNetworkTime = new NtpTrustedTime.TimeResult(
1234L, 54321L, 999, InetSocketAddress.createUnresolved("test.timeserver", 123));
when(mMockNtpTrustedTime.getCachedTimeResult())
.thenReturn(latestNetworkTime);
- UnixEpochTime expectedUnixEpochTime = new UnixEpochTime(
+ UnixEpochTime expected = new UnixEpochTime(
latestNetworkTime.getElapsedRealtimeMillis(),
latestNetworkTime.getTimeMillis());
- NetworkTimeSuggestion expected = new NetworkTimeSuggestion(
- expectedUnixEpochTime, latestNetworkTime.getUncertaintyMillis());
- assertEquals(expected, mTimeDetectorService.getLatestNetworkSuggestion());
+ assertEquals(expected, mTimeDetectorService.latestNetworkTime());
}
}
@Test
- public void testGetLatestNetworkSuggestion_noTimeAvailable() {
+ public void testLatestNetworkTime_noTimeAvailable() {
if (TimeDetectorNetworkTimeHelper.isInUse()) {
mFakeTimeDetectorStrategySpy.setLatestNetworkTime(null);
-
- assertNull(mTimeDetectorService.getLatestNetworkSuggestion());
} else {
when(mMockNtpTrustedTime.getCachedTimeResult()).thenReturn(null);
- assertNull(mTimeDetectorService.getLatestNetworkSuggestion());
}
+ assertThrows(ParcelableException.class, () -> mTimeDetectorService.latestNetworkTime());
}
@Test
diff --git a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
index b921838e0bfc..4c0361d30d67 100644
--- a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
+++ b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
@@ -263,7 +263,7 @@ public class ShortcutManagerTestUtils {
+ instrumentation.getContext().getUserId() + " " + RoleManager.ROLE_HOME + " "
+ packageName + " 0");
waitUntil("Failed to get shortcut access",
- () -> hasShortcutAccess(instrumentation, packageName), 20);
+ () -> hasShortcutAccess(instrumentation, packageName), 60);
}
public static void setDefaultLauncher(Instrumentation instrumentation, Context packageContext) {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
index 6f37e601abce..ce076217f37b 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
@@ -24,6 +24,8 @@ import static android.service.notification.NotificationListenerService.META_DATA
import static com.android.server.notification.ManagedServices.APPROVAL_BY_COMPONENT;
import static com.android.server.notification.ManagedServices.APPROVAL_BY_PACKAGE;
+import static com.google.common.truth.Truth.assertThat;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
@@ -1201,28 +1203,11 @@ public class ManagedServicesTest extends UiServiceTestCase {
mIpm, approvalLevel);
loadXml(service);
- List<String> allowedPackagesForUser0 = new ArrayList<>();
- allowedPackagesForUser0.add("this.is.a.package.name");
- allowedPackagesForUser0.add("another.package");
- allowedPackagesForUser0.add("secondary");
-
- List<String> actual = service.getAllowedPackages(0);
- assertEquals(3, actual.size());
- for (String pkg : allowedPackagesForUser0) {
- assertTrue(actual.contains(pkg));
- }
-
- List<String> allowedPackagesForUser10 = new ArrayList<>();
- allowedPackagesForUser10.add("this.is.another.package");
- allowedPackagesForUser10.add("package");
- allowedPackagesForUser10.add("this.is.another.package");
- allowedPackagesForUser10.add("component");
-
- actual = service.getAllowedPackages(10);
- assertEquals(4, actual.size());
- for (String pkg : allowedPackagesForUser10) {
- assertTrue(actual.contains(pkg));
- }
+ assertThat(service.getAllowedPackages(0)).containsExactly("this.is.a.package.name",
+ "another.package", "secondary");
+ assertThat(service.getAllowedPackages(10)).containsExactly("this.is.another.package",
+ "package", "this.is.another.package", "component");
+ assertThat(service.getAllowedPackages(999)).isEmpty();
}
}
@@ -1263,31 +1248,6 @@ public class ManagedServicesTest extends UiServiceTestCase {
}
@Test
- public void testGetAllowedPackages() throws Exception {
- ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
- mIpm, APPROVAL_BY_COMPONENT);
- loadXml(service);
- service.mApprovalLevel = APPROVAL_BY_PACKAGE;
- loadXml(service);
-
- List<String> allowedPackages = new ArrayList<>();
- allowedPackages.add("this.is.a.package.name");
- allowedPackages.add("another.package");
- allowedPackages.add("secondary");
- allowedPackages.add("this.is.another.package");
- allowedPackages.add("package");
- allowedPackages.add("component");
- allowedPackages.add("bananas!");
- allowedPackages.add("non.user.set.package");
-
- Set<String> actual = service.getAllowedPackages();
- assertEquals(allowedPackages.size(), actual.size());
- for (String pkg : allowedPackages) {
- assertTrue(actual.contains(pkg));
- }
- }
-
- @Test
public void testOnUserRemoved() throws Exception {
for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
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 ef3b007171b2..354420f46c2f 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -29,6 +29,7 @@ import static android.app.Notification.FLAG_FOREGROUND_SERVICE;
import static android.app.Notification.FLAG_NO_CLEAR;
import static android.app.Notification.FLAG_ONGOING_EVENT;
import static android.app.NotificationChannel.USER_LOCKED_ALLOW_BUBBLE;
+import static android.app.NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_NONE;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_SELECTED;
@@ -50,7 +51,6 @@ import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
-
import static android.app.PendingIntent.FLAG_IMMUTABLE;
import static android.app.PendingIntent.FLAG_MUTABLE;
import static android.app.PendingIntent.FLAG_ONE_SHOT;
@@ -177,7 +177,6 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
-import android.permission.PermissionCheckerManager;
import android.permission.PermissionManager;
import android.provider.DeviceConfig;
import android.provider.MediaStore;
@@ -238,6 +237,7 @@ import com.android.server.utils.quota.MultiRateLimiter;
import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.WindowManagerInternal;
+import com.google.android.collect.Lists;
import com.google.common.collect.ImmutableList;
import org.junit.After;
@@ -246,10 +246,13 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.ArgumentMatcher;
+import org.mockito.ArgumentMatchers;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import java.io.BufferedInputStream;
@@ -441,6 +444,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
mContext.addMockSystemService(Context.ALARM_SERVICE, mAlarmManager);
mContext.addMockSystemService(NotificationManager.class, mMockNm);
+ doNothing().when(mContext).sendBroadcastAsUser(any(), any());
doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any());
setDpmAppOppsExemptFromDismissal(false);
@@ -7829,6 +7833,75 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@Test
+ public void onZenModeChanged_sendsBroadcasts() throws Exception {
+ when(mAmi.getCurrentUserId()).thenReturn(100);
+ when(mUmInternal.getProfileIds(eq(100), anyBoolean())).thenReturn(new int[]{100, 101, 102});
+ when(mConditionProviders.getAllowedPackages(anyInt())).then(new Answer<List<String>>() {
+ @Override
+ public List<String> answer(InvocationOnMock invocation) {
+ int userId = invocation.getArgument(0);
+ switch (userId) {
+ case 100:
+ return Lists.newArrayList("a", "b", "c");
+ case 101:
+ return Lists.newArrayList();
+ case 102:
+ return Lists.newArrayList("b");
+ default:
+ throw new IllegalArgumentException(
+ "Why would you ask for packages of userId " + userId + "?");
+ }
+ }
+ });
+
+ mService.getBinderService().setZenMode(Settings.Global.ZEN_MODE_NO_INTERRUPTIONS, null,
+ "testing!");
+ waitForIdle();
+
+ InOrder inOrder = inOrder(mContext);
+ // Verify broadcasts for registered receivers
+ inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(
+ new Intent(ACTION_INTERRUPTION_FILTER_CHANGED).setFlags(
+ Intent.FLAG_RECEIVER_REGISTERED_ONLY)), eq(UserHandle.of(100)), eq(null));
+ inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(
+ new Intent(ACTION_INTERRUPTION_FILTER_CHANGED).setFlags(
+ Intent.FLAG_RECEIVER_REGISTERED_ONLY)), eq(UserHandle.of(101)), eq(null));
+ inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(
+ new Intent(ACTION_INTERRUPTION_FILTER_CHANGED).setFlags(
+ Intent.FLAG_RECEIVER_REGISTERED_ONLY)), eq(UserHandle.of(102)), eq(null));
+
+ // Verify broadcast for packages that manage DND.
+ inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(new Intent(
+ ACTION_INTERRUPTION_FILTER_CHANGED).setPackage("a").setFlags(
+ Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(100)));
+ inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(new Intent(
+ ACTION_INTERRUPTION_FILTER_CHANGED).setPackage("b").setFlags(
+ Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(100)));
+ inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(new Intent(
+ ACTION_INTERRUPTION_FILTER_CHANGED).setPackage("c").setFlags(
+ Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(100)));
+ inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(new Intent(
+ ACTION_INTERRUPTION_FILTER_CHANGED).setPackage("b").setFlags(
+ Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(102)));
+ }
+
+ private static Intent eqIntent(Intent wanted) {
+ return ArgumentMatchers.argThat(
+ new ArgumentMatcher<Intent>() {
+ @Override
+ public boolean matches(Intent argument) {
+ return wanted.filterEquals(argument)
+ && wanted.getFlags() == argument.getFlags();
+ }
+
+ @Override
+ public String toString() {
+ return wanted.toString();
+ }
+ });
+ }
+
+ @Test
public void testAreNotificationsEnabledForPackage() throws Exception {
mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
mUid);
@@ -10254,7 +10327,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
throws Exception {
verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI,
- /* permissionState= */ PermissionCheckerManager.PERMISSION_HARD_DENIED,
+ /* permissionState= */ PermissionManager.PERMISSION_HARD_DENIED,
/* isSticky= */ true);
}
@@ -10263,7 +10336,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
throws Exception {
verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI,
- /* permissionState= */ PermissionCheckerManager.PERMISSION_SOFT_DENIED,
+ /* permissionState= */ PermissionManager.PERMISSION_SOFT_DENIED,
/* isSticky= */ true);
}
@@ -10272,7 +10345,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
throws Exception {
verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI,
- /* permissionState= */ PermissionCheckerManager.PERMISSION_GRANTED,
+ /* permissionState= */ PermissionManager.PERMISSION_GRANTED,
/* isSticky= */ false);
}
@@ -10281,7 +10354,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
throws Exception {
verifyStickyHun(/* flag= */ FSI_FORCE_DEMOTE,
- /* permissionState= */ PermissionCheckerManager.PERMISSION_HARD_DENIED,
+ /* permissionState= */ PermissionManager.PERMISSION_HARD_DENIED,
/* isSticky= */ true);
}
@@ -10290,7 +10363,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
throws Exception {
verifyStickyHun(/* flag= */ FSI_FORCE_DEMOTE,
- /* permissionState= */ PermissionCheckerManager.PERMISSION_SOFT_DENIED,
+ /* permissionState= */ PermissionManager.PERMISSION_SOFT_DENIED,
/* isSticky= */ true);
}
@@ -10299,7 +10372,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
throws Exception {
verifyStickyHun(/* flag= */ FSI_FORCE_DEMOTE,
- /* permissionState= */ PermissionCheckerManager.PERMISSION_GRANTED,
+ /* permissionState= */ PermissionManager.PERMISSION_GRANTED,
/* isSticky= */ true);
}
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 f0f9204c4e4e..79f69ee94a62 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -57,6 +57,7 @@ import static junit.framework.Assert.fail;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -1576,6 +1577,47 @@ public class PreferencesHelperTest extends UiServiceTestCase {
new NotificationChannel("bananas", "bananas", IMPORTANCE_MAX), true, false));
}
+ @Test
+ public void testUpdateChannel_downgradeImportance() {
+ mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+ new NotificationChannel("bananas", "bananas", IMPORTANCE_DEFAULT),
+ true, false);
+
+ assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+ new NotificationChannel("bananas", "bananas", IMPORTANCE_LOW), true, false));
+ }
+
+ @Test
+ public void testUpdateChannel_upgradeImportance_ignored() {
+ mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+ new NotificationChannel("bananas", "bananas", IMPORTANCE_DEFAULT),
+ true, false);
+
+ assertFalse(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+ new NotificationChannel("bananas", "bananas", IMPORTANCE_MAX), true, false));
+ }
+
+ @Test
+ public void testUpdateChannel_badImportance() {
+ mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+ new NotificationChannel("bananas", "bananas", IMPORTANCE_DEFAULT),
+ true, false);
+
+ assertThrows(IllegalArgumentException.class,
+ () -> mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+ new NotificationChannel("bananas", "bananas", IMPORTANCE_NONE - 1), true,
+ false));
+
+ assertThrows(IllegalArgumentException.class,
+ () -> mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+ new NotificationChannel("bananas", "bananas", IMPORTANCE_UNSPECIFIED), true,
+ false));
+
+ assertThrows(IllegalArgumentException.class,
+ () -> mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+ new NotificationChannel("bananas", "bananas", IMPORTANCE_MAX + 1), true,
+ false));
+ }
@Test
public void testUpdate() throws Exception {
@@ -4089,17 +4131,26 @@ public class PreferencesHelperTest extends UiServiceTestCase {
}
@Test
- public void testTooManyGroups() {
+ public void testTooManyGroups_fromTargetApp() {
+ testTooManyGroups(/* fromTargetApp= */ true);
+ }
+
+ @Test
+ public void testTooManyGroups_fromListener() {
+ testTooManyGroups(/* fromTargetApp= */ false);
+ }
+
+ private void testTooManyGroups(boolean fromTargetApp) {
for (int i = 0; i < NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT; i++) {
NotificationChannelGroup group = new NotificationChannelGroup(String.valueOf(i),
String.valueOf(i));
- mHelper.createNotificationChannelGroup(PKG_O, UID_O, group, true);
+ mHelper.createNotificationChannelGroup(PKG_O, UID_O, group, fromTargetApp);
}
try {
NotificationChannelGroup group = new NotificationChannelGroup(
String.valueOf(NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT),
String.valueOf(NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT));
- mHelper.createNotificationChannelGroup(PKG_O, UID_O, group, true);
+ mHelper.createNotificationChannelGroup(PKG_O, UID_O, group, fromTargetApp);
fail("Allowed to create too many notification channel groups");
} catch (IllegalStateException e) {
// great
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
index 2b6db149313e..893f53825bbb 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
@@ -32,9 +32,9 @@ import android.service.notification.Condition;
import android.service.notification.ZenModeConfig;
import android.service.notification.ZenModeConfig.EventInfo;
import android.service.notification.ZenPolicy;
-import android.test.suitebuilder.annotation.SmallTest;
import android.util.Xml;
+import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.modules.utils.TypedXmlPullParser;
@@ -43,11 +43,13 @@ import com.android.server.UiServiceTestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.xmlpull.v1.XmlPullParserException;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.IOException;
@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -189,8 +191,6 @@ public class ZenModeConfigTest extends UiServiceTestCase {
@Test
public void testRuleXml() throws Exception {
- String tag = "tag";
-
ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule();
rule.configurationActivity = new ComponentName("a", "a");
rule.component = new ComponentName("b", "b");
@@ -205,20 +205,11 @@ public class ZenModeConfigTest extends UiServiceTestCase {
rule.snoozing = true;
rule.pkg = "b";
- TypedXmlSerializer out = Xml.newFastSerializer();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
- out.setOutput(new BufferedOutputStream(baos), "utf-8");
- out.startDocument(null, true);
- out.startTag(null, tag);
- ZenModeConfig.writeRuleXml(rule, out);
- out.endTag(null, tag);
- out.endDocument();
+ writeRuleXml(rule, baos);
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ZenModeConfig.ZenRule fromXml = readRuleXml(bais);
- TypedXmlPullParser parser = Xml.newFastPullParser();
- parser.setInput(new BufferedInputStream(
- new ByteArrayInputStream(baos.toByteArray())), null);
- parser.nextTag();
- ZenModeConfig.ZenRule fromXml = ZenModeConfig.readRuleXml(parser);
assertEquals("b", fromXml.pkg);
// always resets on reboot
assertFalse(fromXml.snoozing);
@@ -237,75 +228,41 @@ public class ZenModeConfigTest extends UiServiceTestCase {
@Test
public void testRuleXml_pkg_component() throws Exception {
- String tag = "tag";
-
ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule();
rule.configurationActivity = new ComponentName("a", "a");
rule.component = new ComponentName("b", "b");
- TypedXmlSerializer out = Xml.newFastSerializer();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
- out.setOutput(new BufferedOutputStream(baos), "utf-8");
- out.startDocument(null, true);
- out.startTag(null, tag);
- ZenModeConfig.writeRuleXml(rule, out);
- out.endTag(null, tag);
- out.endDocument();
+ writeRuleXml(rule, baos);
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ZenModeConfig.ZenRule fromXml = readRuleXml(bais);
- TypedXmlPullParser parser = Xml.newFastPullParser();
- parser.setInput(new BufferedInputStream(
- new ByteArrayInputStream(baos.toByteArray())), null);
- parser.nextTag();
- ZenModeConfig.ZenRule fromXml = ZenModeConfig.readRuleXml(parser);
assertEquals("b", fromXml.pkg);
}
@Test
public void testRuleXml_pkg_configActivity() throws Exception {
- String tag = "tag";
-
ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule();
rule.configurationActivity = new ComponentName("a", "a");
- TypedXmlSerializer out = Xml.newFastSerializer();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
- out.setOutput(new BufferedOutputStream(baos), "utf-8");
- out.startDocument(null, true);
- out.startTag(null, tag);
- ZenModeConfig.writeRuleXml(rule, out);
- out.endTag(null, tag);
- out.endDocument();
+ writeRuleXml(rule, baos);
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ZenModeConfig.ZenRule fromXml = readRuleXml(bais);
- TypedXmlPullParser parser = Xml.newFastPullParser();
- parser.setInput(new BufferedInputStream(
- new ByteArrayInputStream(baos.toByteArray())), null);
- parser.nextTag();
- ZenModeConfig.ZenRule fromXml = ZenModeConfig.readRuleXml(parser);
assertNull(fromXml.pkg);
}
@Test
public void testRuleXml_getPkg_nullPkg() throws Exception {
- String tag = "tag";
-
ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule();
rule.enabled = true;
rule.configurationActivity = new ComponentName("a", "a");
- TypedXmlSerializer out = Xml.newFastSerializer();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
- out.setOutput(new BufferedOutputStream(baos), "utf-8");
- out.startDocument(null, true);
- out.startTag(null, tag);
- ZenModeConfig.writeRuleXml(rule, out);
- out.endTag(null, tag);
- out.endDocument();
-
- TypedXmlPullParser parser = Xml.newFastPullParser();
- parser.setInput(new BufferedInputStream(
- new ByteArrayInputStream(baos.toByteArray())), null);
- parser.nextTag();
- ZenModeConfig.ZenRule fromXml = ZenModeConfig.readRuleXml(parser);
+ writeRuleXml(rule, baos);
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ZenModeConfig.ZenRule fromXml = readRuleXml(bais);
assertEquals("a", fromXml.getPkg());
fromXml.condition = new Condition(Uri.EMPTY, "", Condition.STATE_TRUE);
@@ -313,25 +270,26 @@ public class ZenModeConfigTest extends UiServiceTestCase {
}
@Test
- public void testZenPolicyXml_allUnset() throws Exception {
- String tag = "tag";
+ public void testRuleXml_emptyConditionId() throws Exception {
+ ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule();
+ rule.conditionId = Uri.EMPTY;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ writeRuleXml(rule, baos);
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ZenModeConfig.ZenRule fromXml = readRuleXml(bais);
+
+ assertEquals(rule.condition, fromXml.condition);
+ }
+
+ @Test
+ public void testZenPolicyXml_allUnset() throws Exception {
ZenPolicy policy = new ZenPolicy.Builder().build();
- TypedXmlSerializer out = Xml.newFastSerializer();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
- out.setOutput(new BufferedOutputStream(baos), "utf-8");
- out.startDocument(null, true);
- out.startTag(null, tag);
- ZenModeConfig.writeZenPolicyXml(policy, out);
- out.endTag(null, tag);
- out.endDocument();
-
- TypedXmlPullParser parser = Xml.newFastPullParser();
- parser.setInput(new BufferedInputStream(
- new ByteArrayInputStream(baos.toByteArray())), null);
- parser.nextTag();
- ZenPolicy fromXml = ZenModeConfig.readZenPolicyXml(parser);
+ writePolicyXml(policy, baos);
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ZenPolicy fromXml = readPolicyXml(bais);
// nothing was set, so we should have nothing from the parser
assertNull(fromXml);
@@ -339,8 +297,6 @@ public class ZenModeConfigTest extends UiServiceTestCase {
@Test
public void testZenPolicyXml() throws Exception {
- String tag = "tag";
-
ZenPolicy policy = new ZenPolicy.Builder()
.allowCalls(ZenPolicy.PEOPLE_TYPE_CONTACTS)
.allowMessages(ZenPolicy.PEOPLE_TYPE_NONE)
@@ -355,20 +311,10 @@ public class ZenModeConfigTest extends UiServiceTestCase {
.showVisualEffect(ZenPolicy.VISUAL_EFFECT_AMBIENT, true)
.build();
- TypedXmlSerializer out = Xml.newFastSerializer();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
- out.setOutput(new BufferedOutputStream(baos), "utf-8");
- out.startDocument(null, true);
- out.startTag(null, tag);
- ZenModeConfig.writeZenPolicyXml(policy, out);
- out.endTag(null, tag);
- out.endDocument();
-
- TypedXmlPullParser parser = Xml.newFastPullParser();
- parser.setInput(new BufferedInputStream(
- new ByteArrayInputStream(baos.toByteArray())), null);
- parser.nextTag();
- ZenPolicy fromXml = ZenModeConfig.readZenPolicyXml(parser);
+ writePolicyXml(policy, baos);
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ZenPolicy fromXml = readPolicyXml(bais);
assertNotNull(fromXml);
assertEquals(policy.getPriorityCategoryCalls(), fromXml.getPriorityCategoryCalls());
@@ -457,4 +403,45 @@ public class ZenModeConfigTest extends UiServiceTestCase {
config.suppressedVisualEffects = 0;
return config;
}
+
+ private void writeRuleXml(ZenModeConfig.ZenRule rule, ByteArrayOutputStream os)
+ throws IOException {
+ String tag = "tag";
+
+ TypedXmlSerializer out = Xml.newFastSerializer();
+ out.setOutput(new BufferedOutputStream(os), "utf-8");
+ out.startDocument(null, true);
+ out.startTag(null, tag);
+ ZenModeConfig.writeRuleXml(rule, out);
+ out.endTag(null, tag);
+ out.endDocument();
+ }
+
+ private ZenModeConfig.ZenRule readRuleXml(ByteArrayInputStream is)
+ throws XmlPullParserException, IOException {
+ TypedXmlPullParser parser = Xml.newFastPullParser();
+ parser.setInput(new BufferedInputStream(is), null);
+ parser.nextTag();
+ return ZenModeConfig.readRuleXml(parser);
+ }
+
+ private void writePolicyXml(ZenPolicy policy, ByteArrayOutputStream os) throws IOException {
+ String tag = "tag";
+
+ TypedXmlSerializer out = Xml.newFastSerializer();
+ out.setOutput(new BufferedOutputStream(os), "utf-8");
+ out.startDocument(null, true);
+ out.startTag(null, tag);
+ ZenModeConfig.writeZenPolicyXml(policy, out);
+ out.endTag(null, tag);
+ out.endDocument();
+ }
+
+ private ZenPolicy readPolicyXml(ByteArrayInputStream is)
+ throws XmlPullParserException, IOException {
+ TypedXmlPullParser parser = Xml.newFastPullParser();
+ parser.setInput(new BufferedInputStream(is), null);
+ parser.nextTag();
+ return ZenModeConfig.readZenPolicyXml(parser);
+ }
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index 12f124e385f3..6f6e22428eb4 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -38,11 +38,12 @@ import static android.service.notification.Condition.STATE_TRUE;
import static android.util.StatsLog.ANNOTATION_ID_IS_UID;
import static com.android.internal.util.FrameworkStatsLog.DND_MODE_RULE;
-import static com.android.os.AtomsProto.DNDModeProto.CHANNELS_BYPASSING_FIELD_NUMBER;
-import static com.android.os.AtomsProto.DNDModeProto.ENABLED_FIELD_NUMBER;
-import static com.android.os.AtomsProto.DNDModeProto.ID_FIELD_NUMBER;
-import static com.android.os.AtomsProto.DNDModeProto.UID_FIELD_NUMBER;
-import static com.android.os.AtomsProto.DNDModeProto.ZEN_MODE_FIELD_NUMBER;
+import static com.android.os.dnd.DNDModeProto.CHANNELS_BYPASSING_FIELD_NUMBER;
+import static com.android.os.dnd.DNDModeProto.ENABLED_FIELD_NUMBER;
+import static com.android.os.dnd.DNDModeProto.ID_FIELD_NUMBER;
+import static com.android.os.dnd.DNDModeProto.UID_FIELD_NUMBER;
+import static com.android.os.dnd.DNDModeProto.ZEN_MODE_FIELD_NUMBER;
+import static com.android.os.dnd.DNDProtoEnums.ROOT_CONFIG;
import static com.android.server.notification.ZenModeHelper.RULE_LIMIT_PER_PACKAGE;
import static junit.framework.Assert.assertEquals;
@@ -95,7 +96,6 @@ import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings.Global;
import android.service.notification.Condition;
-import android.service.notification.DNDModeProto;
import android.service.notification.ZenModeConfig;
import android.service.notification.ZenModeConfig.ScheduleInfo;
import android.service.notification.ZenPolicy;
@@ -898,7 +898,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
assertEquals(n + 1, events.size());
for (WrappedSysUiStatsEvent.WrappedBuilder builder : mStatsEventBuilderFactory.builders) {
if (builder.getAtomId() == DND_MODE_RULE) {
- if (builder.getInt(ZEN_MODE_FIELD_NUMBER) == DNDModeProto.ROOT_CONFIG) {
+ if (builder.getInt(ZEN_MODE_FIELD_NUMBER) == ROOT_CONFIG) {
assertTrue(builder.getBoolean(ENABLED_FIELD_NUMBER));
assertFalse(builder.getBoolean(CHANNELS_BYPASSING_FIELD_NUMBER));
}
diff --git a/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java b/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java
index 3ecbbfeed254..8f0a5e6f5d0d 100644
--- a/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java
@@ -141,9 +141,9 @@ public class ModifierShortcutTests extends ShortcutKeyTestBase {
*/
@Test
public void testMetaN() throws RemoteException {
- mPhoneWindowManager.overrideExpandNotificationsPanel();
+ mPhoneWindowManager.overrideTogglePanel();
sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_N}, 0);
- mPhoneWindowManager.assertExpandNotification();
+ mPhoneWindowManager.assertTogglePanel();
}
/**
diff --git a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
index 6da9d0c606cf..b6939747a7b6 100644
--- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
+++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
@@ -67,6 +67,7 @@ import android.os.RemoteException;
import android.os.Vibrator;
import android.service.dreams.DreamManagerInternal;
import android.telecom.TelecomManager;
+import android.util.FeatureFlagUtils;
import android.view.Display;
import android.view.KeyEvent;
import android.view.autofill.AutofillManagerInternal;
@@ -76,6 +77,7 @@ import com.android.internal.accessibility.AccessibilityShortcutController;
import com.android.server.GestureLauncherService;
import com.android.server.LocalServices;
import com.android.server.input.InputManagerInternal;
+import com.android.server.inputmethod.InputMethodManagerInternal;
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.vr.VrManagerInternal;
import com.android.server.wm.ActivityTaskManagerInternal;
@@ -114,6 +116,7 @@ class TestPhoneWindowManager {
@Mock private Vibrator mVibrator;
@Mock private PowerManager mPowerManager;
@Mock private WindowManagerPolicy.WindowManagerFuncs mWindowManagerFuncsImpl;
+ @Mock private InputMethodManagerInternal mInputMethodManagerInternal;
@Mock private AudioManagerInternal mAudioManagerInternal;
@Mock private SearchManager mSearchManager;
@@ -184,6 +187,8 @@ class TestPhoneWindowManager {
() -> LocalServices.getService(eq(GestureLauncherService.class)));
doReturn(null).when(() -> LocalServices.getService(eq(VrManagerInternal.class)));
doReturn(null).when(() -> LocalServices.getService(eq(AutofillManagerInternal.class)));
+ LocalServices.removeServiceForTest(InputMethodManagerInternal.class);
+ LocalServices.addService(InputMethodManagerInternal.class, mInputMethodManagerInternal);
doReturn(mAppOpsManager).when(mContext).getSystemService(eq(AppOpsManager.class));
doReturn(mDisplayManager).when(mContext).getSystemService(eq(DisplayManager.class));
@@ -242,6 +247,7 @@ class TestPhoneWindowManager {
void tearDown() {
mHandlerThread.quitSafely();
+ LocalServices.removeServiceForTest(InputMethodManagerInternal.class);
mMockitoSession.finishMocking();
}
@@ -322,12 +328,12 @@ class TestPhoneWindowManager {
doReturn(true).when(mTelecomManager).endCall();
}
- void overrideExpandNotificationsPanel() {
+ void overrideTogglePanel() {
// Can't directly mock on IStatusbarService, use spyOn and override the specific api.
mPhoneWindowManager.getStatusBarService();
spyOn(mPhoneWindowManager.mStatusBarService);
try {
- doNothing().when(mPhoneWindowManager.mStatusBarService).expandNotificationsPanel();
+ doNothing().when(mPhoneWindowManager.mStatusBarService).togglePanel();
} catch (RemoteException e) {
e.printStackTrace();
}
@@ -417,7 +423,13 @@ class TestPhoneWindowManager {
void assertSwitchKeyboardLayout(int direction) {
waitForIdle();
- verify(mWindowManagerFuncsImpl).switchKeyboardLayout(anyInt(), eq(direction));
+ if (FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_UI)) {
+ verify(mInputMethodManagerInternal).switchKeyboardLayout(eq(direction));
+ verify(mWindowManagerFuncsImpl, never()).switchKeyboardLayout(anyInt(), anyInt());
+ } else {
+ verify(mWindowManagerFuncsImpl).switchKeyboardLayout(anyInt(), eq(direction));
+ verify(mInputMethodManagerInternal, never()).switchKeyboardLayout(anyInt());
+ }
}
void assertTakeBugreport() {
@@ -428,9 +440,9 @@ class TestPhoneWindowManager {
Assert.assertTrue(intentCaptor.getValue().getAction() == Intent.ACTION_BUG_REPORT);
}
- void assertExpandNotification() throws RemoteException {
+ void assertTogglePanel() throws RemoteException {
waitForIdle();
- verify(mPhoneWindowManager.mStatusBarService).expandNotificationsPanel();
+ verify(mPhoneWindowManager.mStatusBarService).togglePanel();
}
void assertToggleShortcutsMenu() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index e5fe32a959e9..49f215a83c2b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -2324,6 +2324,32 @@ public class ActivityRecordTests extends WindowTestsBase {
}
@Test
+ public void testActivityServiceConnectionsHolder() {
+ final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
+ final ActivityServiceConnectionsHolder<Object> holder =
+ mAtm.mInternal.getServiceConnectionsHolder(activity.token);
+ assertNotNull(holder);
+ final Object connection = new Object();
+ holder.addConnection(connection);
+ assertTrue(holder.isActivityVisible());
+ final int[] count = new int[1];
+ final Consumer<Object> c = conn -> count[0]++;
+ holder.forEachConnection(c);
+ assertEquals(1, count[0]);
+
+ holder.removeConnection(connection);
+ holder.forEachConnection(c);
+ assertEquals(1, count[0]);
+
+ activity.setVisibleRequested(false);
+ activity.setState(STOPPED, "test");
+ assertFalse(holder.isActivityVisible());
+
+ activity.removeImmediately();
+ assertNull(mAtm.mInternal.getServiceConnectionsHolder(activity.token));
+ }
+
+ @Test
public void testTransferLaunchCookieWhenFinishing() {
final ActivityRecord activity1 = createActivityWithTask();
final Binder launchCookie = new Binder();
@@ -2871,7 +2897,7 @@ public class ActivityRecordTests extends WindowTestsBase {
// Make the top one invisible, and try transferring the starting window from the top to the
// bottom one.
- activityTop.setVisibility(false, false);
+ activityTop.setVisibility(false);
activityBottom.transferStartingWindowFromHiddenAboveTokenIfNeeded();
waitUntilHandlersIdle();
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index 28e493e062f7..e3cb5fb205c6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -145,7 +145,8 @@ import java.util.Set;
public class ActivityStarterTests extends WindowTestsBase {
private static final String ENABLE_DEFAULT_RESCIND_BAL_PRIVILEGES_FROM_PENDING_INTENT_SENDER =
- "enable_default_rescind_bal_privileges_from_pending_intent_sender";
+ "DefaultRescindBalPrivilegesFromPendingIntentSender__"
+ + "enable_default_rescind_bal_privileges_from_pending_intent_sender";
private static final int PRECONDITION_NO_CALLER_APP = 1;
private static final int PRECONDITION_NO_INTENT_COMPONENT = 1 << 1;
private static final int PRECONDITION_NO_ACTIVITY_INFO = 1 << 2;
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
index 3dcae91f5c89..0044e2e54b5a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -66,6 +66,7 @@ import android.platform.test.annotations.Presubmit;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.IDisplayWindowListener;
+import android.view.WindowManager;
import androidx.test.filters.MediumTest;
@@ -456,13 +457,15 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase {
mAtm.mSupportsNonResizableMultiWindow = 0;
// Supports on large screen.
- tda.getConfiguration().smallestScreenWidthDp = mAtm.mLargeScreenSmallestScreenWidthDp;
+ tda.getConfiguration().smallestScreenWidthDp =
+ WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP;
assertTrue(activity.supportsMultiWindow());
assertTrue(task.supportsMultiWindow());
// Not supports on small screen.
- tda.getConfiguration().smallestScreenWidthDp = mAtm.mLargeScreenSmallestScreenWidthDp - 1;
+ tda.getConfiguration().smallestScreenWidthDp =
+ WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP - 1;
assertFalse(activity.supportsMultiWindow());
assertFalse(task.supportsMultiWindow());
@@ -475,8 +478,10 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase {
new ActivityInfo.WindowLayout(0, 0, 0, 0, 0,
// This is larger than the min dimensions device support in multi window,
// the activity will not be supported in multi window if the device respects
- /* minWidth= */(int) (mAtm.mLargeScreenSmallestScreenWidthDp * density),
- /* minHeight= */(int) (mAtm.mLargeScreenSmallestScreenWidthDp * density));
+ /* minWidth= */
+ (int) (WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP * density),
+ /* minHeight= */
+ (int) (WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP * density));
final ActivityRecord activity = new ActivityBuilder(mAtm)
.setCreateTask(true)
.setWindowLayout(windowLayout)
@@ -501,13 +506,15 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase {
mAtm.mRespectsActivityMinWidthHeightMultiWindow = 0;
// Ignore on large screen.
- tda.getConfiguration().smallestScreenWidthDp = mAtm.mLargeScreenSmallestScreenWidthDp;
+ tda.getConfiguration().smallestScreenWidthDp =
+ WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP;
assertTrue(activity.supportsMultiWindow());
assertTrue(task.supportsMultiWindow());
// Check on small screen.
- tda.getConfiguration().smallestScreenWidthDp = mAtm.mLargeScreenSmallestScreenWidthDp - 1;
+ tda.getConfiguration().smallestScreenWidthDp =
+ WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP - 1;
assertFalse(activity.supportsMultiWindow());
assertFalse(task.supportsMultiWindow());
@@ -518,7 +525,7 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase {
// This is smaller than the min dimensions device support in multi window,
// the activity will be supported in multi window
final float density = mContext.getResources().getDisplayMetrics().density;
- final int supportedWidth = (int) (mAtm.mLargeScreenSmallestScreenWidthDp
+ final int supportedWidth = (int) (WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP
* mAtm.mMinPercentageMultiWindowSupportWidth * density);
final ActivityInfo.WindowLayout windowLayout =
new ActivityInfo.WindowLayout(0, 0, 0, 0, 0,
@@ -531,15 +538,17 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase {
.build();
final Task task = activity.getTask();
final TaskDisplayArea tda = task.getDisplayArea();
- tda.getConfiguration().smallestScreenWidthDp = mAtm.mLargeScreenSmallestScreenWidthDp - 1;
- tda.getConfiguration().screenWidthDp = mAtm.mLargeScreenSmallestScreenWidthDp - 1;
+ tda.getConfiguration().smallestScreenWidthDp =
+ WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP - 1;
+ tda.getConfiguration().screenWidthDp =
+ WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP - 1;
tda.getConfiguration().orientation = ORIENTATION_LANDSCAPE;
assertFalse(activity.supportsMultiWindow());
assertFalse(task.supportsMultiWindow());
tda.getConfiguration().screenWidthDp = (int) Math.ceil(
- mAtm.mLargeScreenSmallestScreenWidthDp
+ WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP
/ mAtm.mMinPercentageMultiWindowSupportWidth);
assertTrue(activity.supportsMultiWindow());
@@ -551,7 +560,7 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase {
// This is smaller than the min dimensions device support in multi window,
// the activity will be supported in multi window
final float density = mContext.getResources().getDisplayMetrics().density;
- final int supportedHeight = (int) (mAtm.mLargeScreenSmallestScreenWidthDp
+ final int supportedHeight = (int) (WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP
* mAtm.mMinPercentageMultiWindowSupportHeight * density);
final ActivityInfo.WindowLayout windowLayout =
new ActivityInfo.WindowLayout(0, 0, 0, 0, 0,
@@ -564,15 +573,17 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase {
.build();
final Task task = activity.getTask();
final TaskDisplayArea tda = task.getDisplayArea();
- tda.getConfiguration().smallestScreenWidthDp = mAtm.mLargeScreenSmallestScreenWidthDp - 1;
- tda.getConfiguration().screenHeightDp = mAtm.mLargeScreenSmallestScreenWidthDp - 1;
+ tda.getConfiguration().smallestScreenWidthDp =
+ WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP - 1;
+ tda.getConfiguration().screenHeightDp =
+ WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP - 1;
tda.getConfiguration().orientation = ORIENTATION_PORTRAIT;
assertFalse(activity.supportsMultiWindow());
assertFalse(task.supportsMultiWindow());
tda.getConfiguration().screenHeightDp = (int) Math.ceil(
- mAtm.mLargeScreenSmallestScreenWidthDp
+ WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP
/ mAtm.mMinPercentageMultiWindowSupportHeight);
assertTrue(activity.supportsMultiWindow());
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
index 4d71b30d71e2..6d1312458ce2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
@@ -165,7 +165,7 @@ public class AppChangeTransitionTests extends WindowTestsBase {
assertTrue(mTask.isInChangeTransition());
// Changing visibility should cancel the change transition and become closing
- mActivity.setVisibility(false, false);
+ mActivity.setVisibility(false);
assertEquals(0, mDisplayContent.mChangingContainers.size());
assertFalse(mTask.isInChangeTransition());
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index 6b814e678419..59cc4f5b0948 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -295,8 +295,8 @@ public class AppTransitionTests extends WindowTestsBase {
dc2.prepareAppTransition(TRANSIT_CLOSE);
// One activity window is visible for resuming & the other activity window is invisible
// for finishing in different display.
- activity1.setVisibility(true, false);
- activity2.setVisibility(false, false);
+ activity1.setVisibility(true);
+ activity2.setVisibility(false);
// Make sure each display is in animating stage.
assertTrue(dc1.mOpeningApps.size() > 0);
@@ -365,7 +365,7 @@ public class AppTransitionTests extends WindowTestsBase {
dc.prepareAppTransition(TRANSIT_CLOSE);
assertTrue(dc.mAppTransition.containsTransitRequest(TRANSIT_CLOSE));
dc.mAppTransition.overridePendingAppTransitionRemote(adapter);
- exitingActivity.setVisibility(false, false);
+ exitingActivity.setVisibility(false);
assertTrue(dc.mClosingApps.size() > 0);
// Make sure window is in animating stage before freeze, and cancel after freeze.
diff --git a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
index ff5ede7a316a..56461f007351 100644
--- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
@@ -17,8 +17,11 @@
package com.android.server.wm;
import static android.app.ActivityOptions.ANIM_SCENE_TRANSITION;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_EXT_ENABLE_ON_BACK_INVOKED_CALLBACK;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.window.BackNavigationInfo.typeToString;
@@ -42,8 +45,10 @@ import android.app.ActivityOptions;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.os.Bundle;
+import android.os.RemoteCallback;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
+import android.util.ArraySet;
import android.view.WindowManager;
import android.window.BackAnimationAdapter;
import android.window.BackMotionEvent;
@@ -320,6 +325,64 @@ public class BackNavigationControllerTests extends WindowTestsBase {
assertThat(backNavigationInfo).isNull();
}
+ @Test
+ public void testTransitionHappensCancelNavigation() {
+ // Create a floating task and a fullscreen task, then navigating on fullscreen task.
+ // The navigation should not been cancelled when transition happens on floating task, and
+ // only be cancelled when transition happens on the navigating task.
+ final Task floatingTask = createTask(mDisplayContent, WINDOWING_MODE_MULTI_WINDOW,
+ ACTIVITY_TYPE_STANDARD);
+ final ActivityRecord baseFloatingActivity = createActivityRecord(floatingTask);
+
+ final Task fullscreenTask = createTopTaskWithActivity();
+ withSystemCallback(fullscreenTask);
+ final ActivityRecord baseFullscreenActivity = fullscreenTask.getTopMostActivity();
+
+ final CountDownLatch navigationObserver = new CountDownLatch(1);
+ startBackNavigation(navigationObserver);
+
+ final ArraySet<ActivityRecord> opening = new ArraySet<>();
+ final ArraySet<ActivityRecord> closing = new ArraySet<>();
+ final ActivityRecord secondFloatingActivity = createActivityRecord(floatingTask);
+ opening.add(secondFloatingActivity);
+ closing.add(baseFloatingActivity);
+ mBackNavigationController.removeIfContainsBackAnimationTargets(opening, closing);
+ assertEquals("Transition happen on an irrelevant task, callback should not been called",
+ 1, navigationObserver.getCount());
+
+ // Create a new activity above navigation target, the transition should cancel navigation.
+ final ActivityRecord topFullscreenActivity = createActivityRecord(fullscreenTask);
+ opening.clear();
+ closing.clear();
+ opening.add(topFullscreenActivity);
+ closing.add(baseFullscreenActivity);
+ mBackNavigationController.removeIfContainsBackAnimationTargets(opening, closing);
+ assertEquals("Transition happen on navigation task, callback should have been called",
+ 0, navigationObserver.getCount());
+ }
+
+ @Test
+ public void testWindowFocusChangeCancelNavigation() {
+ Task task = createTopTaskWithActivity();
+ withSystemCallback(task);
+ WindowState focusWindow = task.getTopVisibleAppMainWindow();
+ final CountDownLatch navigationObserver = new CountDownLatch(1);
+ startBackNavigation(navigationObserver);
+
+ mBackNavigationController.onFocusChanged(null);
+ assertEquals("change focus to null, callback should not have been called",
+ 1, navigationObserver.getCount());
+ mBackNavigationController.onFocusChanged(focusWindow);
+ assertEquals("change focus back, callback should not have been called",
+ 1, navigationObserver.getCount());
+
+ WindowState newWindow = createWindow(null, TYPE_APPLICATION_OVERLAY, "overlayWindow");
+ addToWindowMap(newWindow, true);
+ mBackNavigationController.onFocusChanged(newWindow);
+ assertEquals("Focus change, callback should have been called",
+ 0, navigationObserver.getCount());
+ }
+
private IOnBackInvokedCallback withSystemCallback(Task task) {
IOnBackInvokedCallback callback = createOnBackInvokedCallback();
task.getTopMostActivity().getTopChild().setOnBackInvokedCallbackInfo(
@@ -336,7 +399,14 @@ public class BackNavigationControllerTests extends WindowTestsBase {
@Nullable
private BackNavigationInfo startBackNavigation() {
- return mBackNavigationController.startBackNavigation(null, mBackAnimationAdapter);
+ return mBackNavigationController.startBackNavigation(
+ createNavigationObserver(null), mBackAnimationAdapter);
+ }
+
+ @Nullable
+ private BackNavigationInfo startBackNavigation(CountDownLatch navigationObserverLatch) {
+ return mBackNavigationController.startBackNavigation(
+ createNavigationObserver(navigationObserverLatch), mBackAnimationAdapter);
}
@NonNull
@@ -371,6 +441,14 @@ public class BackNavigationControllerTests extends WindowTestsBase {
};
}
+ private RemoteCallback createNavigationObserver(CountDownLatch latch) {
+ return new RemoteCallback(result -> {
+ if (latch != null) {
+ latch.countDown();
+ }
+ });
+ }
+
private Task initHomeActivity() {
final Task task = mDisplayContent.getDefaultTaskDisplayArea().getRootHomeTask();
task.forAllLeafTasks((t) -> {
diff --git a/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java b/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java
index 8cc362c1820c..17f6d51a74f3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java
@@ -35,6 +35,8 @@ import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.never;
+import android.app.WindowConfiguration;
+import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Rect;
@@ -45,6 +47,7 @@ import android.platform.test.annotations.Presubmit;
import android.provider.DeviceConfig;
import android.util.DisplayMetrics;
import android.view.ContentRecordingSession;
+import android.view.Gravity;
import android.view.Surface;
import android.view.SurfaceControl;
@@ -258,8 +261,17 @@ public class ContentRecorderTests extends WindowTestsBase {
@Test
public void testOnTaskBoundsConfigurationChanged_notifiesCallback() {
+ mTask.getRootTask().setWindowingMode(WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW);
+
final int recordedWidth = 333;
final int recordedHeight = 999;
+
+ final ActivityInfo info = new ActivityInfo();
+ info.windowLayout = new ActivityInfo.WindowLayout(-1 /* width */,
+ -1 /* widthFraction */, -1 /* height */, -1 /* heightFraction */,
+ Gravity.NO_GRAVITY, recordedWidth, recordedHeight);
+ mTask.setMinDimensions(info);
+
// WHEN a recording is ongoing.
mContentRecorder.setContentRecordingSession(mTaskSession);
mContentRecorder.updateRecording();
@@ -267,7 +279,6 @@ public class ContentRecorderTests extends WindowTestsBase {
// WHEN a configuration change arrives, and the recorded content is a different size.
mTask.setBounds(new Rect(0, 0, recordedWidth, recordedHeight));
- mContentRecorder.onConfigurationChanged(mDefaultDisplay.getLastOrientation());
assertThat(mContentRecorder.isCurrentlyRecording()).isTrue();
// THEN content in the captured DisplayArea is scaled to fit the surface size.
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 aaeae239024d..3379bebe6698 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -1620,7 +1620,6 @@ public class DisplayContentTests extends WindowTestsBase {
// If the rotated activity requests to show IME, the IME window should use the
// transformation from activity to lay out in the same orientation.
- mDisplayContent.setImeLayeringTarget(mAppWindow);
LocalServices.getService(WindowManagerInternal.class).onToggleImeRequested(true /* show */,
app.token, app.token, mDisplayContent.mDisplayId);
assertTrue(asyncRotationController.isTargetToken(mImeWindow.mToken));
diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
index 6f633d766af7..06b6ed83d28c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
@@ -68,6 +68,7 @@ import android.view.InsetsSource;
import android.view.InsetsState;
import android.view.RoundedCorner;
import android.view.RoundedCorners;
+import android.view.WindowInsets;
import android.view.WindowManager;
import androidx.test.filters.SmallTest;
@@ -353,7 +354,7 @@ public class LetterboxUiControllerTest extends WindowTestsBase {
@Test
public void testGetCropBoundsIfNeeded_noCrop() {
final InsetsSource taskbar = new InsetsSource(/*id=*/ 0,
- InsetsState.ITYPE_EXTRA_NAVIGATION_BAR);
+ WindowInsets.Type.navigationBars());
final WindowState mainWindow = mockForGetCropBoundsAndRoundedCorners(taskbar);
// Do not apply crop if taskbar is collapsed
@@ -374,7 +375,8 @@ public class LetterboxUiControllerTest extends WindowTestsBase {
@Test
public void testGetCropBoundsIfNeeded_appliesCrop() {
final InsetsSource taskbar = new InsetsSource(/*id=*/ 0,
- InsetsState.ITYPE_EXTRA_NAVIGATION_BAR);
+ WindowInsets.Type.navigationBars());
+ taskbar.setInsetsRoundedCornerFrame(true);
final WindowState mainWindow = mockForGetCropBoundsAndRoundedCorners(taskbar);
// Apply crop if taskbar is expanded
@@ -396,7 +398,8 @@ public class LetterboxUiControllerTest extends WindowTestsBase {
@Test
public void testGetCropBoundsIfNeeded_appliesCropWithSizeCompatScaling() {
final InsetsSource taskbar = new InsetsSource(/*id=*/ 0,
- InsetsState.ITYPE_EXTRA_NAVIGATION_BAR);
+ WindowInsets.Type.navigationBars());
+ taskbar.setInsetsRoundedCornerFrame(true);
final WindowState mainWindow = mockForGetCropBoundsAndRoundedCorners(taskbar);
final float scaling = 2.0f;
@@ -440,7 +443,7 @@ public class LetterboxUiControllerTest extends WindowTestsBase {
configurationRadius * 2 /*2 is to test selection of the min radius*/,
/*centerX=*/ 1, /*centerY=*/ 1)
);
- doReturn(roundedCorners).when(insets).getRoundedCorners();
+ insets.setRoundedCorners(roundedCorners);
mLetterboxConfiguration.setLetterboxActivityCornersRadius(-1);
assertEquals(expectedRadius, mController.getRoundedCornersRadius(mainWindow));
@@ -479,7 +482,7 @@ public class LetterboxUiControllerTest extends WindowTestsBase {
private WindowState mockForGetCropBoundsAndRoundedCorners(@Nullable InsetsSource taskbar) {
final WindowState mainWindow = mock(WindowState.class);
- final InsetsState insets = mock(InsetsState.class);
+ final InsetsState insets = new InsetsState();
final Resources resources = mWm.mContext.getResources();
final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams();
@@ -489,7 +492,7 @@ public class LetterboxUiControllerTest extends WindowTestsBase {
if (taskbar != null) {
taskbar.setVisible(true);
- doReturn(taskbar).when(insets).peekSource(taskbar.getType());
+ insets.addSource(taskbar);
}
doReturn(mLetterboxedPortraitTaskBounds).when(mActivity).getBounds();
doReturn(true).when(mActivity).isVisible();
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 c9f758ce1f55..abbd3977d1a8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -28,7 +28,6 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.provider.DeviceConfig.NAMESPACE_CONSTRAIN_DISPLAY_APIS;
-import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.InsetsState.ITYPE_TOP_MANDATORY_GESTURES;
import static android.view.InsetsState.ITYPE_TOP_TAPPABLE_ELEMENT;
@@ -118,6 +117,8 @@ import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import java.util.List;
+import java.util.function.Consumer;
+import java.util.function.Function;
/**
* Tests for Size Compatibility mode.
@@ -173,6 +174,156 @@ public class SizeCompatTests extends WindowTestsBase {
}
@Test
+ public void testHorizontalReachabilityEnabledForTranslucentActivities() {
+ setUpDisplaySizeWithApp(2500, 1000);
+ mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+ final LetterboxConfiguration config = mWm.mLetterboxConfiguration;
+ config.setTranslucentLetterboxingOverrideEnabled(true);
+ config.setLetterboxHorizontalPositionMultiplier(0.5f);
+ config.setIsHorizontalReachabilityEnabled(true);
+
+ // Opaque activity
+ prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
+ addWindowToActivity(mActivity);
+ mActivity.mRootWindowContainer.performSurfacePlacement();
+
+ // Translucent Activity
+ final ActivityRecord translucentActivity = new ActivityBuilder(mAtm)
+ .setLaunchedFromUid(mActivity.getUid())
+ .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT)
+ .build();
+ doReturn(false).when(translucentActivity).fillsParent();
+ mTask.addChild(translucentActivity);
+
+ spyOn(translucentActivity.mLetterboxUiController);
+ doReturn(true).when(translucentActivity.mLetterboxUiController)
+ .shouldShowLetterboxUi(any());
+
+ addWindowToActivity(translucentActivity);
+ translucentActivity.mRootWindowContainer.performSurfacePlacement();
+
+ final Function<ActivityRecord, Rect> innerBoundsOf =
+ (ActivityRecord a) -> {
+ final Rect bounds = new Rect();
+ a.mLetterboxUiController.getLetterboxInnerBounds(bounds);
+ return bounds;
+ };
+ final Runnable checkLetterboxPositions = () -> assertEquals(innerBoundsOf.apply(mActivity),
+ innerBoundsOf.apply(translucentActivity));
+ final Runnable checkIsLeft = () -> assertThat(
+ innerBoundsOf.apply(translucentActivity).left).isEqualTo(0);
+ final Runnable checkIsRight = () -> assertThat(
+ innerBoundsOf.apply(translucentActivity).right).isEqualTo(2500);
+ final Runnable checkIsCentered = () -> assertThat(
+ innerBoundsOf.apply(translucentActivity).left > 0
+ && innerBoundsOf.apply(translucentActivity).right < 2500).isTrue();
+
+ final Consumer<Integer> doubleClick =
+ (Integer x) -> {
+ mActivity.mLetterboxUiController.handleHorizontalDoubleTap(x);
+ mActivity.mRootWindowContainer.performSurfacePlacement();
+ };
+
+ // Initial state
+ checkIsCentered.run();
+
+ // Double-click left
+ doubleClick.accept(/* x */ 10);
+ checkLetterboxPositions.run();
+ checkIsLeft.run();
+
+ // Double-click right
+ doubleClick.accept(/* x */ 1990);
+ checkLetterboxPositions.run();
+ checkIsCentered.run();
+
+ // Double-click right
+ doubleClick.accept(/* x */ 1990);
+ checkLetterboxPositions.run();
+ checkIsRight.run();
+
+ // Double-click left
+ doubleClick.accept(/* x */ 10);
+ checkLetterboxPositions.run();
+ checkIsCentered.run();
+ }
+
+ @Test
+ public void testVerticalReachabilityEnabledForTranslucentActivities() {
+ setUpDisplaySizeWithApp(1000, 2500);
+ mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+ final LetterboxConfiguration config = mWm.mLetterboxConfiguration;
+ config.setTranslucentLetterboxingOverrideEnabled(true);
+ config.setLetterboxVerticalPositionMultiplier(0.5f);
+ config.setIsVerticalReachabilityEnabled(true);
+
+ // Opaque activity
+ prepareUnresizable(mActivity, SCREEN_ORIENTATION_LANDSCAPE);
+ addWindowToActivity(mActivity);
+ mActivity.mRootWindowContainer.performSurfacePlacement();
+
+ // Translucent Activity
+ final ActivityRecord translucentActivity = new ActivityBuilder(mAtm)
+ .setLaunchedFromUid(mActivity.getUid())
+ .setScreenOrientation(SCREEN_ORIENTATION_LANDSCAPE)
+ .build();
+ doReturn(false).when(translucentActivity).fillsParent();
+ mTask.addChild(translucentActivity);
+
+ spyOn(translucentActivity.mLetterboxUiController);
+ doReturn(true).when(translucentActivity.mLetterboxUiController)
+ .shouldShowLetterboxUi(any());
+
+ addWindowToActivity(translucentActivity);
+ translucentActivity.mRootWindowContainer.performSurfacePlacement();
+
+ final Function<ActivityRecord, Rect> innerBoundsOf =
+ (ActivityRecord a) -> {
+ final Rect bounds = new Rect();
+ a.mLetterboxUiController.getLetterboxInnerBounds(bounds);
+ return bounds;
+ };
+ final Runnable checkLetterboxPositions = () -> assertEquals(innerBoundsOf.apply(mActivity),
+ innerBoundsOf.apply(translucentActivity));
+ final Runnable checkIsTop = () -> assertThat(
+ innerBoundsOf.apply(translucentActivity).top).isEqualTo(0);
+ final Runnable checkIsBottom = () -> assertThat(
+ innerBoundsOf.apply(translucentActivity).bottom).isEqualTo(2500);
+ final Runnable checkIsCentered = () -> assertThat(
+ innerBoundsOf.apply(translucentActivity).top > 0
+ && innerBoundsOf.apply(translucentActivity).bottom < 2500).isTrue();
+
+ final Consumer<Integer> doubleClick =
+ (Integer y) -> {
+ mActivity.mLetterboxUiController.handleVerticalDoubleTap(y);
+ mActivity.mRootWindowContainer.performSurfacePlacement();
+ };
+
+ // Initial state
+ checkIsCentered.run();
+
+ // Double-click top
+ doubleClick.accept(/* y */ 10);
+ checkLetterboxPositions.run();
+ checkIsTop.run();
+
+ // Double-click bottom
+ doubleClick.accept(/* y */ 1990);
+ checkLetterboxPositions.run();
+ checkIsCentered.run();
+
+ // Double-click bottom
+ doubleClick.accept(/* y */ 1990);
+ checkLetterboxPositions.run();
+ checkIsBottom.run();
+
+ // Double-click top
+ doubleClick.accept(/* y */ 10);
+ checkLetterboxPositions.run();
+ checkIsCentered.run();
+ }
+
+ @Test
public void testApplyStrategyToTranslucentActivities() {
mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true);
setUpDisplaySizeWithApp(2000, 1000);
@@ -279,7 +430,8 @@ public class SizeCompatTests extends WindowTestsBase {
public void testTranslucentActivitiesWhenUnfolding() {
mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true);
setUpDisplaySizeWithApp(2800, 1400);
- mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+ mActivity.mDisplayContent.setIgnoreOrientationRequest(
+ true /* ignoreOrientationRequest */);
mActivity.mWmService.mLetterboxConfiguration.setLetterboxHorizontalPositionMultiplier(
1.0f /*letterboxVerticalPositionMultiplier*/);
prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
@@ -290,18 +442,23 @@ public class SizeCompatTests extends WindowTestsBase {
.build();
doReturn(false).when(translucentActivity).fillsParent();
mTask.addChild(translucentActivity);
+ assertEquals(translucentActivity.getBounds(), mActivity.getBounds());
mTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
spyOn(mActivity);
// Halffold
- setFoldablePosture(translucentActivity, true /* isHalfFolded */, false /* isTabletop */);
+ setFoldablePosture(translucentActivity, true /* isHalfFolded */,
+ false /* isTabletop */);
verify(mActivity).recomputeConfiguration();
+ assertEquals(translucentActivity.getBounds(), mActivity.getBounds());
clearInvocations(mActivity);
// Unfold
- setFoldablePosture(translucentActivity, false /* isHalfFolded */, false /* isTabletop */);
+ setFoldablePosture(translucentActivity, false /* isHalfFolded */,
+ false /* isTabletop */);
verify(mActivity).recomputeConfiguration();
+ assertEquals(translucentActivity.getBounds(), mActivity.getBounds());
}
@Test
@@ -817,7 +974,7 @@ public class SizeCompatTests extends WindowTestsBase {
.setResizeMode(ActivityInfo.RESIZE_MODE_UNRESIZEABLE)
.setScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
.build();
- assertFalse(activity.shouldCreateCompatDisplayInsets());
+ assertTrue(activity.shouldCreateCompatDisplayInsets());
// The non-resizable activity should not be size compat because it is on a resizable task
// in multi-window mode.
@@ -850,7 +1007,7 @@ public class SizeCompatTests extends WindowTestsBase {
}
@Test
- public void testShouldNotCreateCompatDisplayInsetsWhenRootActivityIsResizeable() {
+ public void testShouldCreateCompatDisplayInsetsWhenUnresizeableAndSupportsSizeChangesFalse() {
setUpDisplaySizeWithApp(1000, 2500);
// Make the task root resizable.
@@ -859,7 +1016,7 @@ public class SizeCompatTests extends WindowTestsBase {
// Create an activity on the same task.
final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */false,
RESIZE_MODE_UNRESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
- assertFalse(activity.shouldCreateCompatDisplayInsets());
+ assertTrue(activity.shouldCreateCompatDisplayInsets());
}
@Test
@@ -2987,8 +3144,9 @@ public class SizeCompatTests extends WindowTestsBase {
organizer.mPrimary.setBounds(0, screenHeight / 2, screenWidth, screenHeight);
organizer.putTaskToPrimary(mTask, true);
- final InsetsSource navSource =
- new InsetsSource(ITYPE_EXTRA_NAVIGATION_BAR, navigationBars());
+ final InsetsSource navSource = new InsetsSource(
+ InsetsSource.createId(null, 0, navigationBars()), navigationBars());
+ navSource.setInsetsRoundedCornerFrame(true);
navSource.setFrame(new Rect(0, screenHeight - taskbarHeight, screenWidth, screenHeight));
mActivity.mWmService.mLetterboxConfiguration.setLetterboxActivityCornersRadius(15);
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index f4a266c11679..013c6d50d4e7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -545,7 +545,6 @@ public class SystemServicesTestRule implements TestRule {
mDevEnableNonResizableMultiWindow = false;
mMinPercentageMultiWindowSupportHeight = 0.3f;
mMinPercentageMultiWindowSupportWidth = 0.5f;
- mLargeScreenSmallestScreenWidthDp = 600;
mSupportsNonResizableMultiWindow = 0;
mRespectsActivityMinWidthHeightMultiWindow = 0;
mForceResizableActivities = false;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
index df3af7d2f4fa..49d8da1b2880 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
@@ -351,8 +351,8 @@ public class TaskFragmentTest extends WindowTestsBase {
final TaskFragment taskFragment1 = createTaskFragmentWithEmbeddedActivity(task, mOrganizer);
final ActivityRecord activity0 = taskFragment0.getTopMostActivity();
final ActivityRecord activity1 = taskFragment1.getTopMostActivity();
- activity0.setVisibility(true /* visible */, false /* deferHidingClient */);
- activity1.setVisibility(true /* visible */, false /* deferHidingClient */);
+ activity0.setVisibility(true);
+ activity1.setVisibility(true);
spyOn(mAtm.mTaskFragmentOrganizerController);
// Move activity to pinned.
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
index 9cd80a34b714..5208e5a2dc2f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -535,6 +535,34 @@ public class TaskTests extends WindowTestsBase {
assertEquals(reqBounds.height(), task.getBounds().height());
}
+ /** Tests that the task bounds adjust properly to changes between FULLSCREEN and FREEFORM */
+ @Test
+ public void testBoundsOnModeChangeFreeformToFullscreen() {
+ DisplayContent display = mAtm.mRootWindowContainer.getDefaultDisplay();
+ Task rootTask = new TaskBuilder(mSupervisor).setDisplay(display).setCreateActivity(true)
+ .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
+ Task task = rootTask.getBottomMostTask();
+ task.getRootActivity().setOrientation(SCREEN_ORIENTATION_UNSPECIFIED);
+ DisplayInfo info = new DisplayInfo();
+ display.mDisplay.getDisplayInfo(info);
+ final Rect fullScreenBounds = new Rect(0, 0, info.logicalWidth, info.logicalHeight);
+ final Rect freeformBounds = new Rect(fullScreenBounds);
+ freeformBounds.inset((int) (freeformBounds.width() * 0.2),
+ (int) (freeformBounds.height() * 0.2));
+ task.setBounds(freeformBounds);
+
+ assertEquals(freeformBounds, task.getBounds());
+
+ // FULLSCREEN inherits bounds
+ rootTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+ assertEquals(fullScreenBounds, task.getBounds());
+ assertEquals(freeformBounds, task.mLastNonFullscreenBounds);
+
+ // FREEFORM restores bounds
+ rootTask.setWindowingMode(WINDOWING_MODE_FREEFORM);
+ assertEquals(freeformBounds, task.getBounds());
+ }
+
/**
* Tests that a task with forced orientation has orientation-consistent bounds within the
* parent.
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
index fec079b7b15b..7e4a9de950e5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
@@ -30,6 +30,9 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
@@ -39,6 +42,7 @@ import android.graphics.Insets;
import android.graphics.Rect;
import android.hardware.display.DisplayManagerGlobal;
import android.util.DisplayMetrics;
+import android.util.TypedValue;
import android.view.Display;
import android.view.DisplayCutout;
import android.view.DisplayInfo;
@@ -47,6 +51,8 @@ import com.android.server.wm.DisplayWindowSettings.SettingsProvider.SettingsEntr
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
class TestDisplayContent extends DisplayContent {
@@ -197,10 +203,21 @@ class TestDisplayContent extends DisplayContent {
MockitoAnnotations.initMocks(this);
doReturn(mMockContext).when(mService.mContext).createConfigurationContext(any());
doReturn(mResources).when(mMockContext).getResources();
- doReturn(valueDp * mDisplayMetrics.density)
- .when(mResources)
- .getDimension(
- com.android.internal.R.dimen.default_minimal_size_resizable_task);
+ doAnswer(
+ new Answer() {
+ @Override
+ public Object answer(InvocationOnMock i) {
+ Object[] args = i.getArguments();
+ TypedValue v = (TypedValue) args[1];
+ v.type = TypedValue.TYPE_DIMENSION;
+ v.data = TypedValue.createComplexDimension(valueDp,
+ TypedValue.COMPLEX_UNIT_DIP);
+ return null;
+ }
+ }
+ ).when(mResources).getValue(
+ eq(com.android.internal.R.dimen.default_minimal_size_resizable_task),
+ any(TypedValue.class), eq(true));
return this;
}
Builder setDeviceStateController(@NonNull DeviceStateController deviceStateController) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
index 05ee2f24fbaf..048e2ccc82b4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -19,6 +19,7 @@ package com.android.server.wm;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
@@ -1018,6 +1019,10 @@ public class TransitionTests extends WindowTestsBase {
@Test
public void testDisplayRotationChange() {
+ final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
+ spyOn(displayPolicy);
+ // Simulate gesture navigation (non-movable) so it is not seamless.
+ doReturn(false).when(displayPolicy).navigationBarCanMove();
final Task task = createActivityRecord(mDisplayContent).getTask();
final WindowState statusBar = createWindow(null, TYPE_STATUS_BAR, "statusBar");
final WindowState navBar = createWindow(null, TYPE_NAVIGATION_BAR, "navBar");
@@ -1072,7 +1077,8 @@ public class TransitionTests extends WindowTestsBase {
// Navigation bar finishes drawing after the start transaction, so its fade-in animation
// can execute directly.
- asyncRotationController.handleFinishDrawing(navBar, mMockT);
+ navBar.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN;
+ asyncRotationController.updateTargetWindows();
assertFalse(asyncRotationController.isTargetToken(navBar.mToken));
assertNull(mDisplayContent.getAsyncRotationController());
}
@@ -1371,6 +1377,9 @@ public class TransitionTests extends WindowTestsBase {
enteringAnimReports.clear();
closeTransition.finishTransition();
+ assertEquals(ActivityTaskManagerService.APP_SWITCH_DISALLOW, mAtm.getBalAppSwitchesState());
+ assertFalse(activity1.app.hasActivityInVisibleTask());
+
verify(snapshotController, times(1)).recordSnapshot(eq(task1), eq(false));
assertTrue(enteringAnimReports.contains(activity2));
}
@@ -1691,7 +1700,8 @@ public class TransitionTests extends WindowTestsBase {
@Test
public void testTransitionVisibleChange() {
registerTestTransitionPlayer();
- final ActivityRecord app = createActivityRecord(mDisplayContent);
+ final ActivityRecord app = createActivityRecord(
+ mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD);
final Transition transition = new Transition(TRANSIT_OPEN, 0 /* flags */,
app.mTransitionController, mWm.mSyncEngine);
app.mTransitionController.moveToCollecting(transition, BLASTSyncEngine.METHOD_NONE);
@@ -1741,7 +1751,8 @@ public class TransitionTests extends WindowTestsBase {
@Test
public void testVisibleChange_snapshot() {
registerTestTransitionPlayer();
- final ActivityRecord app = createActivityRecord(mDisplayContent);
+ final ActivityRecord app = createActivityRecord(
+ mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD);
final Transition transition = new Transition(TRANSIT_CHANGE, 0 /* flags */,
app.mTransitionController, mWm.mSyncEngine);
app.mTransitionController.moveToCollecting(transition, BLASTSyncEngine.METHOD_NONE);
diff --git a/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
index 2fccb88ad8de..75a8dd822914 100644
--- a/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
@@ -92,11 +92,11 @@ public class UnknownAppVisibilityControllerTest extends WindowTestsBase {
@Test
public void testRemoveFinishingInvisibleActivityFromUnknown() {
- final ActivityRecord activity = createNonAttachedActivityRecord(mDisplayContent);
+ final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity);
activity.finishing = true;
activity.setVisibleRequested(true);
- activity.setVisibility(false, false);
+ activity.setVisibility(false);
assertTrue(mDisplayContent.mUnknownAppVisibilityController.allResolved());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
index d7e4c5523eee..169586e2d9dc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -1023,7 +1023,7 @@ public class WindowOrganizerTests extends WindowTestsBase {
RunningTaskInfo mInfo;
@Override
- public void addStartingWindow(StartingWindowInfo info) { }
+ public void addStartingWindow(StartingWindowInfo info, IBinder appToken) { }
@Override
public void removeStartingWindow(StartingWindowRemovalInfo removalInfo) { }
@Override
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 3aee2cd5fac1..33067df0c8f3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -914,15 +914,15 @@ public class WindowStateTests extends WindowTestsBase {
final WindowState app = createWindow(null, TYPE_APPLICATION, "app", uid);
app.mActivityRecord.setVisible(false);
- app.mActivityRecord.setVisibility(false /* visible */, false /* deferHidingClient */);
+ app.mActivityRecord.setVisibility(false);
assertFalse(mAtm.hasActiveVisibleWindow(uid));
- app.mActivityRecord.setVisibility(true /* visible */, false /* deferHidingClient */);
+ app.mActivityRecord.setVisibility(true);
assertTrue(mAtm.hasActiveVisibleWindow(uid));
// Make the activity invisible and add a visible toast. The uid should have no active
// visible window because toast can be misused by legacy app to bypass background check.
- app.mActivityRecord.setVisibility(false /* visible */, false /* deferHidingClient */);
+ app.mActivityRecord.setVisibility(false);
final WindowState overlay = createWindow(null, TYPE_APPLICATION_OVERLAY, "overlay", uid);
final WindowState toast = createWindow(null, TYPE_TOAST, app.mToken, "toast", uid);
toast.onSurfaceShownChanged(true);
@@ -1157,12 +1157,12 @@ public class WindowStateTests extends WindowTestsBase {
public void testRequestedVisibility() {
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
app.mActivityRecord.setVisible(false);
- app.mActivityRecord.setVisibility(false /* visible */, false /* deferHidingClient */);
+ app.mActivityRecord.setVisibility(false);
assertFalse(app.isVisibleRequested());
// It doesn't have a surface yet, but should still be visible requested.
app.setHasSurface(false);
- app.mActivityRecord.setVisibility(true /* visible */, false /* deferHidingClient */);
+ app.mActivityRecord.setVisibility(true);
assertFalse(app.isVisible());
assertTrue(app.isVisibleRequested());
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index fafe90a5df55..323894ca76df 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -1583,10 +1583,10 @@ class WindowTestsBase extends SystemServiceTestsBase {
}
@Override
- public void addStartingWindow(StartingWindowInfo info) {
+ public void addStartingWindow(StartingWindowInfo info, IBinder appToken) {
synchronized (mWMService.mGlobalLock) {
final ActivityRecord activity = mWMService.mRoot.getActivityRecord(
- info.appToken);
+ appToken);
IWindow iWindow = mock(IWindow.class);
doReturn(mock(IBinder.class)).when(iWindow).asBinder();
final WindowState window = WindowTestsBase.createWindow(null,
@@ -1596,8 +1596,8 @@ class WindowTestsBase extends SystemServiceTestsBase {
iWindow,
mPowerManagerWrapper);
activity.mStartingWindow = window;
- mAppWindowMap.put(info.appToken, window);
- mTaskAppMap.put(info.taskInfo.taskId, info.appToken);
+ mAppWindowMap.put(appToken, window);
+ mTaskAppMap.put(info.taskInfo.taskId, appToken);
}
if (mRunnableWhenAddingSplashScreen != null) {
mRunnableWhenAddingSplashScreen.run();
diff --git a/services/usage/java/com/android/server/usage/TEST_MAPPING b/services/usage/java/com/android/server/usage/TEST_MAPPING
index 1c0c71b65fd7..a3fe6f2876d7 100644
--- a/services/usage/java/com/android/server/usage/TEST_MAPPING
+++ b/services/usage/java/com/android/server/usage/TEST_MAPPING
@@ -18,9 +18,7 @@
"exclude-filter": "com.android.server.usage.StorageStatsServiceTest"
}
]
- }
- ],
- "presubmit-large": [
+ },
{
"name": "CtsUsageStatsTestCases",
"options": [
diff --git a/services/usb/java/com/android/server/usb/UsbDirectMidiDevice.java b/services/usb/java/com/android/server/usb/UsbDirectMidiDevice.java
index 394d6e774aa1..b1cd99420737 100644
--- a/services/usb/java/com/android/server/usb/UsbDirectMidiDevice.java
+++ b/services/usb/java/com/android/server/usb/UsbDirectMidiDevice.java
@@ -19,7 +19,6 @@ package com.android.server.usb;
import android.annotation.NonNull;
import android.content.Context;
import android.hardware.usb.UsbConfiguration;
-import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
@@ -35,9 +34,12 @@ import android.os.Bundle;
import android.service.usb.UsbDirectMidiDeviceProto;
import android.util.Log;
+import com.android.internal.midi.MidiEventMultiScheduler;
import com.android.internal.midi.MidiEventScheduler;
import com.android.internal.midi.MidiEventScheduler.MidiEvent;
import com.android.internal.util.dump.DualDumpOutputStream;
+import com.android.server.usb.descriptors.UsbACMidi10Endpoint;
+import com.android.server.usb.descriptors.UsbDescriptor;
import com.android.server.usb.descriptors.UsbDescriptorParser;
import com.android.server.usb.descriptors.UsbEndpointDescriptor;
import com.android.server.usb.descriptors.UsbInterfaceDescriptor;
@@ -45,6 +47,7 @@ import com.android.server.usb.descriptors.UsbMidiBlockParser;
import libcore.io.IoUtils;
+import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.IOException;
import java.nio.ByteBuffer;
@@ -56,7 +59,7 @@ import java.util.ArrayList;
*/
public final class UsbDirectMidiDevice implements Closeable {
private static final String TAG = "UsbDirectMidiDevice";
- private static final boolean DEBUG = false;
+ private static final boolean DEBUG = true;
private Context mContext;
private String mName;
@@ -74,9 +77,6 @@ public final class UsbDirectMidiDevice implements Closeable {
private MidiDeviceServer mServer;
- // event schedulers for each input port of the physical device
- private MidiEventScheduler[] mEventSchedulers;
-
// Timeout for sending a packet to a device.
// If bulkTransfer times out, retry sending the packet up to 20 times.
private static final int BULK_TRANSFER_TIMEOUT_MILLISECONDS = 50;
@@ -86,8 +86,21 @@ public final class UsbDirectMidiDevice implements Closeable {
private static final int THREAD_JOIN_TIMEOUT_MILLISECONDS = 200;
private ArrayList<UsbDeviceConnection> mUsbDeviceConnections;
+
+ // Array of endpoints by device connection.
private ArrayList<ArrayList<UsbEndpoint>> mInputUsbEndpoints;
private ArrayList<ArrayList<UsbEndpoint>> mOutputUsbEndpoints;
+
+ // Array of cable counts by device connection.
+ // Each number here maps to an entry in mInputUsbEndpoints or mOutputUsbEndpoints.
+ // This is needed because this info is part of UsbEndpointDescriptor but not UsbEndpoint.
+ private ArrayList<ArrayList<Integer>> mInputUsbEndpointCableCounts;
+ private ArrayList<ArrayList<Integer>> mOutputUsbEndpointCableCounts;
+
+ // Array of event schedulers by device connection.
+ // Each number here maps to an entry in mOutputUsbEndpoints.
+ private ArrayList<ArrayList<MidiEventMultiScheduler>> mMidiEventMultiSchedulers;
+
private ArrayList<Thread> mThreads;
private UsbMidiBlockParser mMidiBlockParser = new UsbMidiBlockParser();
@@ -97,8 +110,6 @@ public final class UsbDirectMidiDevice implements Closeable {
private boolean mIsOpen;
private boolean mServerAvailable;
- private UsbMidiPacketConverter mUsbMidiPacketConverter;
-
private PowerBoostSetter mPowerBoostSetter = null;
private static final byte MESSAGE_TYPE_MIDI_1_CHANNEL_VOICE = 0x02;
@@ -238,9 +249,9 @@ public final class UsbDirectMidiDevice implements Closeable {
interfaceDescriptor.getEndpointDescriptor(endpointIndex);
// 0 is output, 1 << 7 is input.
if (endpoint.getDirection() == 0) {
- numOutputs++;
+ numOutputs += getNumJacks(endpoint);
} else {
- numInputs++;
+ numInputs += getNumJacks(endpoint);
}
}
}
@@ -307,19 +318,21 @@ public final class UsbDirectMidiDevice implements Closeable {
Log.d(TAG, "openLocked()");
UsbManager manager = mContext.getSystemService(UsbManager.class);
- // Converting from raw MIDI to USB MIDI is not thread-safe.
- // UsbMidiPacketConverter creates a converter from raw MIDI
- // to USB MIDI for each USB output.
- mUsbMidiPacketConverter = new UsbMidiPacketConverter(mNumOutputs);
-
mUsbDeviceConnections = new ArrayList<UsbDeviceConnection>();
mInputUsbEndpoints = new ArrayList<ArrayList<UsbEndpoint>>();
mOutputUsbEndpoints = new ArrayList<ArrayList<UsbEndpoint>>();
+ mInputUsbEndpointCableCounts = new ArrayList<ArrayList<Integer>>();
+ mOutputUsbEndpointCableCounts = new ArrayList<ArrayList<Integer>>();
+ mMidiEventMultiSchedulers = new ArrayList<ArrayList<MidiEventMultiScheduler>>();
mThreads = new ArrayList<Thread>();
for (int interfaceIndex = 0; interfaceIndex < mUsbInterfaces.size(); interfaceIndex++) {
ArrayList<UsbEndpoint> inputEndpoints = new ArrayList<UsbEndpoint>();
ArrayList<UsbEndpoint> outputEndpoints = new ArrayList<UsbEndpoint>();
+ ArrayList<Integer> inputEndpointCableCounts = new ArrayList<Integer>();
+ ArrayList<Integer> outputEndpointCableCounts = new ArrayList<Integer>();
+ ArrayList<MidiEventMultiScheduler> midiEventMultiSchedulers =
+ new ArrayList<MidiEventMultiScheduler>();
UsbInterfaceDescriptor interfaceDescriptor = mUsbInterfaces.get(interfaceIndex);
for (int endpointIndex = 0; endpointIndex < interfaceDescriptor.getNumEndpoints();
endpointIndex++) {
@@ -328,8 +341,13 @@ public final class UsbDirectMidiDevice implements Closeable {
// 0 is output, 1 << 7 is input.
if (endpoint.getDirection() == 0) {
outputEndpoints.add(endpoint.toAndroid(mParser));
+ outputEndpointCableCounts.add(getNumJacks(endpoint));
+ MidiEventMultiScheduler scheduler =
+ new MidiEventMultiScheduler(getNumJacks(endpoint));
+ midiEventMultiSchedulers.add(scheduler);
} else {
inputEndpoints.add(endpoint.toAndroid(mParser));
+ inputEndpointCableCounts.add(getNumJacks(endpoint));
}
}
if (!outputEndpoints.isEmpty() || !inputEndpoints.isEmpty()) {
@@ -341,46 +359,73 @@ public final class UsbDirectMidiDevice implements Closeable {
mUsbDeviceConnections.add(connection);
mInputUsbEndpoints.add(inputEndpoints);
mOutputUsbEndpoints.add(outputEndpoints);
+ mInputUsbEndpointCableCounts.add(inputEndpointCableCounts);
+ mOutputUsbEndpointCableCounts.add(outputEndpointCableCounts);
+ mMidiEventMultiSchedulers.add(midiEventMultiSchedulers);
}
}
- mEventSchedulers = new MidiEventScheduler[mNumOutputs];
-
- for (int i = 0; i < mNumOutputs; i++) {
- MidiEventScheduler scheduler = new MidiEventScheduler();
- mEventSchedulers[i] = scheduler;
- mMidiInputPortReceivers[i].setReceiver(scheduler.getReceiver());
+ // Set up event schedulers
+ int outputIndex = 0;
+ for (int connectionIndex = 0; connectionIndex < mMidiEventMultiSchedulers.size();
+ connectionIndex++) {
+ for (int endpointIndex = 0;
+ endpointIndex < mMidiEventMultiSchedulers.get(connectionIndex).size();
+ endpointIndex++) {
+ int cableCount =
+ mOutputUsbEndpointCableCounts.get(connectionIndex).get(endpointIndex);
+ MidiEventMultiScheduler multiScheduler =
+ mMidiEventMultiSchedulers.get(connectionIndex).get(endpointIndex);
+ for (int cableNumber = 0; cableNumber < cableCount; cableNumber++) {
+ MidiEventScheduler scheduler = multiScheduler.getEventScheduler(cableNumber);
+ mMidiInputPortReceivers[outputIndex].setReceiver(scheduler.getReceiver());
+ outputIndex++;
+ }
+ }
}
final MidiReceiver[] outputReceivers = mServer.getOutputPortReceivers();
// Create input thread for each input port of the physical device
- int portNumber = 0;
+ int portStartNumber = 0;
for (int connectionIndex = 0; connectionIndex < mInputUsbEndpoints.size();
connectionIndex++) {
for (int endpointIndex = 0;
endpointIndex < mInputUsbEndpoints.get(connectionIndex).size();
endpointIndex++) {
+ // Each USB endpoint maps to one or more outputReceivers. USB MIDI data from an
+ // endpoint should be sent to the appropriate outputReceiver. A new thread is
+ // created and waits for incoming USB data. Once the data is received, it is added
+ // to the packet converter. The packet converter acts as an inverse multiplexer.
+ // With a for loop, data is pulled per cable and sent to the correct output
+ // receiver. The first byte of each legacy MIDI 1.0 USB message indicates which
+ // cable the data should be used and is how the reverse multiplexer directs data.
+ // For MIDI UMP endpoints, a multiplexer is not needed as we are just swapping
+ // the endianness of the packets.
final UsbDeviceConnection connectionFinal =
mUsbDeviceConnections.get(connectionIndex);
final UsbEndpoint endpointFinal =
mInputUsbEndpoints.get(connectionIndex).get(endpointIndex);
- final int portFinal = portNumber;
+ final int portStartFinal = portStartNumber;
+ final int cableCountFinal =
+ mInputUsbEndpointCableCounts.get(connectionIndex).get(endpointIndex);
- Thread newThread = new Thread("UsbDirectMidiDevice input thread " + portFinal) {
+ Thread newThread = new Thread("UsbDirectMidiDevice input thread "
+ + portStartFinal) {
@Override
public void run() {
final UsbRequest request = new UsbRequest();
+ final UsbMidiPacketConverter packetConverter = new UsbMidiPacketConverter();
+ packetConverter.createDecoders(cableCountFinal);
try {
request.initialize(connectionFinal, endpointFinal);
byte[] inputBuffer = new byte[endpointFinal.getMaxPacketSize()];
- while (true) {
+ boolean keepGoing = true;
+ while (keepGoing) {
if (Thread.currentThread().interrupted()) {
Log.w(TAG, "input thread interrupted");
break;
}
- // Record time of event immediately after waking.
- long timestamp = System.nanoTime();
final ByteBuffer byteBuffer = ByteBuffer.wrap(inputBuffer);
if (!request.queue(byteBuffer)) {
Log.w(TAG, "Cannot queue request");
@@ -396,6 +441,9 @@ public final class UsbDirectMidiDevice implements Closeable {
continue;
}
+ // Record time of event after receiving response.
+ long timestamp = System.nanoTime();
+
int bytesRead = byteBuffer.position();
if (bytesRead > 0) {
@@ -403,42 +451,56 @@ public final class UsbDirectMidiDevice implements Closeable {
logByteArray("Input before conversion ", inputBuffer,
0, bytesRead);
}
+
+ // Add packets into the packet decoder.
+ if (!mIsUniversalMidiDevice) {
+ packetConverter.decodeMidiPackets(inputBuffer, bytesRead);
+ }
+
byte[] convertedArray;
- if (mIsUniversalMidiDevice) {
- // For USB, each 32 bit word of a UMP is
- // sent with the least significant byte first.
- convertedArray = swapEndiannessPerWord(inputBuffer,
- bytesRead);
- } else {
- if (mUsbMidiPacketConverter == null) {
- Log.w(TAG, "mUsbMidiPacketConverter is null");
- break;
+ for (int cableNumber = 0; cableNumber < cableCountFinal;
+ cableNumber++) {
+ if (mIsUniversalMidiDevice) {
+ // For USB, each 32 bit word of a UMP is
+ // sent with the least significant byte first.
+ convertedArray = swapEndiannessPerWord(inputBuffer,
+ bytesRead);
+ } else {
+ convertedArray =
+ packetConverter.pullDecodedMidiPackets(
+ cableNumber);
}
- convertedArray =
- mUsbMidiPacketConverter.usbMidiToRawMidi(
- inputBuffer, bytesRead);
- }
- if (DEBUG) {
- logByteArray("Input after conversion ", convertedArray,
- 0, convertedArray.length);
- }
+ if (DEBUG) {
+ logByteArray("Input " + cableNumber
+ + " after conversion ", convertedArray, 0,
+ convertedArray.length);
+ }
- if ((outputReceivers == null)
- || (outputReceivers[portFinal] == null)) {
- Log.w(TAG, "outputReceivers is null");
- break;
- }
- outputReceivers[portFinal].send(convertedArray, 0,
- convertedArray.length, timestamp);
-
- // Boost power if there seems to be a voice message.
- // For legacy devices, boost when message is more than size 1.
- // For UMP devices, boost for channel voice messages.
- if ((mPowerBoostSetter != null && convertedArray.length > 1)
- && (!mIsUniversalMidiDevice
- || isChannelVoiceMessage(convertedArray))) {
- mPowerBoostSetter.boostPower();
+ if (convertedArray.length == 0) {
+ continue;
+ }
+
+ if ((outputReceivers == null)
+ || (outputReceivers[portStartFinal + cableNumber]
+ == null)) {
+ Log.w(TAG, "outputReceivers is null");
+ keepGoing = false;
+ break;
+ }
+ outputReceivers[portStartFinal + cableNumber].send(
+ convertedArray, 0, convertedArray.length,
+ timestamp);
+
+ // Boost power if there seems to be a voice message.
+ // For legacy devices, boost if message length > 1.
+ // For UMP devices, boost for channel voice messages.
+ if ((mPowerBoostSetter != null
+ && convertedArray.length > 1)
+ && (!mIsUniversalMidiDevice
+ || isChannelVoiceMessage(convertedArray))) {
+ mPowerBoostSetter.boostPower();
+ }
}
}
}
@@ -454,64 +516,93 @@ public final class UsbDirectMidiDevice implements Closeable {
};
newThread.start();
mThreads.add(newThread);
- portNumber++;
+ portStartNumber += cableCountFinal;
}
}
// Create output thread for each output port of the physical device
- portNumber = 0;
+ portStartNumber = 0;
for (int connectionIndex = 0; connectionIndex < mOutputUsbEndpoints.size();
connectionIndex++) {
for (int endpointIndex = 0;
endpointIndex < mOutputUsbEndpoints.get(connectionIndex).size();
endpointIndex++) {
+ // Each USB endpoint maps to one or more MIDI ports. Each port has an event
+ // scheduler that is used to pull incoming raw MIDI bytes from Android apps.
+ // With a MidiEventMultiScheduler, data can be pulled if any of the schedulers
+ // have new incoming data. This data is then packaged as USB MIDI packets before
+ // getting sent through USB. One thread will be created per endpoint that pulls
+ // data from all relevant event schedulers. Raw MIDI from the event schedulers
+ // will be converted to the correct USB MIDI format before getting sent through
+ // USB.
+
final UsbDeviceConnection connectionFinal =
mUsbDeviceConnections.get(connectionIndex);
final UsbEndpoint endpointFinal =
mOutputUsbEndpoints.get(connectionIndex).get(endpointIndex);
- final int portFinal = portNumber;
- final MidiEventScheduler eventSchedulerFinal = mEventSchedulers[portFinal];
-
- Thread newThread = new Thread("UsbDirectMidiDevice output thread " + portFinal) {
+ final int portStartFinal = portStartNumber;
+ final int cableCountFinal =
+ mOutputUsbEndpointCableCounts.get(connectionIndex).get(endpointIndex);
+ final MidiEventMultiScheduler multiSchedulerFinal =
+ mMidiEventMultiSchedulers.get(connectionIndex).get(endpointIndex);
+
+ Thread newThread = new Thread("UsbDirectMidiDevice output write thread "
+ + portStartFinal) {
@Override
public void run() {
try {
- while (true) {
- if (Thread.currentThread().interrupted()) {
- Log.w(TAG, "output thread interrupted");
- break;
- }
- MidiEvent event;
- try {
- event = (MidiEvent) eventSchedulerFinal.waitNextEvent();
- } catch (InterruptedException e) {
- Log.w(TAG, "event scheduler interrupted");
+ final ByteArrayOutputStream midi2ByteStream =
+ new ByteArrayOutputStream();
+ final UsbMidiPacketConverter packetConverter =
+ new UsbMidiPacketConverter();
+ packetConverter.createEncoders(cableCountFinal);
+ boolean isInterrupted = false;
+ while (!isInterrupted) {
+ boolean wasSuccessful = multiSchedulerFinal.waitNextEvent();
+ if (!wasSuccessful) {
+ Log.d(TAG, "output thread closed");
break;
}
- if (event == null) {
- Log.w(TAG, "event is null");
- break;
+ long now = System.nanoTime();
+ for (int cableNumber = 0; cableNumber < cableCountFinal;
+ cableNumber++) {
+ MidiEventScheduler eventScheduler =
+ multiSchedulerFinal.getEventScheduler(cableNumber);
+ MidiEvent event =
+ (MidiEvent) eventScheduler.getNextEvent(now);
+ while (event != null) {
+ if (DEBUG) {
+ logByteArray("Output before conversion ",
+ event.data, 0, event.count);
+ }
+ if (mIsUniversalMidiDevice) {
+ // For USB, each 32 bit word of a UMP is
+ // sent with the least significant byte first.
+ byte[] convertedArray = swapEndiannessPerWord(
+ event.data, event.count);
+ midi2ByteStream.write(convertedArray, 0,
+ convertedArray.length);
+ } else {
+ packetConverter.encodeMidiPackets(event.data,
+ event.count, cableNumber);
+ }
+ eventScheduler.addEventToPool(event);
+ event = (MidiEvent) eventScheduler.getNextEvent(now);
+ }
}
- if (DEBUG) {
- logByteArray("Output before conversion ", event.data, 0,
- event.count);
+ if (Thread.currentThread().interrupted()) {
+ Log.d(TAG, "output thread interrupted");
+ break;
}
- byte[] convertedArray;
+ byte[] convertedArray = new byte[0];
if (mIsUniversalMidiDevice) {
- // For USB, each 32 bit word of a UMP is
- // sent with the least significant byte first.
- convertedArray = swapEndiannessPerWord(event.data,
- event.count);
+ convertedArray = midi2ByteStream.toByteArray();
+ midi2ByteStream.reset();
} else {
- if (mUsbMidiPacketConverter == null) {
- Log.w(TAG, "mUsbMidiPacketConverter is null");
- break;
- }
convertedArray =
- mUsbMidiPacketConverter.rawMidiToUsbMidi(
- event.data, event.count, portFinal);
+ packetConverter.pullEncodedMidiPackets();
}
if (DEBUG) {
@@ -519,7 +610,6 @@ public final class UsbDirectMidiDevice implements Closeable {
convertedArray.length);
}
- boolean isInterrupted = false;
// Split the packet into multiple if they are greater than the
// endpoint's max packet size.
for (int curPacketStart = 0;
@@ -557,11 +647,9 @@ public final class UsbDirectMidiDevice implements Closeable {
}
}
}
- if (isInterrupted == true) {
- break;
- }
- eventSchedulerFinal.addEventToPool(event);
}
+ } catch (InterruptedException e) {
+ Log.w(TAG, "output thread: ", e);
} catch (NullPointerException e) {
Log.e(TAG, "output thread: ", e);
}
@@ -570,7 +658,7 @@ public final class UsbDirectMidiDevice implements Closeable {
};
newThread.start();
mThreads.add(newThread);
- portNumber++;
+ portStartNumber += cableCountFinal;
}
}
@@ -666,11 +754,21 @@ public final class UsbDirectMidiDevice implements Closeable {
}
mThreads = null;
- for (int i = 0; i < mEventSchedulers.length; i++) {
+ for (int i = 0; i < mMidiInputPortReceivers.length; i++) {
mMidiInputPortReceivers[i].setReceiver(null);
- mEventSchedulers[i].close();
}
- mEventSchedulers = null;
+
+ for (int connectionIndex = 0; connectionIndex < mMidiEventMultiSchedulers.size();
+ connectionIndex++) {
+ for (int endpointIndex = 0;
+ endpointIndex < mMidiEventMultiSchedulers.get(connectionIndex).size();
+ endpointIndex++) {
+ MidiEventMultiScheduler multiScheduler =
+ mMidiEventMultiSchedulers.get(connectionIndex).get(endpointIndex);
+ multiScheduler.close();
+ }
+ }
+ mMidiEventMultiSchedulers = null;
for (UsbDeviceConnection connection : mUsbDeviceConnections) {
connection.close();
@@ -678,8 +776,8 @@ public final class UsbDirectMidiDevice implements Closeable {
mUsbDeviceConnections = null;
mInputUsbEndpoints = null;
mOutputUsbEndpoints = null;
-
- mUsbMidiPacketConverter = null;
+ mInputUsbEndpointCableCounts = null;
+ mOutputUsbEndpointCableCounts = null;
mIsOpen = false;
}
@@ -787,4 +885,19 @@ public final class UsbDirectMidiDevice implements Closeable {
return messageType == MESSAGE_TYPE_MIDI_1_CHANNEL_VOICE
|| messageType == MESSAGE_TYPE_MIDI_2_CHANNEL_VOICE;
}
+
+ // Returns the number of jacks for MIDI 1.0 endpoints.
+ // For MIDI 2.0 endpoints, this concept does not exist and each endpoint should be treated as
+ // one port.
+ private int getNumJacks(UsbEndpointDescriptor usbEndpointDescriptor) {
+ UsbDescriptor classSpecificEndpointDescriptor =
+ usbEndpointDescriptor.getClassSpecificEndpointDescriptor();
+ if (classSpecificEndpointDescriptor != null
+ && (classSpecificEndpointDescriptor instanceof UsbACMidi10Endpoint)) {
+ UsbACMidi10Endpoint midiEndpoint =
+ (UsbACMidi10Endpoint) classSpecificEndpointDescriptor;
+ return midiEndpoint.getNumJacks();
+ }
+ return 1;
+ }
}
diff --git a/services/usb/java/com/android/server/usb/UsbMidiPacketConverter.java b/services/usb/java/com/android/server/usb/UsbMidiPacketConverter.java
index 56bb23681741..65d7a41cf1ec 100644
--- a/services/usb/java/com/android/server/usb/UsbMidiPacketConverter.java
+++ b/services/usb/java/com/android/server/usb/UsbMidiPacketConverter.java
@@ -16,12 +16,17 @@
package com.android.server.usb;
+import android.util.Log;
+
import java.io.ByteArrayOutputStream;
/**
- * Converts between MIDI packets and USB MIDI 1.0 packets.
+ * Converts between raw MIDI packets and USB MIDI 1.0 packets.
+ * This is NOT thread-safe. Please handle locking outside this function for multiple threads.
+ * For data mapping to an invalid cable number, this converter will use the first cable.
*/
public class UsbMidiPacketConverter {
+ private static final String TAG = "UsbMidiPacketConverter";
// Refer to Table 4-1 in USB MIDI 1.0 spec.
private static final int[] PAYLOAD_SIZE = new int[]{
@@ -74,54 +79,133 @@ public class UsbMidiPacketConverter {
private static final byte SYSEX_START_EXCLUSIVE = (byte) 0xF0;
private static final byte SYSEX_END_EXCLUSIVE = (byte) 0xF7;
- private UsbMidiDecoder mUsbMidiDecoder = new UsbMidiDecoder();
private UsbMidiEncoder[] mUsbMidiEncoders;
+ private ByteArrayOutputStream mEncoderOutputStream = new ByteArrayOutputStream();
- public UsbMidiPacketConverter(int numEncoders) {
- mUsbMidiEncoders = new UsbMidiEncoder[numEncoders];
- for (int i = 0; i < numEncoders; i++) {
- mUsbMidiEncoders[i] = new UsbMidiEncoder();
- }
- }
+ private UsbMidiDecoder mUsbMidiDecoder;
/**
- * Converts a USB MIDI array into a raw MIDI array.
+ * Creates encoders.
*
- * @param usbMidiBytes the USB MIDI bytes to convert
- * @param size the size of usbMidiBytes
- * @return byte array of raw MIDI packets
+ * createEncoders() must be called before raw MIDI can be converted to USB MIDI.
+ *
+ * @param size the number of encoders to create
*/
- public byte[] usbMidiToRawMidi(byte[] usbMidiBytes, int size) {
- return mUsbMidiDecoder.decode(usbMidiBytes, size);
+ public void createEncoders(int size) {
+ mUsbMidiEncoders = new UsbMidiEncoder[size];
+ for (int i = 0; i < size; i++) {
+ mUsbMidiEncoders[i] = new UsbMidiEncoder(i);
+ }
}
/**
* Converts a raw MIDI array into a USB MIDI array.
*
+ * Call pullEncodedMidiPackets to retrieve the byte array.
+ *
* @param midiBytes the raw MIDI bytes to convert
* @param size the size of usbMidiBytes
* @param encoderId which encoder to use
+ */
+ public void encodeMidiPackets(byte[] midiBytes, int size, int encoderId) {
+ // Use the first encoder if the encoderId is invalid.
+ if (encoderId >= mUsbMidiEncoders.length) {
+ Log.w(TAG, "encoderId " + encoderId + " invalid");
+ encoderId = 0;
+ }
+ byte[] encodedPacket = mUsbMidiEncoders[encoderId].encode(midiBytes, size);
+ mEncoderOutputStream.write(encodedPacket, 0, encodedPacket.length);
+ }
+
+ /**
+ * Returns the encoded MIDI packets from encodeMidiPackets
+ *
* @return byte array of USB MIDI packets
*/
- public byte[] rawMidiToUsbMidi(byte[] midiBytes, int size, int encoderId) {
- return mUsbMidiEncoders[encoderId].encode(midiBytes, size);
+ public byte[] pullEncodedMidiPackets() {
+ byte[] output = mEncoderOutputStream.toByteArray();
+ mEncoderOutputStream.reset();
+ return output;
+ }
+
+ /**
+ * Creates decoders.
+ *
+ * createDecoders() must be called before USB MIDI can be converted to raw MIDI.
+ *
+ * @param size the number of decoders to create
+ */
+ public void createDecoders(int size) {
+ mUsbMidiDecoder = new UsbMidiDecoder(size);
+ }
+
+ /**
+ * Converts a USB MIDI array into a multiple MIDI arrays, one per cable.
+ *
+ * Call pullDecodedMidiPackets to retrieve the byte array.
+ *
+ * @param usbMidiBytes the USB MIDI bytes to convert
+ * @param size the size of usbMidiBytes
+ */
+ public void decodeMidiPackets(byte[] usbMidiBytes, int size) {
+ mUsbMidiDecoder.decode(usbMidiBytes, size);
+ }
+
+ /**
+ * Returns the decoded MIDI packets from decodeMidiPackets
+ *
+ * @param cableNumber the cable to pull data from
+ * @return byte array of raw MIDI packets
+ */
+ public byte[] pullDecodedMidiPackets(int cableNumber) {
+ return mUsbMidiDecoder.pullBytes(cableNumber);
}
private class UsbMidiDecoder {
+ int mNumJacks;
+ ByteArrayOutputStream[] mDecodedByteArrays;
+
+ UsbMidiDecoder(int numJacks) {
+ mNumJacks = numJacks;
+ mDecodedByteArrays = new ByteArrayOutputStream[numJacks];
+ for (int i = 0; i < numJacks; i++) {
+ mDecodedByteArrays[i] = new ByteArrayOutputStream();
+ }
+ }
+
// Decodes the data from USB MIDI to raw MIDI.
// Each valid 4 byte input maps to a 1-3 byte output.
// Reference the USB MIDI 1.0 spec for more info.
- public byte[] decode(byte[] usbMidiBytes, int size) {
+ public void decode(byte[] usbMidiBytes, int size) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ if (size % 4 != 0) {
+ Log.w(TAG, "size " + size + " not multiple of 4");
+ }
for (int i = 0; i + 3 < size; i += 4) {
+ int cableNumber = (usbMidiBytes[i] >> 4) & 0x0f;
int codeIndex = usbMidiBytes[i] & 0x0f;
int numPayloadBytes = PAYLOAD_SIZE[codeIndex];
if (numPayloadBytes < 0) {
continue;
}
- outputStream.write(usbMidiBytes, i + 1, numPayloadBytes);
+ // Use the first cable if the cable number is invalid.
+ if (cableNumber >= mNumJacks) {
+ Log.w(TAG, "cableNumber " + cableNumber + " invalid");
+ cableNumber = 0;
+ }
+ mDecodedByteArrays[cableNumber].write(usbMidiBytes, i + 1, numPayloadBytes);
}
- return outputStream.toByteArray();
+ }
+
+ public byte[] pullBytes(int cableNumber) {
+ // Use the first cable if the cable number is invalid.
+ if (cableNumber >= mNumJacks) {
+ Log.w(TAG, "cableNumber " + cableNumber + " invalid");
+ cableNumber = 0;
+ }
+ byte[] output = mDecodedByteArrays[cableNumber].toByteArray();
+ mDecodedByteArrays[cableNumber].reset();
+ return output;
}
}
@@ -135,6 +219,13 @@ public class UsbMidiPacketConverter {
private byte[] mEmptyBytes = new byte[3]; // Used to fill out extra data
+ private byte mShiftedCableNumber;
+
+ UsbMidiEncoder(int cableNumber) {
+ // Jack Id is always the left nibble of every byte so shift this now.
+ mShiftedCableNumber = (byte) (cableNumber << 4);
+ }
+
// Encodes the data from raw MIDI to USB MIDI.
// Each valid 1-3 byte input maps to a 4 byte output.
// Reference the USB MIDI 1.0 spec for more info.
@@ -153,7 +244,8 @@ public class UsbMidiPacketConverter {
midiBytes[curLocation];
mNumStoredSystemExclusiveBytes++;
if (mNumStoredSystemExclusiveBytes == 3) {
- outputStream.write(CODE_INDEX_NUMBER_SYSEX_STARTS_OR_CONTINUES);
+ outputStream.write(CODE_INDEX_NUMBER_SYSEX_STARTS_OR_CONTINUES
+ | mShiftedCableNumber);
outputStream.write(mStoredSystemExclusiveBytes, 0, 3);
mNumStoredSystemExclusiveBytes = 0;
}
@@ -179,7 +271,7 @@ public class UsbMidiPacketConverter {
byte codeIndexNumber = (byte) ((midiBytes[curLocation] >> 4) & 0x0f);
int channelMessageSize = PAYLOAD_SIZE[codeIndexNumber];
if (curLocation + channelMessageSize <= size) {
- outputStream.write(codeIndexNumber);
+ outputStream.write(codeIndexNumber | mShiftedCableNumber);
outputStream.write(midiBytes, curLocation, channelMessageSize);
// Fill in the rest of the bytes with 0.
outputStream.write(mEmptyBytes, 0, 3 - channelMessageSize);
@@ -197,8 +289,8 @@ public class UsbMidiPacketConverter {
curLocation++;
} else if (midiBytes[curLocation] == SYSEX_END_EXCLUSIVE) {
// 1 byte is 0x05, 2 bytes is 0x06, and 3 bytes is 0x07
- outputStream.write(CODE_INDEX_NUMBER_SYSEX_END_SINGLE_BYTE
- + mNumStoredSystemExclusiveBytes);
+ outputStream.write((CODE_INDEX_NUMBER_SYSEX_END_SINGLE_BYTE
+ + mNumStoredSystemExclusiveBytes) | mShiftedCableNumber);
mStoredSystemExclusiveBytes[mNumStoredSystemExclusiveBytes] =
midiBytes[curLocation];
mNumStoredSystemExclusiveBytes++;
@@ -218,7 +310,7 @@ public class UsbMidiPacketConverter {
} else {
int systemMessageSize = PAYLOAD_SIZE[codeIndexNumber];
if (curLocation + systemMessageSize <= size) {
- outputStream.write(codeIndexNumber);
+ outputStream.write(codeIndexNumber | mShiftedCableNumber);
outputStream.write(midiBytes, curLocation, systemMessageSize);
// Fill in the rest of the bytes with 0.
outputStream.write(mEmptyBytes, 0, 3 - systemMessageSize);
@@ -236,7 +328,7 @@ public class UsbMidiPacketConverter {
}
private void writeSingleByte(ByteArrayOutputStream outputStream, byte byteToWrite) {
- outputStream.write(CODE_INDEX_NUMBER_SINGLE_BYTE);
+ outputStream.write(CODE_INDEX_NUMBER_SINGLE_BYTE | mShiftedCableNumber);
outputStream.write(byteToWrite);
outputStream.write(0);
outputStream.write(0);
diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbEndpointDescriptor.java b/services/usb/java/com/android/server/usb/descriptors/UsbEndpointDescriptor.java
index 1f448acac5e8..117a3d9f374e 100644
--- a/services/usb/java/com/android/server/usb/descriptors/UsbEndpointDescriptor.java
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbEndpointDescriptor.java
@@ -118,7 +118,7 @@ public class UsbEndpointDescriptor extends UsbDescriptor {
mClassSpecificEndpointDescriptor = descriptor;
}
- UsbDescriptor getClassSpecificEndpointDescriptor() {
+ public UsbDescriptor getClassSpecificEndpointDescriptor() {
return mClassSpecificEndpointDescriptor;
}
diff --git a/services/voiceinteraction/TEST_MAPPING b/services/voiceinteraction/TEST_MAPPING
index d6c69647d754..5fe1c8d2ecb0 100644
--- a/services/voiceinteraction/TEST_MAPPING
+++ b/services/voiceinteraction/TEST_MAPPING
@@ -1,5 +1,5 @@
{
- "presubmit-large": [
+ "presubmit": [
{
"name": "CtsVoiceInteractionTestCases",
"options": [
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLogging.java b/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLogging.java
index ce1157e1d80c..7d5750e49907 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLogging.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLogging.java
@@ -30,11 +30,14 @@ import android.media.soundtrigger.SoundModel;
import android.media.soundtrigger_middleware.ISoundTriggerCallback;
import android.media.soundtrigger_middleware.ISoundTriggerModule;
import android.media.soundtrigger_middleware.SoundTriggerModuleDescriptor;
+import android.os.BatteryStatsInternal;
import android.os.IBinder;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.util.Log;
import com.android.internal.util.LatencyTracker;
+import com.android.server.LocalServices;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
@@ -291,6 +294,8 @@ public class SoundTriggerMiddlewareLogging implements ISoundTriggerMiddlewareInt
public void onRecognition(int modelHandle, RecognitionEvent event, int captureSession)
throws RemoteException {
try {
+ BatteryStatsHolder.INSTANCE.noteWakingSoundTrigger(
+ SystemClock.elapsedRealtime(), mOriginatorIdentity.uid);
mCallbackDelegate.onRecognition(modelHandle, event, captureSession);
logVoidReturn("onRecognition", modelHandle, event);
} catch (Exception e) {
@@ -304,6 +309,8 @@ public class SoundTriggerMiddlewareLogging implements ISoundTriggerMiddlewareInt
int captureSession)
throws RemoteException {
try {
+ BatteryStatsHolder.INSTANCE.noteWakingSoundTrigger(
+ SystemClock.elapsedRealtime(), mOriginatorIdentity.uid);
startKeyphraseEventLatencyTracking(event);
mCallbackDelegate.onPhraseRecognition(modelHandle, event, captureSession);
logVoidReturn("onPhraseRecognition", modelHandle, event);
@@ -387,6 +394,12 @@ public class SoundTriggerMiddlewareLogging implements ISoundTriggerMiddlewareInt
}
}
+ private static class BatteryStatsHolder {
+ private static final BatteryStatsInternal INSTANCE =
+ LocalServices.getService(BatteryStatsInternal.class);
+ }
+
+
////////////////////////////////////////////////////////////////////////////////////////////////
// Actual logging logic below.
private static final int NUM_EVENTS_TO_DUMP = 64;
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java
index ec9bd2fbfa6d..06fc41626e50 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java
@@ -83,6 +83,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IHotwordRecognitionStatusCallback;
import com.android.internal.infra.AndroidFuture;
import com.android.server.LocalServices;
+import com.android.server.voiceinteraction.VoiceInteractionManagerServiceImpl.DetectorRemoteExceptionListener;
import java.io.Closeable;
import java.io.IOException;
@@ -203,12 +204,16 @@ abstract class DetectorSession {
boolean mPerformingExternalSourceHotwordDetection;
@NonNull final IBinder mToken;
+ @NonNull DetectorRemoteExceptionListener mRemoteExceptionListener;
+
DetectorSession(
@NonNull HotwordDetectionConnection.ServiceConnection remoteDetectionService,
@NonNull Object lock, @NonNull Context context, @NonNull IBinder token,
@NonNull IHotwordRecognitionStatusCallback callback, int voiceInteractionServiceUid,
Identity voiceInteractorIdentity,
- @NonNull ScheduledExecutorService scheduledExecutorService, boolean logging) {
+ @NonNull ScheduledExecutorService scheduledExecutorService, boolean logging,
+ @NonNull DetectorRemoteExceptionListener listener) {
+ mRemoteExceptionListener = listener;
mRemoteDetectionService = remoteDetectionService;
mLock = lock;
mContext = context;
@@ -237,6 +242,14 @@ abstract class DetectorSession {
}
}
+ void notifyOnDetectorRemoteException() {
+ Slog.d(TAG, "notifyOnDetectorRemoteException: mRemoteExceptionListener="
+ + mRemoteExceptionListener);
+ if (mRemoteExceptionListener != null) {
+ mRemoteExceptionListener.onDetectorRemoteException(mToken, getDetectorType());
+ }
+ }
+
@SuppressWarnings("GuardedBy")
private void updateStateAfterProcessStartLocked(PersistableBundle options,
SharedMemory sharedMemory) {
@@ -280,6 +293,7 @@ abstract class DetectorSession {
METRICS_CALLBACK_ON_STATUS_REPORTED_EXCEPTION,
mVoiceInteractionServiceUid);
}
+ notifyOnDetectorRemoteException();
}
}
};
@@ -319,6 +333,7 @@ abstract class DetectorSession {
METRICS_CALLBACK_ON_STATUS_REPORTED_EXCEPTION,
mVoiceInteractionServiceUid);
}
+ notifyOnDetectorRemoteException();
}
} else if (err != null) {
Slog.w(TAG, "Failed to update state: " + err);
@@ -443,6 +458,7 @@ abstract class DetectorSession {
HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_ON_ERROR_EXCEPTION,
mVoiceInteractionServiceUid);
}
+ notifyOnDetectorRemoteException();
}
} finally {
synchronized (mLock) {
@@ -479,8 +495,12 @@ abstract class DetectorSession {
EXTERNAL_HOTWORD_CLEANUP_MILLIS,
TimeUnit.MILLISECONDS);
- callback.onRejected(result);
-
+ try {
+ callback.onRejected(result);
+ } catch (RemoteException e) {
+ notifyOnDetectorRemoteException();
+ throw e;
+ }
if (result != null) {
Slog.i(TAG, "Egressed 'hotword rejected result' "
+ "from hotword trusted process");
@@ -510,14 +530,21 @@ abstract class DetectorSession {
try {
enforcePermissionsForDataDelivery();
} catch (SecurityException e) {
+ Slog.w(TAG, "Ignoring #onDetected due to a "
+ + "SecurityException", e);
HotwordMetricsLogger.writeDetectorEvent(
getDetectorType(),
EXTERNAL_SOURCE_DETECT_SECURITY_EXCEPTION,
mVoiceInteractionServiceUid);
- callback.onError(new HotwordDetectionServiceFailure(
- CALLBACK_ONDETECTED_GOT_SECURITY_EXCEPTION,
- "Security exception occurs in #onDetected"
- + " method."));
+ try {
+ callback.onError(new HotwordDetectionServiceFailure(
+ CALLBACK_ONDETECTED_GOT_SECURITY_EXCEPTION,
+ "Security exception occurs in #onDetected"
+ + " method."));
+ } catch (RemoteException e1) {
+ notifyOnDetectorRemoteException();
+ throw e1;
+ }
return;
}
HotwordDetectedResult newResult;
@@ -525,14 +552,26 @@ abstract class DetectorSession {
newResult = mHotwordAudioStreamCopier
.startCopyingAudioStreams(triggerResult);
} catch (IOException e) {
+ Slog.w(TAG, "Ignoring #onDetected due to a "
+ + "IOException", e);
// TODO: Write event
- callback.onError(new HotwordDetectionServiceFailure(
- CALLBACK_ONDETECTED_STREAM_COPY_ERROR,
- "Copy audio stream failure."));
+ try {
+ callback.onError(new HotwordDetectionServiceFailure(
+ CALLBACK_ONDETECTED_STREAM_COPY_ERROR,
+ "Copy audio stream failure."));
+ } catch (RemoteException e1) {
+ notifyOnDetectorRemoteException();
+ throw e1;
+ }
return;
}
- callback.onDetected(newResult, /* audioFormat= */ null,
- /* audioStream= */ null);
+ try {
+ callback.onDetected(newResult, /* audioFormat= */ null,
+ /* audioStream= */ null);
+ } catch (RemoteException e) {
+ notifyOnDetectorRemoteException();
+ throw e;
+ }
Slog.i(TAG, "Egressed "
+ HotwordDetectedResult.getUsageSize(newResult)
+ " bits from hotword trusted process");
@@ -567,6 +606,7 @@ abstract class DetectorSession {
mDestroyed = true;
mDebugHotwordLogging = false;
mRemoteDetectionService = null;
+ mRemoteExceptionListener = null;
if (mAttentionManagerInternal != null) {
mAttentionManagerInternal.onStopProximityUpdates(mProximityCallbackInternal);
}
@@ -595,6 +635,7 @@ abstract class DetectorSession {
HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_ON_ERROR_EXCEPTION,
mVoiceInteractionServiceUid);
}
+ notifyOnDetectorRemoteException();
}
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/DspTrustedHotwordDetectorSession.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/DspTrustedHotwordDetectorSession.java
index 63e0f466bb10..f9b5111f5348 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/DspTrustedHotwordDetectorSession.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/DspTrustedHotwordDetectorSession.java
@@ -16,6 +16,7 @@
package com.android.server.voiceinteraction;
+import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_ON_DETECTED_EXCEPTION;
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_ON_ERROR_EXCEPTION;
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_ON_PROCESS_RESTARTED_EXCEPTION;
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_ON_REJECTED_EXCEPTION;
@@ -42,6 +43,7 @@ import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IHotwordRecognitionStatusCallback;
+import com.android.server.voiceinteraction.VoiceInteractionManagerServiceImpl.DetectorRemoteExceptionListener;
import java.io.IOException;
import java.io.PrintWriter;
@@ -80,10 +82,11 @@ final class DspTrustedHotwordDetectorSession extends DetectorSession {
@NonNull Object lock, @NonNull Context context, @NonNull IBinder token,
@NonNull IHotwordRecognitionStatusCallback callback, int voiceInteractionServiceUid,
Identity voiceInteractorIdentity,
- @NonNull ScheduledExecutorService scheduledExecutorService, boolean logging) {
+ @NonNull ScheduledExecutorService scheduledExecutorService, boolean logging,
+ @NonNull DetectorRemoteExceptionListener listener) {
super(remoteHotwordDetectionService, lock, context, token, callback,
voiceInteractionServiceUid, voiceInteractorIdentity, scheduledExecutorService,
- logging);
+ logging, listener);
}
@SuppressWarnings("GuardedBy")
@@ -126,14 +129,23 @@ final class DspTrustedHotwordDetectorSession extends DetectorSession {
enforcePermissionsForDataDelivery();
enforceExtraKeyphraseIdNotLeaked(result, recognitionEvent);
} catch (SecurityException e) {
- Slog.i(TAG, "Ignoring #onDetected due to a SecurityException", e);
+ Slog.w(TAG, "Ignoring #onDetected due to a SecurityException", e);
HotwordMetricsLogger.writeKeyphraseTriggerEvent(
HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_DSP,
METRICS_KEYPHRASE_TRIGGERED_DETECT_SECURITY_EXCEPTION,
mVoiceInteractionServiceUid);
- externalCallback.onDetectionFailure(new HotwordDetectionServiceFailure(
- CALLBACK_ONDETECTED_GOT_SECURITY_EXCEPTION,
- "Security exception occurs in #onDetected method."));
+ try {
+ externalCallback.onDetectionFailure(new HotwordDetectionServiceFailure(
+ CALLBACK_ONDETECTED_GOT_SECURITY_EXCEPTION,
+ "Security exception occurs in #onDetected method."));
+ } catch (RemoteException e1) {
+ notifyOnDetectorRemoteException();
+ HotwordMetricsLogger.writeDetectorEvent(
+ HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_DSP,
+ HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_ON_ERROR_EXCEPTION,
+ mVoiceInteractionServiceUid);
+ throw e1;
+ }
return;
}
saveProximityValueToBundle(result);
@@ -141,14 +153,29 @@ final class DspTrustedHotwordDetectorSession extends DetectorSession {
try {
newResult = mHotwordAudioStreamCopier.startCopyingAudioStreams(result);
} catch (IOException e) {
- externalCallback.onDetectionFailure(new HotwordDetectionServiceFailure(
- CALLBACK_ONDETECTED_STREAM_COPY_ERROR,
- "Copy audio stream failure."));
+ try {
+ Slog.w(TAG, "Ignoring #onDetected due to a IOException", e);
+ externalCallback.onDetectionFailure(new HotwordDetectionServiceFailure(
+ CALLBACK_ONDETECTED_STREAM_COPY_ERROR,
+ "Copy audio stream failure."));
+ } catch (RemoteException e1) {
+ notifyOnDetectorRemoteException();
+ throw e1;
+ }
return;
}
- externalCallback.onKeyphraseDetected(recognitionEvent, newResult);
- Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(newResult)
- + " bits from hotword trusted process");
+ try {
+ externalCallback.onKeyphraseDetected(recognitionEvent, newResult);
+ Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(newResult)
+ + " bits from hotword trusted process");
+ } catch (RemoteException e) {
+ notifyOnDetectorRemoteException();
+ HotwordMetricsLogger.writeDetectorEvent(
+ HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_DSP,
+ HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_ON_DETECTED_EXCEPTION,
+ mVoiceInteractionServiceUid);
+ throw e;
+ }
if (mDebugHotwordLogging) {
Slog.i(TAG, "Egressed detected result: " + newResult);
}
@@ -180,7 +207,16 @@ final class DspTrustedHotwordDetectorSession extends DetectorSession {
return;
}
mValidatingDspTrigger = false;
- externalCallback.onRejected(result);
+ try {
+ externalCallback.onRejected(result);
+ } catch (RemoteException e) {
+ notifyOnDetectorRemoteException();
+ HotwordMetricsLogger.writeDetectorEvent(
+ HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_DSP,
+ HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_ON_REJECTED_EXCEPTION,
+ mVoiceInteractionServiceUid);
+ throw e;
+ }
mLastHotwordRejectedResult = result;
if (mDebugHotwordLogging && result != null) {
Slog.i(TAG, "Egressed rejected result: " + result);
@@ -215,6 +251,7 @@ final class DspTrustedHotwordDetectorSession extends DetectorSession {
HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_DSP,
HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_ON_ERROR_EXCEPTION,
mVoiceInteractionServiceUid);
+ notifyOnDetectorRemoteException();
}
},
MAX_VALIDATION_TIMEOUT_MILLIS,
@@ -247,6 +284,7 @@ final class DspTrustedHotwordDetectorSession extends DetectorSession {
HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_DSP,
HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_ON_REJECTED_EXCEPTION,
mVoiceInteractionServiceUid);
+ notifyOnDetectorRemoteException();
}
mValidatingDspTrigger = false;
}
@@ -260,6 +298,7 @@ final class DspTrustedHotwordDetectorSession extends DetectorSession {
HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_DSP,
HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_ON_PROCESS_RESTARTED_EXCEPTION,
mVoiceInteractionServiceUid);
+ notifyOnDetectorRemoteException();
}
mPerformingExternalSourceHotwordDetection = false;
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
index 1ba397529bbd..025e1dc78c86 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
@@ -30,7 +30,7 @@ import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPH
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.ChangeId;
-import android.compat.annotation.EnabledSince;
+import android.compat.annotation.Disabled;
import android.content.ComponentName;
import android.content.ContentCaptureOptions;
import android.content.Context;
@@ -41,7 +41,6 @@ import android.media.AudioFormat;
import android.media.AudioManagerInternal;
import android.media.permission.Identity;
import android.os.Binder;
-import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.IRemoteCallback;
@@ -69,6 +68,7 @@ import com.android.internal.app.IVisualQueryDetectionAttentionListener;
import com.android.internal.infra.ServiceConnector;
import com.android.server.LocalServices;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
+import com.android.server.voiceinteraction.VoiceInteractionManagerServiceImpl.DetectorRemoteExceptionListener;
import java.io.PrintWriter;
import java.time.Instant;
@@ -88,8 +88,7 @@ final class HotwordDetectionConnection {
static final boolean DEBUG = false;
/**
- * For apps targeting Android API Build.VERSION_CODES#UPSIDE_DOWN_CAKE and above,
- * implementors of the HotwordDetectionService must not augment the phrase IDs which are
+ * Implementors of the HotwordDetectionService must not augment the phrase IDs which are
* supplied via HotwordDetectionService
* #onDetect(AlwaysOnHotwordDetector.EventPayload, long, HotwordDetectionService.Callback).
*
@@ -103,7 +102,7 @@ final class HotwordDetectionConnection {
* </p>
*/
@ChangeId
- @EnabledSince(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Disabled
public static final long ENFORCE_HOTWORD_PHRASE_ID = 215066299L;
private static final String KEY_RESTART_PERIOD_IN_SECONDS = "restart_period_in_seconds";
@@ -147,6 +146,8 @@ final class HotwordDetectionConnection {
@GuardedBy("mLock")
private boolean mDebugHotwordLogging = false;
+ private DetectorRemoteExceptionListener mRemoteExceptionListener;
+
/**
* For multiple detectors feature, we only support one AlwaysOnHotwordDetector and one
* SoftwareHotwordDetector at the same time. We use SparseArray with detector type as the key
@@ -159,7 +160,8 @@ final class HotwordDetectionConnection {
HotwordDetectionConnection(Object lock, Context context, int voiceInteractionServiceUid,
Identity voiceInteractorIdentity, ComponentName hotwordDetectionServiceName,
ComponentName visualQueryDetectionServiceName, int userId,
- boolean bindInstantServiceAllowed, int detectorType) {
+ boolean bindInstantServiceAllowed, int detectorType,
+ DetectorRemoteExceptionListener listener) {
mLock = lock;
mContext = context;
mVoiceInteractionServiceUid = voiceInteractionServiceUid;
@@ -168,6 +170,7 @@ final class HotwordDetectionConnection {
mVisualQueryDetectionComponentName = visualQueryDetectionServiceName;
mUser = userId;
mDetectorType = detectorType;
+ mRemoteExceptionListener = listener;
mReStartPeriodSeconds = DeviceConfig.getInt(DeviceConfig.NAMESPACE_VOICE_INTERACTION,
KEY_RESTART_PERIOD_IN_SECONDS, 0);
@@ -251,6 +254,7 @@ final class HotwordDetectionConnection {
void cancelLocked() {
Slog.v(TAG, "cancelLocked");
clearDebugHotwordLoggingTimeoutLocked();
+ mRemoteExceptionListener = null;
runForEachDetectorSessionLocked((session) -> {
session.destroyLocked();
});
@@ -772,7 +776,8 @@ final class HotwordDetectionConnection {
}
session = new DspTrustedHotwordDetectorSession(mRemoteHotwordDetectionService,
mLock, mContext, token, callback, mVoiceInteractionServiceUid,
- mVoiceInteractorIdentity, mScheduledExecutorService, mDebugHotwordLogging);
+ mVoiceInteractorIdentity, mScheduledExecutorService, mDebugHotwordLogging,
+ mRemoteExceptionListener);
} else if (detectorType == HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) {
if (mRemoteVisualQueryDetectionService == null) {
mRemoteVisualQueryDetectionService =
@@ -781,7 +786,7 @@ final class HotwordDetectionConnection {
session = new VisualQueryDetectorSession(
mRemoteVisualQueryDetectionService, mLock, mContext, token, callback,
mVoiceInteractionServiceUid, mVoiceInteractorIdentity,
- mScheduledExecutorService, mDebugHotwordLogging);
+ mScheduledExecutorService, mDebugHotwordLogging, mRemoteExceptionListener);
} else {
if (mRemoteHotwordDetectionService == null) {
mRemoteHotwordDetectionService =
@@ -790,7 +795,7 @@ final class HotwordDetectionConnection {
session = new SoftwareTrustedHotwordDetectorSession(
mRemoteHotwordDetectionService, mLock, mContext, token, callback,
mVoiceInteractionServiceUid, mVoiceInteractorIdentity,
- mScheduledExecutorService, mDebugHotwordLogging);
+ mScheduledExecutorService, mDebugHotwordLogging, mRemoteExceptionListener);
}
mDetectorSessions.put(detectorType, session);
session.initialize(options, sharedMemory);
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoftwareTrustedHotwordDetectorSession.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/SoftwareTrustedHotwordDetectorSession.java
index 522d832c41bc..367fb8166b00 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoftwareTrustedHotwordDetectorSession.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/SoftwareTrustedHotwordDetectorSession.java
@@ -18,6 +18,8 @@ package com.android.server.voiceinteraction;
import static android.service.voice.HotwordDetectionService.AUDIO_SOURCE_MICROPHONE;
+import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_ON_DETECTED_EXCEPTION;
+import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_ON_ERROR_EXCEPTION;
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_ON_PROCESS_RESTARTED_EXCEPTION;
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__START_SOFTWARE_DETECTION;
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECTED;
@@ -43,6 +45,7 @@ import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IHotwordRecognitionStatusCallback;
+import com.android.server.voiceinteraction.VoiceInteractionManagerServiceImpl.DetectorRemoteExceptionListener;
import java.io.IOException;
import java.io.PrintWriter;
@@ -68,10 +71,11 @@ final class SoftwareTrustedHotwordDetectorSession extends DetectorSession {
@NonNull Object lock, @NonNull Context context, @NonNull IBinder token,
@NonNull IHotwordRecognitionStatusCallback callback, int voiceInteractionServiceUid,
Identity voiceInteractorIdentity,
- @NonNull ScheduledExecutorService scheduledExecutorService, boolean logging) {
+ @NonNull ScheduledExecutorService scheduledExecutorService, boolean logging,
+ @NonNull DetectorRemoteExceptionListener listener) {
super(remoteHotwordDetectionService, lock, context, token, callback,
voiceInteractionServiceUid, voiceInteractorIdentity, scheduledExecutorService,
- logging);
+ logging, listener);
}
@SuppressWarnings("GuardedBy")
@@ -118,13 +122,23 @@ final class SoftwareTrustedHotwordDetectorSession extends DetectorSession {
try {
enforcePermissionsForDataDelivery();
} catch (SecurityException e) {
+ Slog.w(TAG, "Ignoring #onDetected due to a SecurityException", e);
HotwordMetricsLogger.writeKeyphraseTriggerEvent(
HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE,
METRICS_KEYPHRASE_TRIGGERED_DETECT_SECURITY_EXCEPTION,
mVoiceInteractionServiceUid);
- mSoftwareCallback.onError(new HotwordDetectionServiceFailure(
- CALLBACK_ONDETECTED_GOT_SECURITY_EXCEPTION,
- "Security exception occurs in #onDetected method."));
+ try {
+ mSoftwareCallback.onError(new HotwordDetectionServiceFailure(
+ CALLBACK_ONDETECTED_GOT_SECURITY_EXCEPTION,
+ "Security exception occurs in #onDetected method."));
+ } catch (RemoteException e1) {
+ notifyOnDetectorRemoteException();
+ HotwordMetricsLogger.writeDetectorEvent(
+ HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE,
+ HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_ON_ERROR_EXCEPTION,
+ mVoiceInteractionServiceUid);
+ throw e1;
+ }
return;
}
saveProximityValueToBundle(result);
@@ -132,13 +146,32 @@ final class SoftwareTrustedHotwordDetectorSession extends DetectorSession {
try {
newResult = mHotwordAudioStreamCopier.startCopyingAudioStreams(result);
} catch (IOException e) {
+ Slog.w(TAG, "Ignoring #onDetected due to a IOException", e);
// TODO: Write event
- mSoftwareCallback.onError(new HotwordDetectionServiceFailure(
- CALLBACK_ONDETECTED_STREAM_COPY_ERROR,
- "Copy audio stream failure."));
+ try {
+ mSoftwareCallback.onError(new HotwordDetectionServiceFailure(
+ CALLBACK_ONDETECTED_STREAM_COPY_ERROR,
+ "Copy audio stream failure."));
+ } catch (RemoteException e1) {
+ notifyOnDetectorRemoteException();
+ HotwordMetricsLogger.writeDetectorEvent(
+ HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE,
+ HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_ON_ERROR_EXCEPTION,
+ mVoiceInteractionServiceUid);
+ throw e1;
+ }
return;
}
- mSoftwareCallback.onDetected(newResult, null, null);
+ try {
+ mSoftwareCallback.onDetected(newResult, null, null);
+ } catch (RemoteException e1) {
+ notifyOnDetectorRemoteException();
+ HotwordMetricsLogger.writeDetectorEvent(
+ HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE,
+ HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_ON_DETECTED_EXCEPTION,
+ mVoiceInteractionServiceUid);
+ throw e1;
+ }
Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(newResult)
+ " bits from hotword trusted process");
if (mDebugHotwordLogging) {
@@ -204,6 +237,7 @@ final class SoftwareTrustedHotwordDetectorSession extends DetectorSession {
HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE,
HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_ON_PROCESS_RESTARTED_EXCEPTION,
mVoiceInteractionServiceUid);
+ notifyOnDetectorRemoteException();
}
// Restart listening from microphone if the hotword process has been restarted.
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VisualQueryDetectorSession.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VisualQueryDetectorSession.java
index c397812b4158..afe5dab0b78b 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VisualQueryDetectorSession.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VisualQueryDetectorSession.java
@@ -38,6 +38,7 @@ import android.util.Slog;
import com.android.internal.app.IHotwordRecognitionStatusCallback;
import com.android.internal.app.IVisualQueryDetectionAttentionListener;
+import com.android.server.voiceinteraction.VoiceInteractionManagerServiceImpl.DetectorRemoteExceptionListener;
import java.io.PrintWriter;
import java.util.Objects;
@@ -64,13 +65,15 @@ final class VisualQueryDetectorSession extends DetectorSession {
@NonNull Object lock, @NonNull Context context, @NonNull IBinder token,
@NonNull IHotwordRecognitionStatusCallback callback, int voiceInteractionServiceUid,
Identity voiceInteractorIdentity,
- @NonNull ScheduledExecutorService scheduledExecutorService, boolean logging) {
+ @NonNull ScheduledExecutorService scheduledExecutorService, boolean logging,
+ @NonNull DetectorRemoteExceptionListener listener) {
super(remoteService, lock, context, token, callback,
voiceInteractionServiceUid, voiceInteractorIdentity, scheduledExecutorService,
- logging);
+ logging, listener);
mEgressingData = false;
mQueryStreaming = false;
mAttentionListener = null;
+ // TODO: handle notify RemoteException to client
}
@Override
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 96b69f8c4130..929e033315f7 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -743,7 +743,15 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
mHotwordDetectionConnection = new HotwordDetectionConnection(mServiceStub, mContext,
mInfo.getServiceInfo().applicationInfo.uid, voiceInteractorIdentity,
mHotwordDetectionComponentName, mVisualQueryDetectionComponentName, mUser,
- /* bindInstantServiceAllowed= */ false, detectorType);
+ /* bindInstantServiceAllowed= */ false, detectorType,
+ (token1, detectorType1) -> {
+ try {
+ mService.detectorRemoteExceptionOccurred(token1, detectorType1);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Fail to notify client detector remote "
+ + "exception occurred.");
+ }
+ });
} else if (detectorType != HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) {
// TODO: Logger events should be handled in session instead. Temporary adding the
// checking to prevent confusion so VisualQueryDetection events won't be logged if the
@@ -1080,4 +1088,8 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
// client always get the callback even if session is unexpectedly closed.
mServiceStub.setSessionWindowVisible(connection.mToken, false);
}
+
+ interface DetectorRemoteExceptionListener {
+ void onDetectorRemoteException(@NonNull IBinder token, int detectorType);
+ }
}
diff --git a/telecomm/java/android/telecom/CallControl.java b/telecomm/java/android/telecom/CallControl.java
index 2135e276e591..50f2ad4561cc 100644
--- a/telecomm/java/android/telecom/CallControl.java
+++ b/telecomm/java/android/telecom/CallControl.java
@@ -76,7 +76,10 @@ public final class CallControl {
}
/**
- * Request Telecom set the call state to active.
+ * Request Telecom set the call state to active. This method should be called when either an
+ * outgoing call is ready to go active or a held call is ready to go active again. For incoming
+ * calls that are ready to be answered, use
+ * {@link CallControl#answer(int, Executor, OutcomeReceiver)}.
*
* @param executor The {@link Executor} on which the {@link OutcomeReceiver} callback
* will be called on.
@@ -106,6 +109,43 @@ public final class CallControl {
}
/**
+ * Request Telecom answer an incoming call. For outgoing calls and calls that have been placed
+ * on hold, use {@link CallControl#setActive(Executor, OutcomeReceiver)}.
+ *
+ * @param videoState to report to Telecom. Telecom will store VideoState in the event another
+ * service/device requests it in order to continue the call on another screen.
+ * @param executor The {@link Executor} on which the {@link OutcomeReceiver} callback
+ * will be called on.
+ * @param callback that will be completed on the Telecom side that details success or failure
+ * of the requested operation.
+ *
+ * {@link OutcomeReceiver#onResult} will be called if Telecom has successfully
+ * switched the call state to active
+ *
+ * {@link OutcomeReceiver#onError} will be called if Telecom has failed to set
+ * the call state to active. A {@link CallException} will be passed
+ * that details why the operation failed.
+ */
+ public void answer(@android.telecom.CallAttributes.CallType int videoState,
+ @CallbackExecutor @NonNull Executor executor,
+ @NonNull OutcomeReceiver<Void, CallException> callback) {
+ validateVideoState(videoState);
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(callback);
+ if (mServerInterface != null) {
+ try {
+ mServerInterface.answer(videoState, mCallId,
+ new CallControlResultReceiver("answer", executor, callback));
+
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ } else {
+ throw new IllegalStateException(INTERFACE_ERROR_MSG);
+ }
+ }
+
+ /**
* Request Telecom set the call state to inactive. This the same as hold for two call endpoints
* but can be extended to setting a meeting to inactive.
*
@@ -147,10 +187,8 @@ public final class CallControl {
* <li>{@link DisconnectCause#REJECTED}</li>
* <li>{@link DisconnectCause#MISSED}</li>
* </ul>
- *
* @param executor The {@link Executor} on which the {@link OutcomeReceiver} callback
* will be called on.
- *
* @param callback That will be completed on the Telecom side that details success or
* failure of the requested operation.
*
@@ -254,6 +292,39 @@ public final class CallControl {
}
/**
+ * Raises an event to the {@link android.telecom.InCallService} implementations tracking this
+ * call via {@link android.telecom.Call.Callback#onConnectionEvent(Call, String, Bundle)}.
+ * These events and the associated extra keys for the {@code Bundle} parameter are mutually
+ * defined by a VoIP application and {@link android.telecom.InCallService}. This API is used to
+ * relay additional information about a call other than what is specified in the
+ * {@link android.telecom.CallAttributes} to {@link android.telecom.InCallService}s. This might
+ * include, for example, a change to the list of participants in a meeting, or the name of the
+ * speakers who have their hand raised. Where appropriate, the {@link InCallService}s tracking
+ * this call may choose to render this additional information about the call. An automotive
+ * calling UX, for example may have enough screen real estate to indicate the number of
+ * participants in a meeting, but to prevent distractions could suppress the list of
+ * participants.
+ *
+ * @param event a string event identifier agreed upon between a VoIP application and an
+ * {@link android.telecom.InCallService}
+ * @param extras a {@link android.os.Bundle} containing information about the event, as agreed
+ * upon between a VoIP application and {@link android.telecom.InCallService}.
+ */
+ public void sendEvent(@NonNull String event, @NonNull Bundle extras) {
+ Objects.requireNonNull(event);
+ Objects.requireNonNull(extras);
+ if (mServerInterface != null) {
+ try {
+ mServerInterface.sendEvent(mCallId, event, extras);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ } else {
+ throw new IllegalStateException(INTERFACE_ERROR_MSG);
+ }
+ }
+
+ /**
* Since {@link OutcomeReceiver}s cannot be passed via AIDL, a ResultReceiver (which can) must
* wrap the Clients {@link OutcomeReceiver} passed in and await for the Telecom Server side
* response in {@link ResultReceiver#onReceiveResult(int, Bundle)}.
@@ -315,4 +386,13 @@ public final class CallControl {
}
}
+ /** @hide */
+ private void validateVideoState(@android.telecom.CallAttributes.CallType int videoState) {
+ if (videoState != CallAttributes.AUDIO_CALL && videoState != CallAttributes.VIDEO_CALL) {
+ throw new IllegalArgumentException(TextUtils.formatSimple(
+ "The VideoState argument passed in, %d , is not a valid VideoState. The "
+ + "VideoState choices are limited to CallAttributes.AUDIO_CALL or"
+ + "CallAttributes.VIDEO_CALL", videoState));
+ }
+ }
}
diff --git a/telecomm/java/android/telecom/CallControlCallback.java b/telecomm/java/android/telecom/CallControlCallback.java
index aadf3370597c..35e2fd43efdd 100644
--- a/telecomm/java/android/telecom/CallControlCallback.java
+++ b/telecomm/java/android/telecom/CallControlCallback.java
@@ -75,24 +75,17 @@ public interface CallControlCallback {
@NonNull Consumer<Boolean> wasCompleted);
/**
- * Telecom is informing the client to reject the incoming call
- *
- * @param wasCompleted The {@link Consumer} to be completed. If the client can reject the
- * incoming call, {@link Consumer#accept(Object)} should be called with
- * {@link Boolean#TRUE}. Otherwise, {@link Consumer#accept(Object)}
- * should be called with {@link Boolean#FALSE}.
- */
- void onReject(@NonNull Consumer<Boolean> wasCompleted);
-
- /**
* Telecom is informing the client to disconnect the call
*
- * @param wasCompleted The {@link Consumer} to be completed. If the client can disconnect the
- * call on their end, {@link Consumer#accept(Object)} should be called with
- * {@link Boolean#TRUE}. Otherwise, {@link Consumer#accept(Object)}
- * should be called with {@link Boolean#FALSE}.
+ * @param disconnectCause represents the cause for disconnecting the call.
+ * @param wasCompleted The {@link Consumer} to be completed. If the client can disconnect
+ * the call on their end, {@link Consumer#accept(Object)} should be
+ * called with {@link Boolean#TRUE}. Otherwise,
+ * {@link Consumer#accept(Object)} should be called with
+ * {@link Boolean#FALSE}.
*/
- void onDisconnect(@NonNull Consumer<Boolean> wasCompleted);
+ void onDisconnect(@NonNull DisconnectCause disconnectCause,
+ @NonNull Consumer<Boolean> wasCompleted);
/**
* Telecom is informing the client to set the call in streaming.
diff --git a/telecomm/java/android/telecom/CallEventCallback.java b/telecomm/java/android/telecom/CallEventCallback.java
index bfe368560a22..a41c0113e933 100644
--- a/telecomm/java/android/telecom/CallEventCallback.java
+++ b/telecomm/java/android/telecom/CallEventCallback.java
@@ -17,6 +17,7 @@
package android.telecom;
import android.annotation.NonNull;
+import android.os.Bundle;
import java.util.List;
@@ -56,4 +57,20 @@ public interface CallEventCallback {
* @param reason Code to indicate the reason of this failure
*/
void onCallStreamingFailed(@CallStreamingService.StreamingFailedReason int reason);
+
+ /**
+ * Informs this {@link android.telecom.CallEventCallback} on events raised from a
+ * {@link android.telecom.InCallService} presenting this call. These events and the
+ * associated extra keys for the {@code Bundle} parameter are mutually defined by a VoIP
+ * application and {@link android.telecom.InCallService}. This enables alternative calling
+ * surfaces, such as an automotive UI, to relay requests to perform other non-standard call
+ * actions to the app. For example, an automotive calling solution may offer the ability for
+ * the user to raise their hand during a meeting.
+ *
+ * @param event a string event identifier agreed upon between a VoIP application and an
+ * {@link android.telecom.InCallService}
+ * @param extras a {@link android.os.Bundle} containing information about the event, as agreed
+ * upon between a VoIP application and {@link android.telecom.InCallService}.
+ */
+ void onEvent(@NonNull String event, @NonNull Bundle extras);
}
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index b6def1a22205..94c737d61b0a 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -1227,6 +1227,12 @@ public final class PhoneAccount implements Parcelable {
if (hasCapabilities(CAPABILITY_VOICE_CALLING_AVAILABLE)) {
sb.append("Voice ");
}
+ if (hasCapabilities(CAPABILITY_SUPPORTS_TRANSACTIONAL_OPERATIONS)) {
+ sb.append("TransactOps ");
+ }
+ if (hasCapabilities(CAPABILITY_SUPPORTS_CALL_STREAMING)) {
+ sb.append("Stream ");
+ }
return sb.toString();
}
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index de99ebf09e27..e39af5aa3327 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -895,9 +895,13 @@ public class TelecomManager {
"android.telecom.extra.NOTIFICATION_PHONE_NUMBER";
/**
- * The intent to clear missed calls.
+ * Included in the extras of the {@link #ACTION_SHOW_MISSED_CALLS_NOTIFICATION}, provides a
+ * pending intent which can be used to clear the missed calls notification and mark unread
+ * missed call log entries as read.
* @hide
+ * @deprecated Use {@link #cancelMissedCallsNotification()} instead.
*/
+ @Deprecated
@SystemApi
public static final String EXTRA_CLEAR_MISSED_CALLS_INTENT =
"android.telecom.extra.CLEAR_MISSED_CALLS_INTENT";
@@ -2073,6 +2077,14 @@ public class TelecomManager {
* {@link #getPhoneAccount}. Self-managed {@link ConnectionService}s must have
* {@link android.Manifest.permission#MANAGE_OWN_CALLS} to add a new incoming call.
* <p>
+ * Specify the address associated with the incoming call using
+ * {@link #EXTRA_INCOMING_CALL_ADDRESS}. If an incoming call is from an anonymous source, omit
+ * this extra and ensure you specify a valid number presentation via
+ * {@link Connection#setAddress(Uri, int)} on the {@link Connection} instance you return in
+ * your
+ * {@link ConnectionService#onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)}
+ * implementation.
+ * <p>
* The incoming call you are adding is assumed to have a video state of
* {@link VideoProfile#STATE_AUDIO_ONLY}, unless the extra value
* {@link #EXTRA_INCOMING_VIDEO_STATE} is specified.
@@ -2254,9 +2266,10 @@ public class TelecomManager {
}
/**
- * Removes the missed-call notification if one is present.
+ * Removes the missed-call notification if one is present and marks missed calls in the call
+ * log as read.
* <p>
- * Requires that the method-caller be set as the system dialer app.
+ * Requires that the method-caller be set as the default dialer app.
* </p>
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
diff --git a/telecomm/java/com/android/internal/telecom/ClientTransactionalServiceWrapper.java b/telecomm/java/com/android/internal/telecom/ClientTransactionalServiceWrapper.java
index 7bba1eb07ebd..71e9184b7c54 100644
--- a/telecomm/java/com/android/internal/telecom/ClientTransactionalServiceWrapper.java
+++ b/telecomm/java/com/android/internal/telecom/ClientTransactionalServiceWrapper.java
@@ -19,6 +19,7 @@ package com.android.internal.telecom;
import static android.telecom.TelecomManager.TELECOM_TRANSACTION_SUCCESS;
import android.os.Binder;
+import android.os.Bundle;
import android.os.OutcomeReceiver;
import android.os.ResultReceiver;
import android.telecom.CallAttributes;
@@ -27,6 +28,7 @@ import android.telecom.CallControlCallback;
import android.telecom.CallEndpoint;
import android.telecom.CallEventCallback;
import android.telecom.CallException;
+import android.telecom.DisconnectCause;
import android.telecom.PhoneAccountHandle;
import android.text.TextUtils;
import android.util.Log;
@@ -141,17 +143,17 @@ public class ClientTransactionalServiceWrapper {
private static final String ON_SET_ACTIVE = "onSetActive";
private static final String ON_SET_INACTIVE = "onSetInactive";
private static final String ON_ANSWER = "onAnswer";
- private static final String ON_REJECT = "onReject";
private static final String ON_DISCONNECT = "onDisconnect";
private static final String ON_STREAMING_STARTED = "onStreamingStarted";
private static final String ON_REQ_ENDPOINT_CHANGE = "onRequestEndpointChange";
private static final String ON_AVAILABLE_CALL_ENDPOINTS = "onAvailableCallEndpointsChanged";
private static final String ON_MUTE_STATE_CHANGED = "onMuteStateChanged";
private static final String ON_CALL_STREAMING_FAILED = "onCallStreamingFailed";
+ private static final String ON_EVENT = "onEvent";
- private void handleHandshakeCallback(String action, String callId, int code,
- ResultReceiver ackResultReceiver) {
- Log.i(TAG, TextUtils.formatSimple("hHC: id=[%s], action=[%s]", callId, action));
+ private void handleCallEventCallback(String action, String callId,
+ ResultReceiver ackResultReceiver, Object... args) {
+ Log.i(TAG, TextUtils.formatSimple("hCEC: id=[%s], action=[%s]", callId, action));
// lookup the callEventCallback associated with the particular call
TransactionalCall call = mCallIdToTransactionalCall.get(callId);
@@ -172,16 +174,13 @@ public class ClientTransactionalServiceWrapper {
case ON_SET_INACTIVE:
callback.onSetInactive(outcomeReceiverWrapper);
break;
- case ON_REJECT:
- callback.onReject(outcomeReceiverWrapper);
- untrackCall(callId);
- break;
case ON_DISCONNECT:
- callback.onDisconnect(outcomeReceiverWrapper);
+ callback.onDisconnect((DisconnectCause) args[0],
+ outcomeReceiverWrapper);
untrackCall(callId);
break;
case ON_ANSWER:
- callback.onAnswer(code, outcomeReceiverWrapper);
+ callback.onAnswer((int) args[0], outcomeReceiverWrapper);
break;
case ON_STREAMING_STARTED:
callback.onCallStreamingStarted(outcomeReceiverWrapper);
@@ -229,28 +228,23 @@ public class ClientTransactionalServiceWrapper {
@Override
public void onSetActive(String callId, ResultReceiver resultReceiver) {
- handleHandshakeCallback(ON_SET_ACTIVE, callId, 0, resultReceiver);
+ handleCallEventCallback(ON_SET_ACTIVE, callId, resultReceiver);
}
-
@Override
public void onSetInactive(String callId, ResultReceiver resultReceiver) {
- handleHandshakeCallback(ON_SET_INACTIVE, callId, 0, resultReceiver);
+ handleCallEventCallback(ON_SET_INACTIVE, callId, resultReceiver);
}
@Override
public void onAnswer(String callId, int videoState, ResultReceiver resultReceiver) {
- handleHandshakeCallback(ON_ANSWER, callId, videoState, resultReceiver);
- }
-
- @Override
- public void onReject(String callId, ResultReceiver resultReceiver) {
- handleHandshakeCallback(ON_REJECT, callId, 0, resultReceiver);
+ handleCallEventCallback(ON_ANSWER, callId, resultReceiver, videoState);
}
@Override
- public void onDisconnect(String callId, ResultReceiver resultReceiver) {
- handleHandshakeCallback(ON_DISCONNECT, callId, 0, resultReceiver);
+ public void onDisconnect(String callId, DisconnectCause cause,
+ ResultReceiver resultReceiver) {
+ handleCallEventCallback(ON_DISCONNECT, callId, resultReceiver, cause);
}
@Override
@@ -306,7 +300,7 @@ public class ClientTransactionalServiceWrapper {
@Override
public void onCallStreamingStarted(String callId, ResultReceiver resultReceiver) {
- handleHandshakeCallback(ON_STREAMING_STARTED, callId, 0, resultReceiver);
+ handleCallEventCallback(ON_STREAMING_STARTED, callId, resultReceiver);
}
@Override
@@ -314,5 +308,23 @@ public class ClientTransactionalServiceWrapper {
Log.i(TAG, TextUtils.formatSimple("oCSF: id=[%s], reason=[%s]", callId, reason));
handleEventCallback(callId, ON_CALL_STREAMING_FAILED, reason);
}
+
+ @Override
+ public void onEvent(String callId, String event, Bundle extras) {
+ // lookup the callEventCallback associated with the particular call
+ TransactionalCall call = mCallIdToTransactionalCall.get(callId);
+ if (call != null) {
+ CallEventCallback callback = call.getCallStateCallback();
+ Executor executor = call.getExecutor();
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> {
+ callback.onEvent(event, extras);
+ });
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ }
};
}
diff --git a/telecomm/java/com/android/internal/telecom/ICallControl.aidl b/telecomm/java/com/android/internal/telecom/ICallControl.aidl
index b78a77ec9756..5e2c923e4c9c 100644
--- a/telecomm/java/com/android/internal/telecom/ICallControl.aidl
+++ b/telecomm/java/com/android/internal/telecom/ICallControl.aidl
@@ -16,6 +16,7 @@
package com.android.internal.telecom;
+import android.os.Bundle;
import android.telecom.CallControl;
import android.telecom.CallEndpoint;
import android.telecom.DisconnectCause;
@@ -26,8 +27,10 @@ import android.os.ResultReceiver;
*/
oneway interface ICallControl {
void setActive(String callId, in ResultReceiver callback);
+ void answer(int videoState, String callId, in ResultReceiver callback);
void setInactive(String callId, in ResultReceiver callback);
void disconnect(String callId, in DisconnectCause disconnectCause, in ResultReceiver callback);
void startCallStreaming(String callId, in ResultReceiver callback);
void requestCallEndpointChange(in CallEndpoint callEndpoint, in ResultReceiver callback);
+ void sendEvent(String callId, String event, in Bundle extras);
} \ No newline at end of file
diff --git a/telecomm/java/com/android/internal/telecom/ICallEventCallback.aidl b/telecomm/java/com/android/internal/telecom/ICallEventCallback.aidl
index fef5e9e47dc5..213cafbbf188 100644
--- a/telecomm/java/com/android/internal/telecom/ICallEventCallback.aidl
+++ b/telecomm/java/com/android/internal/telecom/ICallEventCallback.aidl
@@ -16,12 +16,14 @@
package com.android.internal.telecom;
+import android.os.Bundle;
import android.telecom.CallControl;
import android.telecom.CallEndpoint;
import com.android.internal.telecom.ICallControl;
import android.os.ResultReceiver;
import android.telecom.CallAudioState;
import android.telecom.CallException;
+import android.telecom.DisconnectCause;
import java.util.List;
/**
@@ -35,8 +37,7 @@ oneway interface ICallEventCallback {
void onSetActive(String callId, in ResultReceiver callback);
void onSetInactive(String callId, in ResultReceiver callback);
void onAnswer(String callId, int videoState, in ResultReceiver callback);
- void onReject(String callId, in ResultReceiver callback);
- void onDisconnect(String callId, in ResultReceiver callback);
+ void onDisconnect(String callId, in DisconnectCause cause, in ResultReceiver callback);
// -- Streaming related. Client registered call streaming capabilities should override
void onCallStreamingStarted(String callId, in ResultReceiver callback);
void onCallStreamingFailed(String callId, int reason);
@@ -44,6 +45,8 @@ oneway interface ICallEventCallback {
void onCallEndpointChanged(String callId, in CallEndpoint endpoint);
void onAvailableCallEndpointsChanged(String callId, in List<CallEndpoint> endpoint);
void onMuteStateChanged(String callId, boolean isMuted);
+ // -- Events
+ void onEvent(String callId, String event, in Bundle extras);
// hidden methods that help with cleanup
void removeCallFromTransactionalServiceWrapper(String callId);
} \ No newline at end of file
diff --git a/telephony/java/android/service/euicc/EuiccProfileInfo.java b/telephony/java/android/service/euicc/EuiccProfileInfo.java
index 7eccd1a4482f..728dfa64090c 100644
--- a/telephony/java/android/service/euicc/EuiccProfileInfo.java
+++ b/telephony/java/android/service/euicc/EuiccProfileInfo.java
@@ -24,6 +24,7 @@ import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.service.carrier.CarrierIdentifier;
+import android.telephony.SubscriptionInfo;
import android.telephony.UiccAccessRule;
import android.text.TextUtils;
@@ -451,6 +452,8 @@ public final class EuiccProfileInfo implements Parcelable {
+ mPolicyRules
+ ", accessRules="
+ Arrays.toString(mAccessRules)
+ + ", iccid="
+ + SubscriptionInfo.givePrintableIccid(mIccid)
+ ")";
}
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 77af95619492..918ae7901dbe 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -537,10 +537,9 @@ public class CarrierConfigManager {
/**
* CDMA activation goes through OTASP.
- * <p>
- * TODO: This should be combined with config_use_hfa_for_provisioning and implemented as an enum
- * (NONE, HFA, OTASP).
*/
+ // TODO: This should be combined with config_use_hfa_for_provisioning and implemented as an enum
+ // (NONE, HFA, OTASP).
public static final String KEY_USE_OTASP_FOR_PROVISIONING_BOOL =
"use_otasp_for_provisioning_bool";
diff --git a/telephony/java/android/telephony/DomainSelectionService.java b/telephony/java/android/telephony/DomainSelectionService.java
index c352f2bc3f83..abcce5f61aee 100644
--- a/telephony/java/android/telephony/DomainSelectionService.java
+++ b/telephony/java/android/telephony/DomainSelectionService.java
@@ -537,9 +537,9 @@ public class DomainSelectionService extends Service {
}
@Override
- public void onWlanSelected() {
+ public void onWlanSelected(boolean useEmergencyPdn) {
try {
- mCallback.onWlanSelected();
+ mCallback.onWlanSelected(useEmergencyPdn);
} catch (Exception e) {
Rlog.e(TAG, "onWlanSelected e=" + e);
}
@@ -702,9 +702,10 @@ public class DomainSelectionService extends Service {
}
@Override
- public void onDomainSelected(@NetworkRegistrationInfo.Domain int domain) {
+ public void onDomainSelected(@NetworkRegistrationInfo.Domain int domain,
+ boolean useEmergencyPdn) {
try {
- mCallback.onDomainSelected(domain);
+ mCallback.onDomainSelected(domain, useEmergencyPdn);
} catch (Exception e) {
Rlog.e(TAG, "onDomainSelected e=" + e);
}
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index b9008c4ecd81..788d0e88170d 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -1526,7 +1526,7 @@ public class PhoneNumberUtils {
* Formats the specified {@code phoneNumber} to the E.164 representation.
*
* @param phoneNumber the phone number to format.
- * @param defaultCountryIso the ISO 3166-1 two letters country code.
+ * @param defaultCountryIso the ISO 3166-1 two letters country code in UPPER CASE.
* @return the E.164 representation, or null if the given phone number is not valid.
*/
public static String formatNumberToE164(String phoneNumber, String defaultCountryIso) {
@@ -1537,7 +1537,7 @@ public class PhoneNumberUtils {
* Formats the specified {@code phoneNumber} to the RFC3966 representation.
*
* @param phoneNumber the phone number to format.
- * @param defaultCountryIso the ISO 3166-1 two letters country code.
+ * @param defaultCountryIso the ISO 3166-1 two letters country code in UPPER CASE.
* @return the RFC3966 representation, or null if the given phone number is not valid.
*/
public static String formatNumberToRFC3966(String phoneNumber, String defaultCountryIso) {
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index b418a02aed60..758372adab1d 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -3964,7 +3964,12 @@ public class SubscriptionManager {
/** @hide */
public static void invalidateActiveDataSubIdCaches() {
- PropertyInvalidatedCache.invalidateCache(CACHE_KEY_ACTIVE_DATA_SUB_ID_PROPERTY);
+ if (isSubscriptionManagerServiceEnabled()) {
+ PropertyInvalidatedCache.invalidateCache(
+ CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY);
+ } else {
+ PropertyInvalidatedCache.invalidateCache(CACHE_KEY_ACTIVE_DATA_SUB_ID_PROPERTY);
+ }
}
/** @hide */
@@ -4401,7 +4406,6 @@ public class SubscriptionManager {
*
* @throws IllegalArgumentException if subscription is invalid.
* @throws SecurityException if the caller doesn't have permissions required.
- * @throws IllegalStateException if subscription service is not available.
*
* @hide
*/
@@ -4418,8 +4422,7 @@ public class SubscriptionManager {
if (iSub != null) {
return iSub.getSubscriptionUserHandle(subscriptionId);
} else {
- throw new IllegalStateException("[getSubscriptionUserHandle]: "
- + "subscription service unavailable");
+ Log.e(LOG_TAG, "[getSubscriptionUserHandle]: subscription service unavailable");
}
} catch (RemoteException ex) {
ex.rethrowAsRuntimeException();
diff --git a/telephony/java/android/telephony/TransportSelectorCallback.java b/telephony/java/android/telephony/TransportSelectorCallback.java
index d39679072d37..04752e418466 100644
--- a/telephony/java/android/telephony/TransportSelectorCallback.java
+++ b/telephony/java/android/telephony/TransportSelectorCallback.java
@@ -35,8 +35,10 @@ public interface TransportSelectorCallback {
/**
* Notify that WLAN transport has been selected.
+ *
+ * @param useEmergencyPdn Indicates whether Wi-Fi emergency services use emergency PDN or not.
*/
- void onWlanSelected();
+ void onWlanSelected(boolean useEmergencyPdn);
/**
* Notify that WWAN transport has been selected.
diff --git a/telephony/java/android/telephony/WwanSelectorCallback.java b/telephony/java/android/telephony/WwanSelectorCallback.java
index b3682caa4eb3..f9c2620cfaf8 100644
--- a/telephony/java/android/telephony/WwanSelectorCallback.java
+++ b/telephony/java/android/telephony/WwanSelectorCallback.java
@@ -46,6 +46,7 @@ public interface WwanSelectorCallback {
* this interface can be discarded.
*
* @param domain The selected domain.
+ * @param useEmergencyPdn Indicates whether emergency services use emergency PDN or not.
*/
- void onDomainSelected(@NetworkRegistrationInfo.Domain int domain);
+ void onDomainSelected(@NetworkRegistrationInfo.Domain int domain, boolean useEmergencyPdn);
}
diff --git a/telephony/java/android/telephony/ims/ImsCallSession.java b/telephony/java/android/telephony/ims/ImsCallSession.java
index 98ed1fa5ddeb..ecd703960d08 100755
--- a/telephony/java/android/telephony/ims/ImsCallSession.java
+++ b/telephony/java/android/telephony/ims/ImsCallSession.java
@@ -584,6 +584,7 @@ public class ImsCallSession {
* Gets the call ID of the session.
*
* @return the call ID
+ * If null is returned for getCallId, then that means that the call ID has not been set yet.
*/
public String getCallId() {
if (mClosed) {
@@ -1779,7 +1780,7 @@ public class ImsCallSession {
sb.append("[ImsCallSession objId:");
sb.append(System.identityHashCode(this));
sb.append(" callId:");
- sb.append(getCallId());
+ sb.append(mCallId != null ? mCallId : "[UNINITIALIZED]");
sb.append("]");
return sb.toString();
}
diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java
index 174675fcde4c..a8fb36b591fa 100644
--- a/telephony/java/android/telephony/ims/feature/ImsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java
@@ -342,8 +342,8 @@ public abstract class ImsFeature {
/**
* @return The SIM slot index associated with this ImsFeature.
*
- * @see SubscriptionManager#getSubscriptionIds(int) for more information on getting the
- * subscription IDs associated with this slot.
+ * @see SubscriptionManager#getSubscriptionId(int) for more information on getting the
+ * subscription ID associated with this slot.
* @hide
*/
@SystemApi
diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java
index 3009bec06a93..64454cc50a5c 100644
--- a/telephony/java/android/telephony/satellite/SatelliteManager.java
+++ b/telephony/java/android/telephony/satellite/SatelliteManager.java
@@ -166,8 +166,8 @@ public class SatelliteManager {
public static final String KEY_SATELLITE_NEXT_VISIBILITY = "satellite_next_visibility";
/**
- * Bundle key to get the respoonse from
- * {@link #sendSatelliteDatagram(long, int, SatelliteDatagram, Executor, OutcomeReceiver)}.
+ * Bundle key to get the respoonse from {@link
+ * #sendSatelliteDatagram(long, int, SatelliteDatagram, boolean, Executor, OutcomeReceiver)}.
* @hide
*/
public static final String KEY_SEND_SATELLITE_DATAGRAM = "send_satellite_datagram";
@@ -615,9 +615,7 @@ public class SatelliteManager {
/**
* The default state indicating that datagram transfer is idle.
- * This should be sent immediately after either
- * {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_SUCCESS} or
- * {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_FAILED}.
+ * This should be sent if there are no message transfer activity happening.
*/
public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE = 0;
/**
@@ -625,25 +623,41 @@ public class SatelliteManager {
*/
public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING = 1;
/**
+ * An end state indicating that datagram sending completed successfully.
+ * After datagram transfer completes, {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE}
+ * will be sent if no more messages are pending.
+ */
+ public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS = 2;
+ /**
+ * An end state indicating that datagram sending completed with a failure.
+ * After datagram transfer completes, {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE}
+ * must be sent before reporting any additional datagram transfer state changes. All pending
+ * messages will be reported as failed, to the corresponding applications.
+ */
+ public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED = 3;
+ /**
* A transition state indicating that a datagram is being received.
*/
- public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING = 2;
+ public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING = 4;
/**
- * A transition state indicating that datagram transfer is being retried.
+ * An end state indicating that datagram receiving completed successfully.
+ * After datagram transfer completes, {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE}
+ * will be sent if no more messages are pending.
*/
- public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_RETRYING = 3;
+ public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS = 5;
/**
- * An end state indicating that datagram transfer completed successfully.
+ * An end state indicating that datagram receive operation found that there are no
+ * messages to be retrieved from the satellite.
* After datagram transfer completes, {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE}
- * must be sent before reporting any additional datagram transfer state changes.
+ * will be sent if no more messages are pending.
*/
- public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_SUCCESS = 4;
+ public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_NONE = 6;
/**
- * An end state indicating that datagram transfer completed with a failure.
+ * An end state indicating that datagram receive completed with a failure.
* After datagram transfer completes, {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE}
- * must be sent before reporting any additional datagram transfer state changes.
+ * will be sent if no more messages are pending.
*/
- public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_FAILED = 5;
+ public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED = 7;
/**
* The datagram transfer state is unknown. This generic datagram transfer state should be used
* only when the datagram transfer state cannot be mapped to other specific datagram transfer
@@ -655,10 +669,12 @@ public class SatelliteManager {
@IntDef(prefix = {"SATELLITE_DATAGRAM_TRANSFER_STATE_"}, value = {
SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED,
SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING,
- SATELLITE_DATAGRAM_TRANSFER_STATE_RETRYING,
- SATELLITE_DATAGRAM_TRANSFER_STATE_SUCCESS,
- SATELLITE_DATAGRAM_TRANSFER_STATE_FAILED,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_NONE,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED,
SATELLITE_DATAGRAM_TRANSFER_STATE_UNKNOWN
})
@Retention(RetentionPolicy.SOURCE)
@@ -685,6 +701,10 @@ public class SatelliteManager {
*/
public static final int SATELLITE_MODEM_STATE_OFF = 4;
/**
+ * Satellite modem is unavailable.
+ */
+ public static final int SATELLITE_MODEM_STATE_UNAVAILABLE = 5;
+ /**
* Satellite modem state is unknown. This generic modem state should be used only when the
* modem state cannot be mapped to other specific modem states.
*/
@@ -697,6 +717,7 @@ public class SatelliteManager {
SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING,
SATELLITE_MODEM_STATE_DATAGRAM_RETRYING,
SATELLITE_MODEM_STATE_OFF,
+ SATELLITE_MODEM_STATE_UNAVAILABLE,
SATELLITE_MODEM_STATE_UNKNOWN
})
@Retention(RetentionPolicy.SOURCE)
@@ -733,9 +754,6 @@ public class SatelliteManager {
* All other results indicate that this operation failed.
* Once satellite position updates begin, datagram transfer state updates will be sent
* through {@link SatellitePositionUpdateCallback}.
- * Modem should report any changes in datagram transfer state and indicate success or failure
- * by reporting {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_SUCCESS} or
- * {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_FAILED}.
*
* @param executor The executor on which the callback and error code listener will be called.
* @param errorCodeListener Listener for the {@link SatelliteError} result of the operation.
@@ -1255,6 +1273,15 @@ public class SatelliteManager {
* SOS_SMS or LOCATION_SHARING.
* @param datagram encoded gateway datagram which is encrypted by the caller.
* Datagram will be passed down to modem without any encoding or encryption.
+ * @param needFullScreenPointingUI If set to true, this indicates pointingUI app to open in full
+ * screen mode if satellite communication needs pointingUI.
+ * If this is set to false, pointingUI may be presented to the
+ * user in collapsed view. Application may decide to mark this
+ * flag as true when the user is sending data for the first time
+ * or whenever there is a considerable idle time between
+ * satellite activity. This decision should be done based upon
+ * user activity and the application's ability to determine the
+ * best possible UX experience for the user.
* @param executor The executor on which the result listener will be called.
* @param callback The callback object to which the result will be returned.
* If datagram is sent successfully, then
@@ -1267,7 +1294,8 @@ public class SatelliteManager {
*/
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
public void sendSatelliteDatagram(long datagramId, @DatagramType int datagramType,
- @NonNull SatelliteDatagram datagram, @NonNull @CallbackExecutor Executor executor,
+ @NonNull SatelliteDatagram datagram, boolean needFullScreenPointingUI,
+ @NonNull @CallbackExecutor Executor executor,
@NonNull OutcomeReceiver<Long, SatelliteException> callback) {
Objects.requireNonNull(datagram);
Objects.requireNonNull(executor);
@@ -1299,7 +1327,7 @@ public class SatelliteManager {
}
};
telephony.sendSatelliteDatagram(mSubId, datagramId, datagramType, datagram,
- receiver);
+ needFullScreenPointingUI, receiver);
} else {
throw new IllegalStateException("telephony service is null.");
}
diff --git a/telephony/java/android/telephony/satellite/stub/ISatellite.aidl b/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
index 5dc1a6529151..d93ee217c2fb 100644
--- a/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
+++ b/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
@@ -31,7 +31,6 @@ oneway interface ISatellite {
* Register the callback interface with satellite service.
*
* @param listener The callback interface to handle satellite service indications.
- * @param errorCallback The callback to receive the error code result of the operation.
*
* Valid error codes returned:
* SatelliteError:ERROR_NONE
@@ -43,7 +42,7 @@ oneway interface ISatellite {
* SatelliteError:REQUEST_NOT_SUPPORTED
* SatelliteError:NO_RESOURCES
*/
- void setSatelliteListener(in ISatelliteListener listener, in IIntegerConsumer errorCallback);
+ void setSatelliteListener(in ISatelliteListener listener);
/**
* Request to enable or disable the satellite service listening mode.
@@ -51,6 +50,8 @@ oneway interface ISatellite {
*
* @param enable True to enable satellite listening mode and false to disable.
* @param isDemoMode Whether demo mode is enabled.
+ * @param timeout How long the satellite modem should wait for the next incoming page before
+ * disabling listening mode.
* @param errorCallback The callback to receive the error code result of the operation.
*
* Valid error codes returned:
@@ -63,7 +64,7 @@ oneway interface ISatellite {
* SatelliteError:REQUEST_NOT_SUPPORTED
* SatelliteError:NO_RESOURCES
*/
- void requestSatelliteListeningEnabled(in boolean enable, in boolean isDemoMode,
+ void requestSatelliteListeningEnabled(in boolean enable, in boolean isDemoMode, in int timeout,
in IIntegerConsumer errorCallback);
/**
diff --git a/telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl b/telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl
index e24e892e5b55..d9668687e6e6 100644
--- a/telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl
+++ b/telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl
@@ -36,10 +36,10 @@ oneway interface ISatelliteListener {
/**
* Indicates that new datagrams have been received on the device.
*
- * @param datagrams Array of new datagrams received.
- * @param pendingCount The number of datagrams that are pending.
+ * @param datagram New datagram that was received.
+ * @param pendingCount Number of additional datagrams yet to be received.
*/
- void onSatelliteDatagramsReceived(in SatelliteDatagram[] datagrams, in int pendingCount);
+ void onSatelliteDatagramReceived(in SatelliteDatagram datagram, in int pendingCount);
/**
* Indicates that the satellite has pending datagrams for the device to be pulled.
diff --git a/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java b/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java
index df5143243812..711dcbe3f62b 100644
--- a/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java
+++ b/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java
@@ -63,19 +63,19 @@ public class SatelliteImplBase extends SatelliteService {
private final IBinder mBinder = new ISatellite.Stub() {
@Override
- public void setSatelliteListener(ISatelliteListener listener,
- IIntegerConsumer errorCallback) throws RemoteException {
+ public void setSatelliteListener(ISatelliteListener listener) throws RemoteException {
executeMethodAsync(
- () -> SatelliteImplBase.this.setSatelliteListener(listener, errorCallback),
+ () -> SatelliteImplBase.this.setSatelliteListener(listener),
"setSatelliteListener");
}
@Override
public void requestSatelliteListeningEnabled(boolean enable, boolean isDemoMode,
- IIntegerConsumer errorCallback) throws RemoteException {
+ int timeout, IIntegerConsumer errorCallback) throws RemoteException {
executeMethodAsync(
() -> SatelliteImplBase.this
- .requestSatelliteListeningEnabled(enable, isDemoMode, errorCallback),
+ .requestSatelliteListeningEnabled(
+ enable, isDemoMode, timeout, errorCallback),
"requestSatelliteListeningEnabled");
}
@@ -229,7 +229,6 @@ public class SatelliteImplBase extends SatelliteService {
* Register the callback interface with satellite service.
*
* @param listener The callback interface to handle satellite service indications.
- * @param errorCallback The callback to receive the error code result of the operation.
*
* Valid error codes returned:
* SatelliteError:ERROR_NONE
@@ -241,8 +240,7 @@ public class SatelliteImplBase extends SatelliteService {
* SatelliteError:REQUEST_NOT_SUPPORTED
* SatelliteError:NO_RESOURCES
*/
- public void setSatelliteListener(@NonNull ISatelliteListener listener,
- @NonNull IIntegerConsumer errorCallback) {
+ public void setSatelliteListener(@NonNull ISatelliteListener listener) {
// stub implementation
}
@@ -252,6 +250,8 @@ public class SatelliteImplBase extends SatelliteService {
*
* @param enable True to enable satellite listening mode and false to disable.
* @param isDemoMode Whether demo mode is enabled.
+ * @param timeout How long the satellite modem should wait for the next incoming page before
+ * disabling listening mode.
* @param errorCallback The callback to receive the error code result of the operation.
*
* Valid error codes returned:
@@ -264,7 +264,7 @@ public class SatelliteImplBase extends SatelliteService {
* SatelliteError:REQUEST_NOT_SUPPORTED
* SatelliteError:NO_RESOURCES
*/
- public void requestSatelliteListeningEnabled(boolean enable, boolean isDemoMode,
+ public void requestSatelliteListeningEnabled(boolean enable, boolean isDemoMode, int timeout,
@NonNull IIntegerConsumer errorCallback) {
// stub implementation
}
diff --git a/telephony/java/android/telephony/satellite/stub/SatelliteModemState.aidl b/telephony/java/android/telephony/satellite/stub/SatelliteModemState.aidl
index 5ee7f9abdcf1..e4f94134caa1 100644
--- a/telephony/java/android/telephony/satellite/stub/SatelliteModemState.aidl
+++ b/telephony/java/android/telephony/satellite/stub/SatelliteModemState.aidl
@@ -42,6 +42,10 @@ enum SatelliteModemState {
*/
SATELLITE_MODEM_STATE_OFF = 4,
/**
+ * Satellite modem is unavailable.
+ */
+ SATELLITE_MODEM_STATE_UNAVAILABLE = 5,
+ /**
* Satellite modem state is unknown. This generic modem state should be used only when the
* modem state cannot be mapped to other specific modem states.
*/
diff --git a/telephony/java/android/telephony/satellite/stub/SatelliteService.java b/telephony/java/android/telephony/satellite/stub/SatelliteService.java
index 3861c5bc8de3..5b96e34186e9 100644
--- a/telephony/java/android/telephony/satellite/stub/SatelliteService.java
+++ b/telephony/java/android/telephony/satellite/stub/SatelliteService.java
@@ -20,7 +20,8 @@ import android.annotation.SdkConstant;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
-import android.util.Log;
+
+import com.android.telephony.Rlog;
/**
* Main SatelliteService implementation, which binds via the Telephony SatelliteServiceController.
@@ -44,7 +45,7 @@ import android.util.Log;
* @hide
*/
public class SatelliteService extends Service {
- public static final String TAG = "SatelliteService";
+ private static final String TAG = "SatelliteService";
@SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
public static final String SERVICE_INTERFACE = "android.telephony.satellite.SatelliteService";
@@ -55,7 +56,7 @@ public class SatelliteService extends Service {
@Override
public IBinder onBind(Intent intent) {
if (SERVICE_INTERFACE.equals(intent.getAction())) {
- Log.e(TAG, "SatelliteService bound");
+ Rlog.d(TAG, "SatelliteService bound");
return new SatelliteImplBase(Runnable::run).getBinder();
}
return null;
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index f4801c2f002f..ef9dc3e3621d 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -2938,13 +2938,16 @@ interface ITelephony {
* @param datagramId An id that uniquely identifies datagram requested to be sent.
* @param datagramType Type of datagram.
* @param datagram Datagram to send over satellite.
+ * @param needFullScreenPointingUI this is used to indicate pointingUI app to open in
+ * full screen mode.
* @param receiver Result receiver to get the datagramId if datagram is sent successfully else
* error code of the request.
*/
@JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+ "android.Manifest.permission.SATELLITE_COMMUNICATION)")
void sendSatelliteDatagram(int subId, long datagramId, int datagramType,
- in SatelliteDatagram datagram, in ResultReceiver receiver);
+ in SatelliteDatagram datagram, in boolean needFullScreenPointingUI,
+ in ResultReceiver receiver);
/**
* Request to get whether satellite communication is allowed for the current location.
diff --git a/telephony/java/com/android/internal/telephony/ITransportSelectorCallback.aidl b/telephony/java/com/android/internal/telephony/ITransportSelectorCallback.aidl
index aca83f4edbd7..6777256d171e 100644
--- a/telephony/java/com/android/internal/telephony/ITransportSelectorCallback.aidl
+++ b/telephony/java/com/android/internal/telephony/ITransportSelectorCallback.aidl
@@ -22,7 +22,7 @@ import com.android.internal.telephony.IWwanSelectorCallback;
interface ITransportSelectorCallback {
oneway void onCreated(in IDomainSelector selector);
- oneway void onWlanSelected();
+ oneway void onWlanSelected(boolean useEmergencyPdn);
IWwanSelectorCallback onWwanSelected();
oneway void onWwanSelectedAsync(in ITransportSelectorResultCallback cb);
oneway void onSelectionTerminated(int cause);
diff --git a/telephony/java/com/android/internal/telephony/IWwanSelectorCallback.aidl b/telephony/java/com/android/internal/telephony/IWwanSelectorCallback.aidl
index 339fbee91812..94e7c871066e 100644
--- a/telephony/java/com/android/internal/telephony/IWwanSelectorCallback.aidl
+++ b/telephony/java/com/android/internal/telephony/IWwanSelectorCallback.aidl
@@ -21,6 +21,6 @@ import com.android.internal.telephony.IWwanSelectorResultCallback;
oneway interface IWwanSelectorCallback {
void onRequestEmergencyNetworkScan(in int[] preferredNetworks,
int scanType, in IWwanSelectorResultCallback cb);
- void onDomainSelected(int domain);
+ void onDomainSelected(int domain, boolean useEmergencyPdn);
void onCancel();
}
diff --git a/test-mock/api/current.txt b/test-mock/api/current.txt
index c5169e502344..d1a68d4e9cb2 100644
--- a/test-mock/api/current.txt
+++ b/test-mock/api/current.txt
@@ -235,7 +235,6 @@ package android.test.mock {
method @Deprecated public android.content.Intent getLaunchIntentForPackage(String);
method @Deprecated public android.content.Intent getLeanbackLaunchIntentForPackage(String);
method @Deprecated public String getNameForUid(int);
- method @Deprecated public android.content.pm.PackageInfo getPackageArchiveInfo(String, int);
method @Deprecated public int[] getPackageGids(String) throws android.content.pm.PackageManager.NameNotFoundException;
method @Deprecated public int[] getPackageGids(String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method @Deprecated public android.content.pm.PackageInfo getPackageInfo(String, int) throws android.content.pm.PackageManager.NameNotFoundException;
diff --git a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
index 90ddb6ffb34a..d2a6bf288be4 100644
--- a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
+++ b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
@@ -31,6 +31,7 @@ import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -299,6 +300,8 @@ public final class BackgroundDexOptServiceIntegrationTests {
// Test that background dexopt under low storage conditions downgrades unused packages.
@Test
+ @Ignore("b/251438180: This test has been failing for a long time; temporarily disable it while"
+ + " we investigate this issue.")
public void testBackgroundDexOptDowngradeSuccessful() throws IOException {
// Should be more than DOWNGRADE_AFTER_DAYS.
long deltaDays = DOWNGRADE_AFTER_DAYS + 1;
diff --git a/tests/EnforcePermission/OWNERS b/tests/EnforcePermission/OWNERS
new file mode 100644
index 000000000000..39550a394f33
--- /dev/null
+++ b/tests/EnforcePermission/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 315013
+tweek@google.com
+brufino@google.com
diff --git a/tests/FlickerTests/Android.bp b/tests/FlickerTests/Android.bp
index 855d3c1f4ea7..fef521163399 100644
--- a/tests/FlickerTests/Android.bp
+++ b/tests/FlickerTests/Android.bp
@@ -42,6 +42,8 @@ android_test {
"androidx.test.ext.junit",
"flickertestapplib",
"flickerlib",
+ "flickerlib-apphelpers",
+ "flickerlib-helpers",
"truth-prebuilt",
"launcher-helper-lib",
"launcher-aosp-tapl",
@@ -65,6 +67,7 @@ java_library {
],
static_libs: [
"flickerlib",
+ "flickerlib-helpers",
"truth-prebuilt",
"app-helpers-core",
],
@@ -80,8 +83,10 @@ java_library {
"**/helpers/*",
],
static_libs: [
- "flickerlib",
"flickertestapplib",
+ "flickerlib",
+ "flickerlib-apphelpers",
+ "flickerlib-helpers",
"truth-prebuilt",
"app-helpers-core",
"wm-flicker-window-extensions",
diff --git a/tests/FlickerTests/AndroidTest.xml b/tests/FlickerTests/AndroidTest.xml
index 707b522c7024..f2ffc19f2a4e 100644
--- a/tests/FlickerTests/AndroidTest.xml
+++ b/tests/FlickerTests/AndroidTest.xml
@@ -24,7 +24,11 @@
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
<option name="run-command" value="settings put secure show_ime_with_hard_keyboard 1" />
+ <option name="run-command" value="settings put system show_touches 1" />
+ <option name="run-command" value="settings put system pointer_location 1" />
<option name="teardown-command" value="settings delete secure show_ime_with_hard_keyboard" />
+ <option name="teardown-command" value="settings delete system show_touches" />
+ <option name="teardown-command" value="settings delete system pointer_location" />
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true"/>
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
index 87bfdebec8e5..4e3ae0c0752a 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
@@ -18,11 +18,13 @@ package com.android.server.wm.flicker
import android.app.Instrumentation
import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerBuilderProvider
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
import android.util.Log
import androidx.test.platform.app.InstrumentationRegistry
import com.android.launcher3.tapl.LauncherInstrumentation
-import com.android.server.wm.flicker.junit.FlickerBuilderProvider
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
import org.junit.Assume
import org.junit.AssumptionViolatedException
import org.junit.Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
index e3dc6999ceb7..9c3460c124ba 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
@@ -18,12 +18,13 @@
package com.android.server.wm.flicker
-import com.android.server.wm.flicker.helpers.WindowUtils
-import com.android.server.wm.flicker.traces.region.RegionSubject
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.component.matchers.IComponentNameMatcher
-import com.android.server.wm.traces.common.service.PlatformConsts
-import com.android.server.wm.traces.common.windowmanager.WindowManagerTrace
+import android.tools.common.PlatformConsts
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.datatypes.component.IComponentNameMatcher
+import android.tools.common.flicker.subject.region.RegionSubject
+import android.tools.common.traces.wm.WindowManagerTrace
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.helpers.WindowUtils
/**
* Checks that [ComponentNameMatcher.STATUS_BAR] window is visible and above the app windows in all
@@ -208,7 +209,7 @@ fun FlickerTest.statusBarLayerPositionAtStart(
wmTrace: WindowManagerTrace? = this.reader.readWmTrace()
) {
// collect navbar position for the equivalent WM state
- val state = wmTrace?.firstOrNull() ?: error("WM state missing in $this")
+ val state = wmTrace?.entries?.firstOrNull() ?: error("WM state missing in $this")
val display = state.getDisplay(PlatformConsts.DEFAULT_DISPLAY) ?: error("Display not found")
val navBarPosition = WindowUtils.getExpectedStatusBarPosition(display)
assertLayersStart {
@@ -224,7 +225,7 @@ fun FlickerTest.statusBarLayerPositionAtEnd(
wmTrace: WindowManagerTrace? = this.reader.readWmTrace()
) {
// collect navbar position for the equivalent WM state
- val state = wmTrace?.lastOrNull() ?: error("WM state missing in $this")
+ val state = wmTrace?.entries?.lastOrNull() ?: error("WM state missing in $this")
val display = state.getDisplay(PlatformConsts.DEFAULT_DISPLAY) ?: error("Display not found")
val navBarPosition = WindowUtils.getExpectedStatusBarPosition(display)
assertLayersEnd {
@@ -257,7 +258,7 @@ fun FlickerTest.snapshotStartingWindowLayerCoversExactlyOnApp(component: ICompon
if (snapshotLayers.isNotEmpty()) {
val visibleAreas =
snapshotLayers
- .mapNotNull { snapshotLayer -> snapshotLayer.layer?.visibleRegion }
+ .mapNotNull { snapshotLayer -> snapshotLayer.layer.visibleRegion }
.toTypedArray()
val snapshotRegion = RegionSubject(visibleAreas, this, timestamp)
val appVisibleRegion = it.visibleRegion(component)
@@ -316,7 +317,8 @@ fun FlickerTest.replacesLayer(
assertion.then().isVisible(ComponentNameMatcher.SNAPSHOT, isOptional = true)
}
if (ignoreSplashscreen) {
- assertion.then().isSplashScreenVisibleFor(newLayer, isOptional = true)
+ assertion.then().isSplashScreenVisibleFor(
+ ComponentNameMatcher(newLayer.packageName, className = ""), isOptional = true)
}
assertion.then().isVisible(newLayer)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/ActivityEmbeddingTestBase.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/ActivityEmbeddingTestBase.kt
index b7bdeeb7d834..7ef4d939fee2 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/ActivityEmbeddingTestBase.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/ActivityEmbeddingTestBase.kt
@@ -16,8 +16,8 @@
package com.android.server.wm.flicker.activityembedding
+import android.tools.device.flicker.legacy.FlickerTest
import com.android.server.wm.flicker.BaseTest
-import com.android.server.wm.flicker.FlickerTest
import com.android.server.wm.flicker.helpers.ActivityEmbeddingAppHelper
import org.junit.Before
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingPlaceholderSplitTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingPlaceholderSplitTest.kt
index 7f2e057febf1..ed17059e79e7 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingPlaceholderSplitTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingPlaceholderSplitTest.kt
@@ -17,12 +17,12 @@
package com.android.server.wm.flicker.activityembedding
import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
import com.android.server.wm.flicker.helpers.ActivityEmbeddingAppHelper
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingSecondaryToSplitTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingSecondaryToSplitTest.kt
index 20259a7d4485..c3cbb84fd37f 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingSecondaryToSplitTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingSecondaryToSplitTest.kt
@@ -17,13 +17,13 @@
package com.android.server.wm.flicker.activityembedding
import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
import com.android.server.wm.flicker.helpers.ActivityEmbeddingAppHelper
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -59,14 +59,12 @@ class OpenActivityEmbeddingSecondaryToSplitTest(flicker: FlickerTest) :
@Presubmit
@Test
fun mainActivityWindowIsAlwaysVisible() {
- flicker.assertWm {
- isAppWindowVisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
- }
+ flicker.assertWm { isAppWindowVisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) }
}
/**
- * Main activity surface is animated from fullscreen to ActivityEmbedding split.
- * During the transition, there is a period of time that it is covered by a snapshot of itself.
+ * Main activity surface is animated from fullscreen to ActivityEmbedding split. During the
+ * transition, there is a period of time that it is covered by a snapshot of itself.
*/
@Presubmit
@Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
index dba588a55c20..5dc2dd7d93a8 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
@@ -17,12 +17,12 @@
package com.android.server.wm.flicker.close
import android.platform.test.annotations.FlakyTest
+import android.tools.device.flicker.annotation.FlickerServiceCompatible
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.annotation.FlickerServiceCompatible
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTestCfArm.kt
index 86f52d5d362e..9fa840190fbf 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTestCfArm.kt
@@ -16,10 +16,10 @@
package com.android.server.wm.flicker.close
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.annotation.FlickerServiceCompatible
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.annotation.FlickerServiceCompatible
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
index 4d2b86a00524..b042a14b30da 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
@@ -17,12 +17,12 @@
package com.android.server.wm.flicker.close
import android.platform.test.annotations.FlakyTest
+import android.tools.device.flicker.annotation.FlickerServiceCompatible
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.annotation.FlickerServiceCompatible
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTestCfArm.kt
index 470764214665..136995a78fd7 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTestCfArm.kt
@@ -16,10 +16,10 @@
package com.android.server.wm.flicker.close
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.annotation.FlickerServiceCompatible
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.annotation.FlickerServiceCompatible
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt
index 4d72729b368d..c4628aaa90af 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt
@@ -17,14 +17,14 @@
package com.android.server.wm.flicker.close
import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher.Companion.LAUNCHER
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
import com.android.server.wm.flicker.BaseTest
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
import com.android.server.wm.flicker.helpers.SimpleAppHelper
-import com.android.server.wm.flicker.helpers.StandardAppHelper
import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.flicker.replacesLayer
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher.Companion.LAUNCHER
import org.junit.Test
/** Base test class for transitions that close an app back to the launcher screen */
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt
index 65d0fa991ae7..e531bc06fb3d 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt
@@ -17,6 +17,12 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.wm.WindowManagerState.Companion.STATE_RESUMED
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.helpers.FIND_TIMEOUT
+import android.tools.device.traces.parsers.WindowManagerStateHelper
+import android.tools.device.traces.parsers.toFlickerComponent
import android.util.Log
import androidx.test.uiautomator.By
import androidx.test.uiautomator.Until
@@ -24,10 +30,6 @@ import androidx.window.extensions.WindowExtensions
import androidx.window.extensions.WindowExtensionsProvider
import androidx.window.extensions.embedding.ActivityEmbeddingComponent
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.windowmanager.WindowManagerState.Companion.STATE_RESUMED
-import com.android.server.wm.traces.parser.toFlickerComponent
-import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
import org.junit.Assume.assumeNotNull
class ActivityEmbeddingAppHelper
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/AppPairsHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/AppPairsHelper.kt
index 73018a05bb58..afb9fbf47350 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/AppPairsHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/AppPairsHelper.kt
@@ -17,7 +17,8 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
class AppPairsHelper(
instrumentation: Instrumentation,
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/AssistantAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/AssistantAppHelper.kt
index 18563ffbc0b7..7aea05d0ce9b 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/AssistantAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/AssistantAppHelper.kt
@@ -19,6 +19,7 @@ package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
import android.content.ComponentName
import android.provider.Settings
+import android.tools.device.helpers.FIND_TIMEOUT
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.Until
@@ -31,10 +32,10 @@ constructor(
val instr: Instrumentation,
val component: ComponentName = ActivityOptions.ASSISTANT_SERVICE_COMPONENT_NAME,
) {
- protected val uiDevice: UiDevice = UiDevice.getInstance(instr)
- protected val defaultAssistant: String? =
+ private val uiDevice: UiDevice = UiDevice.getInstance(instr)
+ private val defaultAssistant: String? =
Settings.Secure.getString(instr.targetContext.contentResolver, Settings.Secure.ASSISTANT)
- protected val defaultVoiceInteractionService: String? =
+ private val defaultVoiceInteractionService: String? =
Settings.Secure.getString(
instr.targetContext.contentResolver,
Settings.Secure.VOICE_INTERACTION_SERVICE
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FixedOrientationAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FixedOrientationAppHelper.kt
index cdf7ae5fbce3..47dd4e9fb32d 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FixedOrientationAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FixedOrientationAppHelper.kt
@@ -17,9 +17,10 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.traces.parsers.toFlickerComponent
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.parser.toFlickerComponent
class FixedOrientationAppHelper
@JvmOverloads
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerExtensions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerExtensions.kt
index 2ae8e1d4932a..9227e07f5b11 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerExtensions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerExtensions.kt
@@ -18,16 +18,16 @@
package com.android.server.wm.flicker.helpers
-import com.android.server.wm.flicker.IFlickerTestData
-import com.android.server.wm.flicker.rules.ChangeDisplayOrientationRule
-import com.android.server.wm.traces.common.service.PlatformConsts
+import android.tools.common.Rotation
+import android.tools.device.flicker.legacy.IFlickerTestData
+import android.tools.device.flicker.rules.ChangeDisplayOrientationRule
/**
* Changes the device [rotation] and wait for the rotation animation to complete
*
* @param rotation New device rotation
*/
-fun IFlickerTestData.setRotation(rotation: PlatformConsts.Rotation) =
+fun IFlickerTestData.setRotation(rotation: Rotation) =
ChangeDisplayOrientationRule.setRotation(
rotation,
instrumentation,
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt
index f5aed411ed87..79c048a14e84 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt
@@ -17,13 +17,14 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.traces.parsers.WindowManagerStateHelper
+import android.tools.device.traces.parsers.toFlickerComponent
import androidx.test.uiautomator.By
import androidx.test.uiautomator.Direction
import androidx.test.uiautomator.Until
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.parser.toFlickerComponent
-import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
class GameAppHelper
@JvmOverloads
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt
index a433b152ce73..73effbde4515 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt
@@ -17,12 +17,14 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.helpers.FIND_TIMEOUT
+import android.tools.device.traces.parsers.WindowManagerStateHelper
+import android.tools.device.traces.parsers.toFlickerComponent
import androidx.test.uiautomator.By
import androidx.test.uiautomator.Until
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.parser.toFlickerComponent
-import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
open class ImeAppHelper
@JvmOverloads
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeEditorPopupDialogAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeEditorPopupDialogAppHelper.kt
index fb0242e8e679..a6e57d5641d6 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeEditorPopupDialogAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeEditorPopupDialogAppHelper.kt
@@ -17,12 +17,13 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.helpers.FIND_TIMEOUT
+import android.tools.device.traces.parsers.WindowManagerStateHelper
+import android.tools.device.traces.parsers.toFlickerComponent
import androidx.test.uiautomator.By
import androidx.test.uiautomator.Until
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.parser.toFlickerComponent
-import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
class ImeEditorPopupDialogAppHelper
@JvmOverloads
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeShownOnAppStartHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeShownOnAppStartHelper.kt
index fb04b32a7bf7..d61a500e3293 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeShownOnAppStartHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeShownOnAppStartHelper.kt
@@ -17,26 +17,28 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.datatypes.component.IComponentMatcher
+import android.tools.common.traces.Condition
+import android.tools.common.traces.DeviceStateDump
+import android.tools.device.helpers.FIND_TIMEOUT
+import android.tools.device.helpers.IME_PACKAGE
+import android.tools.device.traces.parsers.WindowManagerStateHelper
+import android.tools.device.traces.parsers.toFlickerComponent
import android.view.WindowInsets.Type.ime
import android.view.WindowInsets.Type.navigationBars
import android.view.WindowInsets.Type.statusBars
import androidx.test.uiautomator.By
import androidx.test.uiautomator.Until
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.Condition
-import com.android.server.wm.traces.common.DeviceStateDump
-import com.android.server.wm.traces.common.component.matchers.IComponentMatcher
-import com.android.server.wm.traces.common.service.PlatformConsts
-import com.android.server.wm.traces.parser.toFlickerComponent
-import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
import java.util.regex.Pattern
class ImeShownOnAppStartHelper
@JvmOverloads
constructor(
instr: Instrumentation,
- private val rotation: PlatformConsts.Rotation,
+ private val rotation: Rotation,
private val imePackageName: String = IME_PACKAGE,
launcherName: String = ActivityOptions.Ime.AutoFocusActivity.LABEL,
component: ComponentNameMatcher =
@@ -55,7 +57,12 @@ constructor(
waitConditions: Array<Condition<DeviceStateDump>>
) {
super.launchViaIntent(
- wmHelper, launchedAppComponentMatcherOverride, action, stringExtras, waitConditions)
+ wmHelper,
+ launchedAppComponentMatcherOverride,
+ action,
+ stringExtras,
+ waitConditions
+ )
waitIMEShown(wmHelper)
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeStateInitializeHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeStateInitializeHelper.kt
index 8a25e36394d2..fb5e1d2da26b 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeStateInitializeHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeStateInitializeHelper.kt
@@ -17,9 +17,10 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.traces.parsers.toFlickerComponent
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.parser.toFlickerComponent
class ImeStateInitializeHelper
@JvmOverloads
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/LaunchBubbleHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/LaunchBubbleHelper.kt
index ba8dabd4dfec..b95d86b72f34 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/LaunchBubbleHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/LaunchBubbleHelper.kt
@@ -17,8 +17,9 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.traces.parsers.toFlickerComponent
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.parser.toFlickerComponent
class LaunchBubbleHelper(instrumentation: Instrumentation) :
StandardAppHelper(
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MailAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MailAppHelper.kt
index d6ed24a6e4af..ab916858858a 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MailAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MailAppHelper.kt
@@ -17,13 +17,15 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.helpers.FIND_TIMEOUT
+import android.tools.device.traces.parsers.toFlickerComponent
import androidx.test.uiautomator.By
import androidx.test.uiautomator.Direction
import androidx.test.uiautomator.UiObject2
import androidx.test.uiautomator.Until
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.parser.toFlickerComponent
class MailAppHelper
@JvmOverloads
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MultiWindowUtils.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MultiWindowUtils.kt
index ae4223251683..e93e9c8e9bfb 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MultiWindowUtils.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MultiWindowUtils.kt
@@ -19,9 +19,10 @@ package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
import android.content.Context
import android.provider.Settings
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
import android.util.Log
import com.android.compatibility.common.util.SystemUtil
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
import java.io.IOException
class MultiWindowUtils(
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NewTasksAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NewTasksAppHelper.kt
index 5c1eca32bbec..c547ad06fe6c 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NewTasksAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NewTasksAppHelper.kt
@@ -17,13 +17,15 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.helpers.FIND_TIMEOUT
+import android.tools.device.traces.parsers.WindowManagerStateHelper
+import android.tools.device.traces.parsers.toFlickerComponent
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.Until
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.parser.toFlickerComponent
-import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
class NewTasksAppHelper
@JvmOverloads
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NonResizeableAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NonResizeableAppHelper.kt
index 58da2d84a5ba..20ee3b9d236d 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NonResizeableAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NonResizeableAppHelper.kt
@@ -17,9 +17,10 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.traces.parsers.toFlickerComponent
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.parser.toFlickerComponent
class NonResizeableAppHelper
@JvmOverloads
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt
index d7f083031ec6..78f8bcf70b60 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt
@@ -17,12 +17,14 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.helpers.FIND_TIMEOUT
+import android.tools.device.traces.parsers.WindowManagerStateHelper
+import android.tools.device.traces.parsers.toFlickerComponent
import androidx.test.uiautomator.By
import androidx.test.uiautomator.Until
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.parser.toFlickerComponent
-import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
class NotificationAppHelper
@JvmOverloads
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
index 0c8589d6515f..0e852b6c84ff 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
@@ -19,17 +19,19 @@ package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
import android.media.session.MediaController
import android.media.session.MediaSessionManager
+import android.tools.common.datatypes.Rect
+import android.tools.common.datatypes.Region
+import android.tools.common.datatypes.component.IComponentMatcher
+import android.tools.common.traces.ConditionsFactory
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.helpers.FIND_TIMEOUT
+import android.tools.device.helpers.SYSTEMUI_PACKAGE
+import android.tools.device.traces.parsers.WindowManagerStateHelper
+import android.tools.device.traces.parsers.toFlickerComponent
import android.util.Log
import androidx.test.uiautomator.By
import androidx.test.uiautomator.Until
-import com.android.server.wm.flicker.helpers.GestureHelper.Tuple
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.Rect
-import com.android.server.wm.traces.common.WindowManagerConditionsFactory
-import com.android.server.wm.traces.common.component.matchers.IComponentMatcher
-import com.android.server.wm.traces.common.region.Region
-import com.android.server.wm.traces.parser.toFlickerComponent
-import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
open class PipAppHelper(instrumentation: Instrumentation) :
StandardAppHelper(
@@ -93,10 +95,10 @@ open class PipAppHelper(instrumentation: Instrumentation) :
// if the distance per step is less than 1, carry out the animation in two steps
gestureHelper.pinch(
- Tuple(initLeftX, yCoord),
- Tuple(initRightX, yCoord),
- Tuple(finalLeftX, yCoord),
- Tuple(finalRightX, yCoord),
+ GestureHelper.Tuple(initLeftX, yCoord),
+ GestureHelper.Tuple(initRightX, yCoord),
+ GestureHelper.Tuple(finalLeftX, yCoord),
+ GestureHelper.Tuple(finalRightX, yCoord),
adjustedSteps
)
@@ -141,10 +143,10 @@ open class PipAppHelper(instrumentation: Instrumentation) :
// if the distance per step is less than 1, carry out the animation in two steps
gestureHelper.pinch(
- Tuple(initLeftX, yCoord),
- Tuple(initRightX, yCoord),
- Tuple(finalLeftX, yCoord),
- Tuple(finalRightX, yCoord),
+ GestureHelper.Tuple(initLeftX, yCoord),
+ GestureHelper.Tuple(initRightX, yCoord),
+ GestureHelper.Tuple(finalLeftX, yCoord),
+ GestureHelper.Tuple(finalRightX, yCoord),
adjustedSteps
)
@@ -167,7 +169,7 @@ open class PipAppHelper(instrumentation: Instrumentation) :
launchedAppComponentMatcherOverride,
action,
stringExtras,
- waitConditions = arrayOf(WindowManagerConditionsFactory.hasPipWindow())
+ waitConditions = arrayOf(ConditionsFactory.hasPipWindow())
)
wmHelper.StateSyncBuilder().withPipShown().waitForAndVerify()
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SeamlessRotationAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SeamlessRotationAppHelper.kt
index 8f54000a96d3..06e668ea07a1 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SeamlessRotationAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SeamlessRotationAppHelper.kt
@@ -17,9 +17,10 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.traces.parsers.toFlickerComponent
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.parser.toFlickerComponent
class SeamlessRotationAppHelper
@JvmOverloads
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt
index 61dabfc422a1..94c90dabd2c8 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt
@@ -17,9 +17,10 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.traces.parsers.toFlickerComponent
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.parser.toFlickerComponent
class ShowWhenLockedAppHelper
@JvmOverloads
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SimpleAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SimpleAppHelper.kt
index 9ed9d28efd36..64af811d1c4f 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SimpleAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SimpleAppHelper.kt
@@ -17,9 +17,10 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.traces.parsers.toFlickerComponent
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.parser.toFlickerComponent
class SimpleAppHelper
@JvmOverloads
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/TwoActivitiesAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/TwoActivitiesAppHelper.kt
index 8f7049acbe07..316766a5c3f3 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/TwoActivitiesAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/TwoActivitiesAppHelper.kt
@@ -17,13 +17,15 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.helpers.FIND_TIMEOUT
+import android.tools.device.traces.parsers.WindowManagerStateHelper
+import android.tools.device.traces.parsers.toFlickerComponent
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.Until
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.parser.toFlickerComponent
-import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
class TwoActivitiesAppHelper
@JvmOverloads
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt
index 092a4fd8a10a..c23cf34be60a 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt
@@ -17,16 +17,16 @@
package com.android.server.wm.flicker.ime
import android.platform.test.annotations.Presubmit
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.flicker.subject.region.RegionSubject
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.BaseTest
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
import com.android.server.wm.flicker.helpers.ImeEditorPopupDialogAppHelper
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.flicker.traces.region.RegionSubject
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.service.PlatformConsts
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -86,9 +86,7 @@ class CloseImeOnDismissPopupDialogTest(flicker: FlickerTest) : BaseTest(flicker)
if (imeSnapshotLayers.isNotEmpty()) {
val visibleAreas =
imeSnapshotLayers
- .mapNotNull { imeSnapshotLayer ->
- imeSnapshotLayer.layer?.visibleRegion
- }
+ .mapNotNull { imeSnapshotLayer -> imeSnapshotLayer.layer.visibleRegion }
.toTypedArray()
val imeVisibleRegion = RegionSubject(visibleAreas, this, timestamp)
val appVisibleRegion = it.visibleRegion(imeTestApp)
@@ -105,7 +103,7 @@ class CloseImeOnDismissPopupDialogTest(flicker: FlickerTest) : BaseTest(flicker)
@JvmStatic
fun getParams(): Collection<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt
index 0870cec9ecab..823328af57aa 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt
@@ -18,15 +18,15 @@ package com.android.server.wm.flicker.ime
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Presubmit
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.BaseTest
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
import com.android.server.wm.flicker.helpers.ImeAppHelper
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.service.PlatformConsts
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -117,7 +117,7 @@ open class CloseImeOnGoHomeTest(flicker: FlickerTest) : BaseTest(flicker) {
@JvmStatic
fun getParams(): Collection<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTestCfArm.kt
index 96b23bc01a79..0fe52df5bb25 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTestCfArm.kt
@@ -16,8 +16,8 @@
package com.android.server.wm.flicker.ime
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt
index 48dbf25cb5b5..a4e4b6f40867 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt
@@ -17,15 +17,15 @@
package com.android.server.wm.flicker.ime
import android.platform.test.annotations.Presubmit
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.BaseTest
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.service.PlatformConsts
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -96,7 +96,7 @@ open class CloseImeShownOnAppStartOnGoHomeTest(flicker: FlickerTest) : BaseTest(
fun getParams(): Collection<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
// b/190352379 (IME doesn't show on app launch in 90 degrees)
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTestCfArm.kt
index ed5d3096d039..5aacb3011e79 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTestCfArm.kt
@@ -16,8 +16,8 @@
package com.android.server.wm.flicker.ime
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt
index 7b935ff344a7..e85da1f09772 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt
@@ -17,15 +17,15 @@
package com.android.server.wm.flicker.ime
import android.platform.test.annotations.Presubmit
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.BaseTest
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.service.PlatformConsts
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -90,7 +90,7 @@ open class CloseImeShownOnAppStartToAppOnPressBackTest(flicker: FlickerTest) : B
fun getParams(): Collection<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
// b/190352379 (IME doesn't show on app launch in 90 degrees)
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTestCfArm.kt
index 0a899914a35d..eb81aed35011 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTestCfArm.kt
@@ -16,8 +16,8 @@
package com.android.server.wm.flicker.ime
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt
index 1a0c95958a29..1b4d6ad4422f 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt
@@ -19,15 +19,15 @@ package com.android.server.wm.flicker.ime
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.BaseTest
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
import com.android.server.wm.flicker.helpers.ImeAppHelper
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.navBarLayerPositionAtStartAndEnd
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
import org.junit.Assume
import org.junit.FixMethodOrder
import org.junit.Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTestCfArm.kt
index 37e8c6baf677..db1440b0c5b8 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTestCfArm.kt
@@ -16,8 +16,8 @@
package com.android.server.wm.flicker.ime
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt
index 0b7b165aaad6..e2d6dbf428f9 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt
@@ -19,16 +19,16 @@ package com.android.server.wm.flicker.ime
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Presubmit
+import android.tools.common.Rotation
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.BaseTest
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
import com.android.server.wm.flicker.helpers.ImeAppHelper
import com.android.server.wm.flicker.helpers.SimpleAppHelper
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.service.PlatformConsts
import org.junit.Assume
import org.junit.FixMethodOrder
import org.junit.Test
@@ -93,7 +93,7 @@ open class CloseImeToHomeOnFinishActivityTest(flicker: FlickerTest) : BaseTest(f
@JvmStatic
fun getParams(): Collection<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTestCfArm.kt
index 116bc1bf6f20..405ab6bcd9d6 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTestCfArm.kt
@@ -16,8 +16,8 @@
package com.android.server.wm.flicker.ime
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
index dcffa4785f6d..579c10f62f52 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
@@ -18,8 +18,8 @@
package com.android.server.wm.flicker.ime
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.legacy.FlickerTest
fun FlickerTest.imeLayerBecomesVisible() {
assertLayers {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToFixedPortraitAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToFixedPortraitAppTest.kt
index defb43755841..3a8db45ab767 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToFixedPortraitAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToFixedPortraitAppTest.kt
@@ -16,17 +16,18 @@
package com.android.server.wm.flicker.ime
import android.platform.test.annotations.Postsubmit
+import android.tools.common.NavBar
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.flicker.subject.region.RegionSubject
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.helpers.WindowUtils
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.BaseTest
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper
-import com.android.server.wm.flicker.helpers.WindowUtils
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.flicker.traces.region.RegionSubject
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.service.PlatformConsts
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -107,10 +108,9 @@ class OpenImeWindowToFixedPortraitAppTest(flicker: FlickerTest) : BaseTest(flick
return FlickerTestFactory.nonRotationTests(
supportedRotations =
listOf(
- PlatformConsts.Rotation.ROTATION_90,
+ Rotation.ROTATION_90,
),
- supportedNavigationModes =
- listOf(PlatformConsts.NavBar.MODE_3BUTTON, PlatformConsts.NavBar.MODE_GESTURAL)
+ supportedNavigationModes = listOf(NavBar.MODE_3BUTTON, NavBar.MODE_GESTURAL)
)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest.kt
index 89d37dbbb780..1fee20d7803a 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest.kt
@@ -18,17 +18,17 @@ package com.android.server.wm.flicker.ime
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Presubmit
+import android.tools.common.Rotation
+import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.BaseTest
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.snapshotStartingWindowLayerCoversExactlyOnApp
-import com.android.server.wm.traces.common.service.PlatformConsts
import org.junit.Assume
import org.junit.FixMethodOrder
import org.junit.Test
@@ -64,7 +64,7 @@ open class ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest(flicker: Fl
}
transitions {
// Bring the existing IME activity to the front in landscape mode device rotation.
- setRotation(PlatformConsts.Rotation.ROTATION_90)
+ setRotation(Rotation.ROTATION_90)
imeTestApp.launchViaIntent(wmHelper)
}
teardown { imeTestApp.exit(wmHelper) }
@@ -99,7 +99,7 @@ open class ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest(flicker: Fl
@JvmStatic
fun getParams(): Collection<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_90)
+ supportedRotations = listOf(Rotation.ROTATION_90)
)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTestCfArm.kt
index 307821f2d151..3aca2a07f7cd 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTestCfArm.kt
@@ -16,8 +16,8 @@
package com.android.server.wm.flicker.ime
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt
index c72e4e47c951..6179fc2aef21 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt
@@ -17,17 +17,17 @@
package com.android.server.wm.flicker.ime
import android.platform.test.annotations.Presubmit
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.helpers.reopenAppFromOverview
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.BaseTest
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper
-import com.android.server.wm.flicker.helpers.reopenAppFromOverview
import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.service.PlatformConsts
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -142,7 +142,7 @@ open class ShowImeOnAppStartWhenLaunchingAppFromOverviewTest(flicker: FlickerTes
@JvmStatic
fun getParams(): Collection<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt
index 167689cd1c18..954f589ffa7f 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt
@@ -18,18 +18,19 @@ package com.android.server.wm.flicker.ime
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Presubmit
+import android.tools.common.NavBar
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.BaseTest
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper
import com.android.server.wm.flicker.helpers.SimpleAppHelper
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.service.PlatformConsts
import org.junit.Assume
import org.junit.Before
import org.junit.FixMethodOrder
@@ -133,8 +134,8 @@ open class ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest(flicker: Flicker
@JvmStatic
fun getParams(): Collection<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL),
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedNavigationModes = listOf(NavBar.MODE_GESTURAL),
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTestCfArm.kt
index 82c38a31f128..0f57467c0449 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTestCfArm.kt
@@ -17,8 +17,8 @@
package com.android.server.wm.flicker.ime
import android.platform.test.annotations.Presubmit
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTestShellTransit.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTestShellTransit.kt
index 6c6003f8e64f..a927102f2a08 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTestShellTransit.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTestShellTransit.kt
@@ -17,10 +17,10 @@
package com.android.server.wm.flicker.ime
import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import org.junit.Assume
import org.junit.Before
import org.junit.FixMethodOrder
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt
index e7cfb9e7ab78..7514c9befe4f 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt
@@ -17,17 +17,17 @@
package com.android.server.wm.flicker.ime
import android.platform.test.annotations.Presubmit
-import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.BaseTest
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper
import com.android.server.wm.flicker.helpers.ImeStateInitializeHelper
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.BaseTest
import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.service.PlatformConsts
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -123,7 +123,7 @@ open class ShowImeOnAppStartWhenLaunchingAppTest(flicker: FlickerTest) : BaseTes
@JvmStatic
fun getParams(): Collection<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnStartWhenLaunchingAppCfArmTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnStartWhenLaunchingAppCfArmTest.kt
index e7ecb87ada24..194c86be3207 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnStartWhenLaunchingAppCfArmTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnStartWhenLaunchingAppCfArmTest.kt
@@ -16,8 +16,8 @@
package com.android.server.wm.flicker.ime
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt
index 851651eea91c..d1335294f629 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt
@@ -18,14 +18,14 @@ package com.android.server.wm.flicker.ime
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Presubmit
+import android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.BaseTest
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
import com.android.server.wm.flicker.helpers.ImeAppHelper
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.service.PlatformConsts
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -81,7 +81,7 @@ open class ShowImeWhenFocusingOnInputFieldTest(flicker: FlickerTest) : BaseTest(
@JvmStatic
fun getParams(): Collection<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTestCfArm.kt
index 0c5315524314..f5b22949e6b4 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTestCfArm.kt
@@ -16,8 +16,8 @@
package com.android.server.wm.flicker.ime
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt
index 605821225c1f..99b9bd2bfc66 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt
@@ -17,18 +17,18 @@
package com.android.server.wm.flicker.ime
import android.platform.test.annotations.Presubmit
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import android.view.WindowInsets.Type.ime
import android.view.WindowInsets.Type.navigationBars
import android.view.WindowInsets.Type.statusBars
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.BaseTest
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.service.PlatformConsts
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.FixMethodOrder
@@ -91,7 +91,7 @@ class ShowImeWhileDismissingThemedPopupDialogTest(flicker: FlickerTest) : BaseTe
@JvmStatic
fun getParams(): Collection<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt
index 5d963467229f..9ea12a9e22a0 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt
@@ -17,19 +17,19 @@
package com.android.server.wm.flicker.ime
import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.ConditionsFactory
+import android.tools.device.flicker.isShellTransitionsEnabled
+import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.traces.parsers.WindowManagerStateHelper
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.BaseTest
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.navBarLayerIsVisibleAtStartAndEnd
import com.android.server.wm.flicker.statusBarLayerIsVisibleAtStartAndEnd
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.WindowManagerConditionsFactory
-import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
import org.junit.Assume
import org.junit.FixMethodOrder
import org.junit.Ignore
@@ -82,7 +82,7 @@ open class ShowImeWhileEnteringOverviewTest(flicker: FlickerTest) : BaseTest(fli
private fun waitNavStatusBarVisibility(stateSync: WindowManagerStateHelper.StateSyncBuilder) {
when {
flicker.scenario.isLandscapeOrSeascapeAtStart && !flicker.scenario.isTablet ->
- stateSync.add(WindowManagerConditionsFactory.isStatusBarVisible().negate())
+ stateSync.add(ConditionsFactory.isStatusBarVisible().negate())
else -> stateSync.withNavOrTaskBarVisible().withStatusBarVisible()
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTestCfArm.kt
index 9308fbbc3f06..fc3971351db7 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTestCfArm.kt
@@ -16,8 +16,8 @@
package com.android.server.wm.flicker.ime
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt
index 7979cf9b7ba5..e8f9aa3038ef 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt
@@ -17,16 +17,16 @@
package com.android.server.wm.flicker.launch
import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.traces.parsers.toFlickerComponent
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.BaseTest
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
import com.android.server.wm.flicker.helpers.TwoActivitiesAppHelper
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.parser.toFlickerComponent
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTestCfArm.kt
index 549b929a6e81..8b89a8b4c40d 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTestCfArm.kt
@@ -16,9 +16,9 @@
package com.android.server.wm.flicker.launch
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTest.kt
index 09422876bd9b..549183f407e2 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTest.kt
@@ -16,12 +16,12 @@
package com.android.server.wm.flicker.launch
+import android.tools.device.apphelpers.CameraAppHelper
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.helpers.CameraAppHelper
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdFromIcon.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdFromIcon.kt
index 9d86f8c8dc81..19ecf6ab8799 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdFromIcon.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdFromIcon.kt
@@ -16,13 +16,14 @@
package com.android.server.wm.flicker.launch
+import android.tools.common.NavBar
+import android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.flicker.rules.RemoveAllTasksButHomeRule
-import com.android.server.wm.traces.common.service.PlatformConsts
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@@ -61,7 +62,7 @@ class OpenAppColdFromIcon(flicker: FlickerTest) : OpenAppFromLauncherTransition(
if (flicker.scenario.isTablet) {
tapl.setExpectedRotation(flicker.scenario.startRotation.value)
} else {
- tapl.setExpectedRotation(PlatformConsts.Rotation.ROTATION_0.value)
+ tapl.setExpectedRotation(Rotation.ROTATION_0.value)
}
RemoveAllTasksButHomeRule.removeAllTasksButHome()
}
@@ -87,7 +88,7 @@ class OpenAppColdFromIcon(flicker: FlickerTest) : OpenAppFromLauncherTransition(
fun getParams(): Collection<FlickerTest> {
// TAPL fails on landscape mode b/240916028
return FlickerTestFactory.nonRotationTests(
- supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_3BUTTON)
+ supportedNavigationModes = listOf(NavBar.MODE_3BUTTON)
)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
index 9fbec973e93f..8fdbb6445bac 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
@@ -17,14 +17,14 @@
package com.android.server.wm.flicker.launch
import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.annotation.FlickerServiceCompatible
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.annotation.FlickerServiceCompatible
import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.flicker.rules.RemoveAllTasksButHomeRule.Companion.removeAllTasksButHome
+import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule.Companion.removeAllTasksButHome
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLauncherTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLauncherTransition.kt
index 2f0e56f1a276..1a1d4036579f 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLauncherTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLauncherTransition.kt
@@ -17,9 +17,9 @@
package com.android.server.wm.flicker.launch
import android.platform.test.annotations.Presubmit
-import com.android.server.wm.flicker.FlickerTest
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.legacy.FlickerTest
import com.android.server.wm.flicker.replacesLayer
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
import org.junit.Test
/** Base class for app launch tests */
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt
index 08786d315623..63ffee6fd77b 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt
@@ -19,12 +19,15 @@ package com.android.server.wm.flicker.launch
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
+import android.platform.test.rule.SettingOverrideRule
+import android.provider.Settings
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
+import org.junit.ClassRule
import org.junit.FixMethodOrder
import org.junit.Ignore
import org.junit.Test
@@ -130,5 +133,16 @@ open class OpenAppFromLockNotificationCold(flicker: FlickerTest) :
fun getParams(): Collection<FlickerTest> {
return FlickerTestFactory.nonRotationTests()
}
+
+ /**
+ * Ensures that posted notifications will be visible on the lockscreen and not
+ * suppressed due to being marked as seen.
+ */
+ @ClassRule
+ @JvmField
+ val disableUnseenNotifFilterRule = SettingOverrideRule(
+ Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS,
+ /* value= */ "0",
+ )
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt
index a5d85ccadf0c..a221ef6963c3 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt
@@ -18,13 +18,16 @@ package com.android.server.wm.flicker.launch
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Presubmit
+import android.platform.test.rule.SettingOverrideRule
+import android.provider.Settings
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.statusBarLayerPositionAtEnd
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
+import org.junit.ClassRule
import org.junit.FixMethodOrder
import org.junit.Ignore
import org.junit.Test
@@ -145,5 +148,16 @@ class OpenAppFromLockNotificationWarm(flicker: FlickerTest) : OpenAppFromNotific
fun getParams(): Collection<FlickerTest> {
return FlickerTestFactory.nonRotationTests()
}
+
+ /**
+ * Ensures that posted notifications will be visible on the lockscreen and not
+ * suppressed due to being marked as seen.
+ */
+ @ClassRule
+ @JvmField
+ val disableUnseenNotifFilterRule = SettingOverrideRule(
+ Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS,
+ /* value= */ "0",
+ )
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt
index ff39611fbbf2..4efee55b97b5 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt
@@ -19,14 +19,14 @@ package com.android.server.wm.flicker.launch
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.helpers.wakeUpAndGoToHomeScreen
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
import com.android.server.wm.flicker.helpers.ShowWhenLockedAppHelper
-import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -46,8 +46,7 @@ import org.junit.runners.Parameterized
@Postsubmit
class OpenAppFromLockNotificationWithLockOverlayApp(flicker: FlickerTest) :
OpenAppFromLockNotificationCold(flicker) {
- private val showWhenLockedApp: ShowWhenLockedAppHelper =
- ShowWhenLockedAppHelper(instrumentation)
+ private val showWhenLockedApp = ShowWhenLockedAppHelper(instrumentation)
// Although we are technically still locked here, the overlay app means we should open the
// notification shade as if we were unlocked.
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt
index aa054a9333f1..730f78ff3bc2 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt
@@ -18,11 +18,11 @@ package com.android.server.wm.flicker.launch
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Presubmit
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
import com.android.server.wm.flicker.navBarLayerPositionAtEnd
import com.android.server.wm.flicker.statusBarLayerPositionAtEnd
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
import org.junit.Assume
import org.junit.Ignore
import org.junit.Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt
index 0ed3bba8311e..9c16b7938e73 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt
@@ -18,13 +18,13 @@ package com.android.server.wm.flicker.launch
import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.statusBarLayerPositionAtEnd
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
import org.junit.FixMethodOrder
import org.junit.Ignore
import org.junit.Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt
index af6c81d454b7..4a9507aabf75 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt
@@ -18,24 +18,24 @@ package com.android.server.wm.flicker.launch
import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.helpers.wakeUpAndGoToHomeScreen
import android.view.WindowInsets
import android.view.WindowManager
import androidx.test.filters.RequiresDevice
import androidx.test.uiautomator.By
import androidx.test.uiautomator.Until
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
import com.android.server.wm.flicker.helpers.NotificationAppHelper
import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.navBarLayerIsVisibleAtEnd
import com.android.server.wm.flicker.navBarLayerPositionAtEnd
import com.android.server.wm.flicker.navBarWindowIsVisibleAtEnd
import com.android.server.wm.flicker.taskBarLayerIsVisibleAtEnd
import com.android.server.wm.flicker.taskBarWindowIsVisibleAtEnd
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
import org.junit.Assume
import org.junit.FixMethodOrder
import org.junit.Ignore
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
index 2b16ef0de5a8..00d7544f7217 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
@@ -18,14 +18,14 @@ package com.android.server.wm.flicker.launch
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Presubmit
+import android.tools.common.Rotation
+import android.tools.device.flicker.annotation.FlickerServiceCompatible
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.annotation.FlickerServiceCompatible
import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.service.PlatformConsts
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -74,7 +74,7 @@ open class OpenAppFromOverviewTest(flicker: FlickerTest) : OpenAppFromLauncherTr
if (flicker.scenario.isTablet) {
tapl.setExpectedRotation(flicker.scenario.startRotation.value)
} else {
- tapl.setExpectedRotation(PlatformConsts.Rotation.ROTATION_0.value)
+ tapl.setExpectedRotation(Rotation.ROTATION_0.value)
}
tapl.workspace.switchToOverview()
wmHelper.StateSyncBuilder().withRecentsActivityVisible().waitForAndVerify()
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTestCfArm.kt
index 1c979e825793..ff24190a7aef 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTestCfArm.kt
@@ -16,10 +16,10 @@
package com.android.server.wm.flicker.launch
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.annotation.FlickerServiceCompatible
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.annotation.FlickerServiceCompatible
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
index 55e7a9926a04..9ab61566e13f 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
@@ -19,14 +19,15 @@ package com.android.server.wm.flicker.launch
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
+import android.tools.common.NavBar
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.annotation.FlickerServiceCompatible
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.annotation.FlickerServiceCompatible
import com.android.server.wm.flicker.helpers.NonResizeableAppHelper
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.service.PlatformConsts
import org.junit.Assume
import org.junit.FixMethodOrder
import org.junit.Ignore
@@ -213,8 +214,8 @@ open class OpenAppNonResizeableTest(flicker: FlickerTest) : OpenAppFromLockTrans
@JvmStatic
fun getParams(): Collection<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL),
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedNavigationModes = listOf(NavBar.MODE_GESTURAL),
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTransition.kt
index 618fb8ab76ea..e0db96f3b5c6 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTransition.kt
@@ -17,14 +17,14 @@
package com.android.server.wm.flicker.launch
import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.helpers.wakeUpAndGoToHomeScreen
import com.android.server.wm.flicker.BaseTest
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
import com.android.server.wm.flicker.helpers.SimpleAppHelper
-import com.android.server.wm.flicker.helpers.StandardAppHelper
import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
import org.junit.Test
/** Base class for app launch tests */
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
index 93bf09995984..cdd2d45769bb 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
@@ -18,13 +18,13 @@ package com.android.server.wm.flicker.launch
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.annotation.FlickerServiceCompatible
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.annotation.FlickerServiceCompatible
import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenCameraOnDoubleClickPowerButton.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenCameraOnDoubleClickPowerButton.kt
index 8d2af38c8898..786bb32096ad 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenCameraOnDoubleClickPowerButton.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenCameraOnDoubleClickPowerButton.kt
@@ -16,17 +16,18 @@
package com.android.server.wm.flicker.launch
+import android.os.SystemClock
import android.platform.test.annotations.Postsubmit
+import android.tools.device.apphelpers.CameraAppHelper
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import android.view.KeyEvent
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.annotation.FlickerServiceCompatible
-import com.android.server.wm.flicker.helpers.CameraAppHelper
import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.flicker.rules.RemoveAllTasksButHomeRule
+import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -54,13 +55,14 @@ import org.junit.runners.Parameterized
* ```
*/
@RequiresDevice
-@FlickerServiceCompatible
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class OpenCameraOnDoubleClickPowerButton(flicker: FlickerTest) :
OpenAppFromLauncherTransition(flicker) {
private val cameraApp = CameraAppHelper(instrumentation)
+ override val testApp: StandardAppHelper
+ get() = cameraApp
override val transition: FlickerBuilder.() -> Unit
get() = {
@@ -70,6 +72,7 @@ class OpenCameraOnDoubleClickPowerButton(flicker: FlickerTest) :
}
transitions {
device.pressKeyCode(KeyEvent.KEYCODE_POWER)
+ SystemClock.sleep(100)
device.pressKeyCode(KeyEvent.KEYCODE_POWER)
wmHelper.StateSyncBuilder().withWindowSurfaceAppeared(cameraApp).waitForAndVerify()
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt
index c78d0e9c5c5f..da985232a1e3 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt
@@ -20,21 +20,20 @@ import android.app.Instrumentation
import android.os.Bundle
import android.os.Handler
import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.ConditionsFactory
+import android.tools.device.flicker.junit.FlickerBuilderProvider
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
import com.android.server.wm.flicker.R
-import com.android.server.wm.flicker.helpers.SimpleAppHelper
-import com.android.server.wm.flicker.helpers.StandardAppHelper
import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
-import com.android.server.wm.flicker.junit.FlickerBuilderProvider
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.flicker.rules.RemoveAllTasksButHomeRule
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.WindowManagerConditionsFactory
+import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule
+import android.tools.device.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.helpers.SimpleAppHelper
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -58,7 +57,7 @@ import org.junit.runners.Parameterized
class OverrideTaskTransitionTest(val flicker: FlickerTest) {
private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
- private val testApp: StandardAppHelper = SimpleAppHelper(instrumentation)
+ private val testApp = SimpleAppHelper(instrumentation)
@FlickerBuilderProvider
fun buildFlicker(): FlickerBuilder {
@@ -75,7 +74,7 @@ class OverrideTaskTransitionTest(val flicker: FlickerTest) {
)
wmHelper
.StateSyncBuilder()
- .add(WindowManagerConditionsFactory.isWMStateComplete())
+ .add(ConditionsFactory.isWMStateComplete())
.withAppTransitionIdle()
.withWindowSurfaceAppeared(testApp)
.waitForAndVerify()
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt
index 94afd815921c..dd9e4cffcd30 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt
@@ -21,23 +21,23 @@ import android.app.WallpaperManager
import android.content.res.Resources
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.datatypes.component.ComponentNameMatcher.Companion.DEFAULT_TASK_DISPLAY_AREA
+import android.tools.common.datatypes.component.ComponentNameMatcher.Companion.SPLASH_SCREEN
+import android.tools.common.datatypes.component.ComponentNameMatcher.Companion.WALLPAPER_BBQ_WRAPPER
+import android.tools.common.datatypes.component.ComponentSplashScreenMatcher
+import android.tools.common.datatypes.component.IComponentMatcher
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.helpers.WindowUtils
+import android.tools.device.traces.parsers.toFlickerComponent
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.BaseTest
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
import com.android.server.wm.flicker.helpers.NewTasksAppHelper
import com.android.server.wm.flicker.helpers.SimpleAppHelper
-import com.android.server.wm.flicker.helpers.WindowUtils
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher.Companion.DEFAULT_TASK_DISPLAY_AREA
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher.Companion.SPLASH_SCREEN
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher.Companion.WALLPAPER_BBQ_WRAPPER
-import com.android.server.wm.traces.common.component.matchers.ComponentSplashScreenMatcher
-import com.android.server.wm.traces.common.component.matchers.IComponentMatcher
-import com.android.server.wm.traces.parser.toFlickerComponent
import org.junit.Assume
import org.junit.FixMethodOrder
import org.junit.Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
index b7faf8325fc2..78cee3c4e71c 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
@@ -17,18 +17,18 @@
package com.android.server.wm.flicker.quickswitch
import android.platform.test.annotations.Presubmit
+import android.tools.common.NavBar
+import android.tools.common.datatypes.Rect
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.BaseTest
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
import com.android.server.wm.flicker.helpers.NonResizeableAppHelper
import com.android.server.wm.flicker.helpers.SimpleAppHelper
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.Rect
-import com.android.server.wm.traces.common.service.PlatformConsts
import org.junit.Assume
import org.junit.Before
import org.junit.FixMethodOrder
@@ -237,7 +237,7 @@ open class QuickSwitchBetweenTwoAppsBackTest(flicker: FlickerTest) : BaseTest(fl
@JvmStatic
fun getParams(): Collection<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL)
+ supportedNavigationModes = listOf(NavBar.MODE_GESTURAL)
)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTestCfArm.kt
index e6cdd1efa798..f970a79abcb8 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTestCfArm.kt
@@ -16,11 +16,10 @@
package com.android.server.wm.flicker.quickswitch
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.Rect
-import com.android.server.wm.traces.common.service.PlatformConsts
+import android.tools.common.NavBar
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@@ -32,13 +31,11 @@ import org.junit.runners.Parameterized
class QuickSwitchBetweenTwoAppsBackTestCfArm(flicker: FlickerTest) :
QuickSwitchBetweenTwoAppsBackTest(flicker) {
companion object {
- private var startDisplayBounds = Rect.EMPTY
-
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): Collection<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL)
+ supportedNavigationModes = listOf(NavBar.MODE_GESTURAL)
)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt
index 25d9753b363f..2b69e9b7d258 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt
@@ -17,10 +17,10 @@
package com.android.server.wm.flicker.quickswitch
import android.platform.test.annotations.FlakyTest
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import org.junit.Assume
import org.junit.Before
import org.junit.FixMethodOrder
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
index 6294761ba1bf..cd7d6fac0e9c 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
@@ -17,18 +17,18 @@
package com.android.server.wm.flicker.quickswitch
import android.platform.test.annotations.Presubmit
+import android.tools.common.NavBar
+import android.tools.common.datatypes.Rect
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.BaseTest
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
import com.android.server.wm.flicker.helpers.NonResizeableAppHelper
import com.android.server.wm.flicker.helpers.SimpleAppHelper
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.Rect
-import com.android.server.wm.traces.common.service.PlatformConsts
import org.junit.Assume
import org.junit.Before
import org.junit.FixMethodOrder
@@ -255,7 +255,7 @@ open class QuickSwitchBetweenTwoAppsForwardTest(flicker: FlickerTest) : BaseTest
@JvmStatic
fun getParams(): Collection<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL)
+ supportedNavigationModes = listOf(NavBar.MODE_GESTURAL)
)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTestCfArm.kt
index aa9adf0116ae..9f48cdae20f1 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTestCfArm.kt
@@ -16,11 +16,10 @@
package com.android.server.wm.flicker.quickswitch
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.Rect
-import com.android.server.wm.traces.common.service.PlatformConsts
+import android.tools.common.NavBar
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@@ -32,13 +31,11 @@ import org.junit.runners.Parameterized
class QuickSwitchBetweenTwoAppsForwardTestCfArm(flicker: FlickerTest) :
QuickSwitchBetweenTwoAppsForwardTest(flicker) {
companion object {
- private var startDisplayBounds = Rect.EMPTY
-
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): Collection<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL)
+ supportedNavigationModes = listOf(NavBar.MODE_GESTURAL)
)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest_ShellTransit.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest_ShellTransit.kt
index b40ecac2d19a..b0d4e2753758 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest_ShellTransit.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest_ShellTransit.kt
@@ -17,10 +17,10 @@
package com.android.server.wm.flicker.quickswitch
import android.platform.test.annotations.FlakyTest
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import org.junit.Assume
import org.junit.Before
import org.junit.FixMethodOrder
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt
index c03cd2954e25..63299cb6cd7a 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt
@@ -18,17 +18,18 @@ package com.android.server.wm.flicker.quickswitch
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Presubmit
+import android.tools.common.NavBar
+import android.tools.common.Rotation
+import android.tools.common.datatypes.Rect
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.BaseTest
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
import com.android.server.wm.flicker.helpers.SimpleAppHelper
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.Rect
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.service.PlatformConsts
import org.junit.Assume
import org.junit.FixMethodOrder
import org.junit.Ignore
@@ -283,9 +284,9 @@ open class QuickSwitchFromLauncherTest(flicker: FlickerTest) : BaseTest(flicker)
@JvmStatic
fun getParams(): Collection<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL),
+ supportedNavigationModes = listOf(NavBar.MODE_GESTURAL),
// TODO: Test with 90 rotation
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTestCfArm.kt
index 8b216035f9f8..af671df194ae 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTestCfArm.kt
@@ -16,10 +16,11 @@
package com.android.server.wm.flicker.quickswitch
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.service.PlatformConsts
+import android.tools.common.NavBar
+import android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@@ -35,9 +36,9 @@ open class QuickSwitchFromLauncherTestCfArm(flicker: FlickerTest) :
@JvmStatic
fun getParams(): Collection<FlickerTest> {
return FlickerTestFactory.nonRotationTests(
- supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL),
+ supportedNavigationModes = listOf(NavBar.MODE_GESTURAL),
// TODO: Test with 90 rotation
- supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ supportedRotations = listOf(Rotation.ROTATION_0)
)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
index e7e39c69f5fb..4a4180b6bbff 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
@@ -18,13 +18,13 @@ package com.android.server.wm.flicker.rotation
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
import com.android.server.wm.flicker.helpers.SimpleAppHelper
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTestCfArm.kt
index 6420f79a01f1..0e6b20fc21c6 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTestCfArm.kt
@@ -16,9 +16,9 @@
package com.android.server.wm.flicker.rotation
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
index 74ecddeb359a..3c0bbd6c4c1c 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
@@ -17,12 +17,12 @@
package com.android.server.wm.flicker.rotation
import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
import com.android.server.wm.flicker.BaseTest
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.helpers.StandardAppHelper
import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
import org.junit.Test
/** Base class for app rotation tests */
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
index 1a69344ded40..17b3b2b97e4b 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
@@ -18,16 +18,16 @@ package com.android.server.wm.flicker.rotation
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Presubmit
+import android.tools.common.ScenarioBuilder
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import android.view.WindowManager
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.ScenarioBuilder
import com.android.server.wm.flicker.helpers.SeamlessRotationAppHelper
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
import org.junit.FixMethodOrder
import org.junit.Ignore
import org.junit.Test
@@ -108,8 +108,10 @@ open class SeamlessAppRotationTest(flicker: FlickerTest) : RotationTransition(fl
fun appWindowFullScreen() {
flicker.assertWm {
this.invoke("isFullScreen") {
- val appWindow = it.windowState(testApp.`package`)
- val flags = appWindow.windowState?.attributes?.flags ?: 0
+ val appWindow =
+ it.windowState(testApp.`package`)
+ ?: error("App window for package ${testApp.`package`} not found")
+ val flags = appWindow.windowState.attributes.flags
appWindow
.check { "isFullScreen" }
.that(flags.and(WindowManager.LayoutParams.FLAG_FULLSCREEN))
@@ -124,8 +126,10 @@ open class SeamlessAppRotationTest(flicker: FlickerTest) : RotationTransition(fl
fun appWindowSeamlessRotation() {
flicker.assertWm {
this.invoke("isRotationSeamless") {
- val appWindow = it.windowState(testApp.`package`)
- val rotationAnimation = appWindow.windowState?.attributes?.rotationAnimation ?: 0
+ val appWindow =
+ it.windowState(testApp.`package`)
+ ?: error("App window for package ${testApp.`package`} not found")
+ val rotationAnimation = appWindow.windowState.attributes.rotationAnimation
appWindow
.check { "isRotationSeamless" }
.that(
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTestCfArm.kt
index 0ebbf4eb6eae..b236d87616ab 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTestCfArm.kt
@@ -16,9 +16,9 @@
package com.android.server.wm.flicker.rotation
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
import com.android.server.wm.flicker.testapp.ActivityOptions
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
diff --git a/tests/FlickerTests/test-apps/flickerapp/Android.bp b/tests/FlickerTests/test-apps/flickerapp/Android.bp
index 9b1262dd193b..75e35ee9c765 100644
--- a/tests/FlickerTests/test-apps/flickerapp/Android.bp
+++ b/tests/FlickerTests/test-apps/flickerapp/Android.bp
@@ -41,6 +41,7 @@ android_test {
"kotlin-stdlib",
"kotlinx-coroutines-android",
"wm-flicker-common-app-helpers",
+ "wm-flicker-common-assertions",
"wm-flicker-window-extensions",
],
}
diff --git a/tests/Input/src/com/android/test/input/MotionPredictorTest.kt b/tests/Input/src/com/android/test/input/MotionPredictorTest.kt
index 8b1b06fe40e8..24a567130ff0 100644
--- a/tests/Input/src/com/android/test/input/MotionPredictorTest.kt
+++ b/tests/Input/src/com/android/test/input/MotionPredictorTest.kt
@@ -124,14 +124,12 @@ class MotionPredictorTest {
predictor.record(moveEvent)
val predicted = predictor.predict(Duration.ofMillis(8).toNanos())
- assertEquals(1, predicted.size)
- val event = predicted[0]
- assertNotNull(event)
+ assertNotNull(predicted)
// Prediction will happen for t=12 (since it is the next input interval after the requested
// time, 8, plus the model offset, 1).
- assertEquals(12, event.eventTime)
- assertEquals(30f, event.x, /*delta=*/5f)
- assertEquals(60f, event.y, /*delta=*/15f)
+ assertEquals(12, predicted!!.eventTime)
+ assertEquals(30f, predicted.x, /*delta=*/5f)
+ assertEquals(60f, predicted.y, /*delta=*/15f)
}
}
diff --git a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/NotificationTest.java b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/NotificationTest.java
index 573b3b695a90..d2708ad47712 100644
--- a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/NotificationTest.java
+++ b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/NotificationTest.java
@@ -42,6 +42,7 @@ import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.BySelector;
import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
import androidx.test.uiautomator.Until;
import org.junit.After;
@@ -74,7 +75,7 @@ public final class NotificationTest {
// This is for AOSP System UI for phones. When testing customized System UI, please modify here.
private static final BySelector REPLY_SEND_BUTTON_SELECTOR =
- By.res("com.android.systemui", "remote_input_send");
+ By.res("com.android.systemui", "remote_input_send").enabled(true);
@Rule
public UnlockScreenRule mUnlockScreenRule = new UnlockScreenRule();
@@ -119,7 +120,15 @@ public final class NotificationTest {
mUiDevice.pressKeyCode(KeyEvent.KEYCODE_A);
mUiDevice.pressKeyCode(KeyEvent.KEYCODE_B);
mUiDevice.pressKeyCode(KeyEvent.KEYCODE_C);
- mUiDevice.wait(Until.findObject(REPLY_SEND_BUTTON_SELECTOR.enabled(true)), TIMEOUT).click();
+ UiObject2 sendButton = mUiDevice.wait(
+ Until.findObject(REPLY_SEND_BUTTON_SELECTOR), TIMEOUT);
+ if (sendButton == null) {
+ // If the screen is too small, sendButton may be hidden by IME.
+ // Dismiss IME and try again.
+ mUiDevice.pressBack();
+ sendButton = mUiDevice.wait(Until.findObject(REPLY_SEND_BUTTON_SELECTOR), TIMEOUT);
+ }
+ sendButton.click();
// Verify that IME is gone.
assertThat(mUiDevice.wait(Until.gone(By.pkg(getImePackage(mContext))), TIMEOUT)).isTrue();
}
diff --git a/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java b/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java
index c7e5a5ea3311..e59071bd1d88 100644
--- a/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java
+++ b/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java
@@ -29,6 +29,7 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.os.Debug.MemoryInfo;
+import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.UserHandle;
import android.test.InstrumentationTestCase;
@@ -40,6 +41,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
/**
* This test is intended to measure the amount of memory applications use when
@@ -313,17 +315,19 @@ public class MemoryUsageTest extends InstrumentationTestCase {
public void run() {
try {
- String mimeType = mLaunchIntent.getType();
- if (mimeType == null && mLaunchIntent.getData() != null
+ AtomicReference<String> mimeType = new AtomicReference<>(mLaunchIntent.getType());
+ if (mimeType.get() == null && mLaunchIntent.getData() != null
&& "content".equals(mLaunchIntent.getData().getScheme())) {
- mimeType = mAm.getProviderMimeType(mLaunchIntent.getData(),
- UserHandle.USER_CURRENT);
+ mAm.getMimeTypeFilterAsync(mLaunchIntent.getData(), UserHandle.USER_CURRENT,
+ new RemoteCallback(result -> {
+ mimeType.set(result.getPairValue());
+ }));
}
mAtm.startActivityAndWait(null,
getInstrumentation().getContext().getBasePackageName(),
getInstrumentation().getContext().getAttributionTag(), mLaunchIntent,
- mimeType, null, null, 0, mLaunchIntent.getFlags(), null, null,
+ mimeType.get(), null, null, 0, mLaunchIntent.getFlags(), null, null,
UserHandle.USER_CURRENT_OR_SELF);
} catch (RemoteException e) {
Log.w(TAG, "Error launching app", e);
diff --git a/tests/MidiTests/Android.bp b/tests/MidiTests/Android.bp
new file mode 100644
index 000000000000..254770d21818
--- /dev/null
+++ b/tests/MidiTests/Android.bp
@@ -0,0 +1,40 @@
+//
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test {
+ name: "MidiTests",
+ srcs: ["**/*.java"],
+ static_libs: [
+ "androidx.test.rules",
+ "mockito-target-inline-minus-junit4",
+ "platform-test-annotations",
+ "services.midi",
+ "truth-prebuilt",
+ ],
+ jni_libs: ["libdexmakerjvmtiagent"],
+ certificate: "platform",
+ platform_apis: true,
+ test_suites: ["device-tests"],
+}
diff --git a/tests/MidiTests/AndroidManifest.xml b/tests/MidiTests/AndroidManifest.xml
new file mode 100644
index 000000000000..0ee1b4493764
--- /dev/null
+++ b/tests/MidiTests/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.server.midi" >
+
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
+ <uses-permission android:name="android.permission.MANAGE_USERS" />
+
+ <application android:debuggable="true">
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.server.midi"
+ android:label="MidiTests"/>
+</manifest>
diff --git a/tests/MidiTests/AndroidTest.xml b/tests/MidiTests/AndroidTest.xml
new file mode 100644
index 000000000000..9320f0aac090
--- /dev/null
+++ b/tests/MidiTests/AndroidTest.xml
@@ -0,0 +1,30 @@
+<!-- Copyright (C) 2023 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.
+-->
+<configuration description="Runs sample instrumentation test.">
+ <target_preparer class="com.android.tradefed.targetprep.TestFilePushSetup"/>
+ <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+ <option name="test-file-name" value="MidiTests.apk"/>
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"/>
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"/>
+ <option name="test-suite-tag" value="apct"/>
+ <option name="test-tag" value="MidiTests"/>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="com.android.server.midi"/>
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner"/>
+ <option name="hidden-api-checks" value="false"/>
+ </test>
+</configuration>
diff --git a/tests/MidiTests/OWNERS b/tests/MidiTests/OWNERS
new file mode 100644
index 000000000000..af273a6f50e0
--- /dev/null
+++ b/tests/MidiTests/OWNERS
@@ -0,0 +1 @@
+include /services/midi/OWNERS
diff --git a/tests/MidiTests/TEST_MAPPING b/tests/MidiTests/TEST_MAPPING
new file mode 100644
index 000000000000..60416a8ab3f9
--- /dev/null
+++ b/tests/MidiTests/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "MidiTests"
+ }
+ ]
+}
diff --git a/tests/MidiTests/src/com/android/server/midi/MidiEventMultiSchedulerTest.java b/tests/MidiTests/src/com/android/server/midi/MidiEventMultiSchedulerTest.java
new file mode 100644
index 000000000000..1659cc07f021
--- /dev/null
+++ b/tests/MidiTests/src/com/android/server/midi/MidiEventMultiSchedulerTest.java
@@ -0,0 +1,342 @@
+/*
+ * Copyright (C) 2023 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.midi;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.midi.MidiEventMultiScheduler;
+import com.android.internal.midi.MidiEventScheduler;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Random;
+
+/**
+ * Unit tests for com.android.internal.midi.MidiEventMultiScheduler.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class MidiEventMultiSchedulerTest {
+ private byte[] generateRandomByteStream(Random rnd, int size) {
+ byte[] output = new byte[size];
+ rnd.nextBytes(output);
+ return output;
+ }
+
+ private void compareByteArrays(byte[] expectedArray, byte[] outputArray) {
+ assertEquals(expectedArray.length, outputArray.length);
+ for (int i = 0; i < outputArray.length; i++) {
+ assertEquals(expectedArray[i], outputArray[i]);
+ }
+ }
+
+ private long timeFromNow(long milliseconds) {
+ return System.nanoTime() + 1000000L * milliseconds;
+ }
+
+ @Test
+ public void testMultiScheduler() {
+ try {
+ MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(3);
+ assertEquals(3, multiScheduler.getNumEventSchedulers());
+ MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+ MidiEventScheduler scheduler1 = multiScheduler.getEventScheduler(1);
+ MidiEventScheduler scheduler2 = multiScheduler.getEventScheduler(2);
+
+ scheduler0.add(scheduler0.createScheduledEvent(new byte[]{(byte) 0xf0, (byte) 0xf7},
+ 0, 2, timeFromNow(100)));
+ scheduler1.add(scheduler1.createScheduledEvent(new byte[]{(byte) 0xf1, (byte) 0xf2},
+ 0, 2, timeFromNow(200)));
+ scheduler2.add(scheduler2.createScheduledEvent(new byte[]{(byte) 0xf3, (byte) 0xf4},
+ 0, 2, timeFromNow(300)));
+ scheduler0.add(scheduler0.createScheduledEvent(new byte[]{(byte) 0xf5, (byte) 0xf6},
+ 0, 2, timeFromNow(400)));
+ assertTrue(multiScheduler.waitNextEvent());
+ assertNotNull(scheduler0.getNextEvent(System.nanoTime()));
+ assertNull(scheduler1.getNextEvent(System.nanoTime()));
+ assertNull(scheduler2.getNextEvent(System.nanoTime()));
+ assertTrue(multiScheduler.waitNextEvent());
+ assertNull(scheduler0.getNextEvent(System.nanoTime()));
+ assertNotNull(scheduler1.getNextEvent(System.nanoTime()));
+ assertNull(scheduler2.getNextEvent(System.nanoTime()));
+ assertTrue(multiScheduler.waitNextEvent());
+ assertNull(scheduler0.getNextEvent(System.nanoTime()));
+ assertNull(scheduler1.getNextEvent(System.nanoTime()));
+ assertNotNull(scheduler2.getNextEvent(System.nanoTime()));
+ assertTrue(multiScheduler.waitNextEvent());
+ assertNotNull(scheduler0.getNextEvent(System.nanoTime()));
+ assertNull(scheduler1.getNextEvent(System.nanoTime()));
+ assertNull(scheduler2.getNextEvent(System.nanoTime()));
+ } catch (InterruptedException ex) {
+
+ }
+ }
+
+ @Test
+ public void testSchedulerLargeData() {
+ try {
+ MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(1);
+ assertEquals(1, multiScheduler.getNumEventSchedulers());
+ MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+
+ Random rnd = new Random(42);
+
+ final int arraySize = 1000;
+ byte[] expectedArray = generateRandomByteStream(rnd, arraySize);
+
+ scheduler0.add(scheduler0.createScheduledEvent(expectedArray, 0, arraySize,
+ timeFromNow(100)));
+ assertTrue(multiScheduler.waitNextEvent());
+ MidiEventScheduler.MidiEvent event =
+ (MidiEventScheduler.MidiEvent) scheduler0.getNextEvent(System.nanoTime());
+ assertNotNull(event);
+ compareByteArrays(expectedArray, event.data);
+ } catch (InterruptedException ex) {
+
+ }
+ }
+
+ @Test
+ public void testSchedulerClose() {
+ try {
+ MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(1);
+ assertEquals(1, multiScheduler.getNumEventSchedulers());
+ MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+ scheduler0.close();
+ // After all schedulers are closed, waitNextEvent() should return false.
+ assertFalse(multiScheduler.waitNextEvent());
+ } catch (InterruptedException ex) {
+
+ }
+ }
+
+ @Test
+ public void testSchedulerMultiClose() {
+ try {
+ MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(3);
+ assertEquals(3, multiScheduler.getNumEventSchedulers());
+ multiScheduler.close();
+ // After all schedulers are closed, waitNextEvent() should return false.
+ assertFalse(multiScheduler.waitNextEvent());
+ } catch (InterruptedException ex) {
+
+ }
+ }
+
+ @Test
+ public void testSchedulerNoPreemptiveClose() {
+ try {
+ MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(3);
+ assertEquals(3, multiScheduler.getNumEventSchedulers());
+ MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+ MidiEventScheduler scheduler1 = multiScheduler.getEventScheduler(1);
+ MidiEventScheduler scheduler2 = multiScheduler.getEventScheduler(2);
+ scheduler0.close();
+ scheduler1.close();
+ scheduler2.add(scheduler2.createScheduledEvent(new byte[]{(byte) 0xf5, (byte) 0xf6},
+ 0, 2, timeFromNow(100)));
+ assertTrue(multiScheduler.waitNextEvent());
+ scheduler2.close();
+ // After all schedulers are closed, waitNextEvent() should return false.
+ assertFalse(multiScheduler.waitNextEvent());
+ } catch (InterruptedException ex) {
+
+ }
+ }
+
+ @Test
+ public void testSchedulerSpamEvents() {
+ MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(1);
+ assertEquals(1, multiScheduler.getNumEventSchedulers());
+ MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+ // Create a msg with size 1
+ byte[] msg = new byte[1];
+ for (int i = 0; i < 1000; i++) {
+ msg[0] = (byte) i;
+ scheduler0.add(scheduler0.createScheduledEvent(msg, 0, 1, timeFromNow(0)));
+ MidiEventScheduler.MidiEvent event =
+ (MidiEventScheduler.MidiEvent) scheduler0.getNextEvent(System.nanoTime());
+ assertNotNull(event);
+ assertEquals(1, event.count);
+ assertEquals(msg[0], event.data[0]);
+ }
+ assertNull(scheduler0.getNextEvent(System.nanoTime()));
+ }
+
+ @Test
+ public void testSchedulerSpamEventsPullLater() {
+ MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(1);
+ assertEquals(1, multiScheduler.getNumEventSchedulers());
+ MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+ // Create a msg with size 1
+ byte[] msg = new byte[1];
+ for (int i = 0; i < 1000; i++) {
+ msg[0] = (byte) i;
+ scheduler0.add(scheduler0.createScheduledEvent(msg, 0, 1, timeFromNow(0)));
+ }
+
+ for (int i = 0; i < 1000; i++) {
+ MidiEventScheduler.MidiEvent event =
+ (MidiEventScheduler.MidiEvent) scheduler0.getNextEvent(System.nanoTime());
+ assertNotNull(event);
+ assertEquals(1, event.count);
+ assertEquals((byte) i, event.data[0]);
+ }
+ assertNull(scheduler0.getNextEvent(System.nanoTime()));
+ }
+
+ @Test
+ public void testSchedulerSpamEventsCallbackLater() {
+ MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(1);
+ assertEquals(1, multiScheduler.getNumEventSchedulers());
+ MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+ // Create a msg with size 1
+ byte[] msg = new byte[1];
+ for (int i = 0; i < 1000; i++) {
+ msg[0] = (byte) i;
+ scheduler0.add(scheduler0.createScheduledEvent(msg, 0, 1, timeFromNow(0)));
+ }
+
+ for (int i = 0; i < 1000; i++) {
+ try {
+ assertTrue(multiScheduler.waitNextEvent());
+ } catch (InterruptedException ex) {
+ }
+ MidiEventScheduler.MidiEvent event =
+ (MidiEventScheduler.MidiEvent) scheduler0.getNextEvent(System.nanoTime());
+ assertNotNull(event);
+ assertEquals(1, event.count);
+ assertEquals((byte) i, event.data[0]);
+ }
+ assertNull(scheduler0.getNextEvent(System.nanoTime()));
+ }
+
+ @Test
+ public void testMultiSchedulerOutOfOrder() {
+ try {
+ MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(3);
+ assertEquals(3, multiScheduler.getNumEventSchedulers());
+ MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+ MidiEventScheduler scheduler1 = multiScheduler.getEventScheduler(1);
+ MidiEventScheduler scheduler2 = multiScheduler.getEventScheduler(2);
+
+ scheduler0.add(scheduler0.createScheduledEvent(new byte[]{(byte) 0xf3},
+ 0, 1,
+ timeFromNow(400)));
+ scheduler2.add(scheduler2.createScheduledEvent(new byte[]{(byte) 0xf2},
+ 0, 1,
+ timeFromNow(300)));
+ scheduler1.add(scheduler1.createScheduledEvent(new byte[]{(byte) 0xf1},
+ 0, 1,
+ timeFromNow(200)));
+ scheduler0.add(scheduler0.createScheduledEvent(new byte[]{(byte) 0xf0},
+ 0, 1,
+ timeFromNow(100)));
+
+ assertTrue(multiScheduler.waitNextEvent());
+ MidiEventScheduler.MidiEvent event =
+ (MidiEventScheduler.MidiEvent) scheduler0.getNextEvent(System.nanoTime());
+ assertNotNull(event);
+ assertEquals(1, event.count);
+ assertEquals((byte) 0xf0, event.data[0]);
+ assertNull(scheduler1.getNextEvent(System.nanoTime()));
+ assertNull(scheduler2.getNextEvent(System.nanoTime()));
+ assertTrue(multiScheduler.waitNextEvent());
+ assertNull(scheduler0.getNextEvent(System.nanoTime()));
+ event = (MidiEventScheduler.MidiEvent) scheduler1.getNextEvent(System.nanoTime());
+ assertNotNull(event);
+ assertEquals(1, event.count);
+ assertEquals((byte) 0xf1, event.data[0]);
+ assertNull(scheduler2.getNextEvent(System.nanoTime()));
+ assertTrue(multiScheduler.waitNextEvent());
+ assertNull(scheduler0.getNextEvent(System.nanoTime()));
+ assertNull(scheduler1.getNextEvent(System.nanoTime()));
+ event = (MidiEventScheduler.MidiEvent) scheduler2.getNextEvent(System.nanoTime());
+ assertNotNull(event);
+ assertEquals(1, event.count);
+ assertEquals((byte) 0xf2, event.data[0]);
+ assertTrue(multiScheduler.waitNextEvent());
+ event = (MidiEventScheduler.MidiEvent) scheduler0.getNextEvent(System.nanoTime());
+ assertNotNull(event);
+ assertEquals(1, event.count);
+ assertEquals((byte) 0xf3, event.data[0]);
+ assertNull(scheduler1.getNextEvent(System.nanoTime()));
+ assertNull(scheduler2.getNextEvent(System.nanoTime()));
+ } catch (InterruptedException ex) {
+
+ }
+ }
+
+ @Test
+ public void testMultiSchedulerOutOfOrderNegativeTime() {
+ try {
+ MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(3);
+ assertEquals(3, multiScheduler.getNumEventSchedulers());
+ MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+ MidiEventScheduler scheduler1 = multiScheduler.getEventScheduler(1);
+ MidiEventScheduler scheduler2 = multiScheduler.getEventScheduler(2);
+
+ scheduler0.add(scheduler0.createScheduledEvent(new byte[]{(byte) 0xf3},
+ 0, 1,
+ timeFromNow(-100)));
+ scheduler2.add(scheduler2.createScheduledEvent(new byte[]{(byte) 0xf2},
+ 0, 1,
+ timeFromNow(-200)));
+ scheduler1.add(scheduler1.createScheduledEvent(new byte[]{(byte) 0xf1},
+ 0, 1,
+ timeFromNow(-300)));
+ scheduler0.add(scheduler0.createScheduledEvent(new byte[]{(byte) 0xf0},
+ 0, 1,
+ timeFromNow(-400)));
+
+ assertTrue(multiScheduler.waitNextEvent());
+ MidiEventScheduler.MidiEvent event =
+ (MidiEventScheduler.MidiEvent) scheduler0.getNextEvent(System.nanoTime());
+ assertNotNull(event);
+ assertEquals(1, event.count);
+ assertEquals((byte) 0xf0, event.data[0]);
+ assertTrue(multiScheduler.waitNextEvent());
+ event = (MidiEventScheduler.MidiEvent) scheduler1.getNextEvent(System.nanoTime());
+ assertNotNull(event);
+ assertEquals(1, event.count);
+ assertEquals((byte) 0xf1, event.data[0]);
+ assertTrue(multiScheduler.waitNextEvent());
+ event = (MidiEventScheduler.MidiEvent) scheduler2.getNextEvent(System.nanoTime());
+ assertNotNull(event);
+ assertEquals(1, event.count);
+ assertEquals((byte) 0xf2, event.data[0]);
+ assertNull(scheduler1.getNextEvent(System.nanoTime()));
+ assertTrue(multiScheduler.waitNextEvent());
+ event = (MidiEventScheduler.MidiEvent) scheduler0.getNextEvent(System.nanoTime());
+ assertNotNull(event);
+ assertEquals(1, event.count);
+ assertEquals((byte) 0xf3, event.data[0]);
+ assertNull(scheduler1.getNextEvent(System.nanoTime()));
+ assertNull(scheduler2.getNextEvent(System.nanoTime()));
+ } catch (InterruptedException ex) {
+
+ }
+ }
+}
diff --git a/tests/MotionPrediction/src/test/motionprediction/DrawingView.kt b/tests/MotionPrediction/src/test/motionprediction/DrawingView.kt
index f529bf77f32a..229d0c8da6e9 100644
--- a/tests/MotionPrediction/src/test/motionprediction/DrawingView.kt
+++ b/tests/MotionPrediction/src/test/motionprediction/DrawingView.kt
@@ -97,8 +97,8 @@ class DrawingView(context: Context, attrs: AttributeSet) : View(context, attrs)
}
// Draw predictions. Convert to nanos and hardcode to +20ms into the future
- val predictionList = predictor.predict(eventTime * 1000000 + 20000000)
- for (prediction in predictionList) {
+ val prediction = predictor.predict(eventTime * 1000000 + 20000000)
+ if (prediction != null) {
val realEvents = events.get(prediction.deviceId)!!
drawLine(canvas, realEvents[realEvents.size - 1], prediction, predictionPaint)
}
diff --git a/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapImage.kt b/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapImage.kt
index 387564437b5f..e079b6d5e4db 100644
--- a/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapImage.kt
+++ b/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapImage.kt
@@ -80,10 +80,10 @@ class GainmapImage(context: Context, attrs: AttributeSet?) : FrameLayout(context
spinner.adapter = adapter
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(
- parent: AdapterView<*>?,
- view: View?,
- position: Int,
- id: Long
+ parent: AdapterView<*>?,
+ view: View?,
+ position: Int,
+ id: Long
) {
setImage(position)
}
@@ -108,7 +108,7 @@ class GainmapImage(context: Context, attrs: AttributeSet?) : FrameLayout(context
if (selectedImage == position) return
selectedImage = position
val source = ImageDecoder.createSource(resources.assets,
- "gainmaps/${gainmapImages[position]}")
+ "gainmaps/${gainmapImages[position]}")
doDecode(source)
}
@@ -137,16 +137,16 @@ class GainmapImage(context: Context, attrs: AttributeSet?) : FrameLayout(context
gainmapVisualizer = map
} else {
gainmapVisualizer = Bitmap.createBitmap(map.width, map.height,
- Bitmap.Config.ARGB_8888)
+ Bitmap.Config.ARGB_8888)
val canvas = Canvas(gainmapVisualizer!!)
val paint = Paint()
paint.colorFilter = ColorMatrixColorFilter(
- floatArrayOf(
- 0f, 0f, 0f, 1f, 0f,
- 0f, 0f, 0f, 1f, 0f,
- 0f, 0f, 0f, 1f, 0f,
- 0f, 0f, 0f, 0f, 255f
- )
+ floatArrayOf(
+ 0f, 0f, 0f, 1f, 0f,
+ 0f, 0f, 0f, 1f, 0f,
+ 0f, 0f, 0f, 1f, 0f,
+ 0f, 0f, 0f, 0f, 255f
+ )
)
canvas.drawBitmap(map, 0f, 0f, paint)
canvas.setBitmap(null)
@@ -174,8 +174,14 @@ class GainmapImage(context: Context, attrs: AttributeSet?) : FrameLayout(context
if (bitmap == null) return
imageView.setImage(ImageSource.cachedBitmap(when (outputMode) {
- R.id.output_hdr -> { bitmap!!.gainmap = gainmap; bitmap!! }
- R.id.output_sdr -> { bitmap!!.gainmap = null; bitmap!! }
+ R.id.output_hdr -> {
+ bitmap!!.gainmap = gainmap; bitmap!!
+ }
+
+ R.id.output_sdr -> {
+ bitmap!!.gainmap = null; bitmap!!
+ }
+
R.id.output_gainmap -> gainmapVisualizer!!
else -> throw IllegalStateException()
}))
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/BufferPresentationTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/BufferPresentationTests.kt
index 7a8d9490b540..97398dc4e334 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/BufferPresentationTests.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/BufferPresentationTests.kt
@@ -15,7 +15,7 @@
*/
package com.android.test
-import com.android.server.wm.flicker.traces.layers.LayersTraceSubject
+import android.tools.common.flicker.subject.layers.LayersTraceSubject
import junit.framework.Assert.assertEquals
import junit.framework.Assert.assertTrue
import org.junit.Test
@@ -170,4 +170,4 @@ class BufferPresentationTests(useBlastAdapter: Boolean) : SurfaceTracingTestBase
assertTrue(failures)
}
}
-} \ No newline at end of file
+}
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/BufferRejectionTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/BufferRejectionTests.kt
index da53387c935c..0cc18d657cf5 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/BufferRejectionTests.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/BufferRejectionTests.kt
@@ -16,10 +16,11 @@
package com.android.test
import android.graphics.Point
-import com.android.server.wm.flicker.traces.layers.LayersTraceSubject
+import android.tools.common.flicker.subject.layers.LayersTraceSubject
import com.android.test.SurfaceViewBufferTestBase.Companion.ScalingMode
import com.android.test.SurfaceViewBufferTestBase.Companion.Transform
import junit.framework.Assert.assertEquals
+import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
@@ -45,8 +46,9 @@ class BufferRejectionTests(useBlastAdapter: Boolean) : SurfaceTracingTestBase(us
activity.mSurfaceProxy.waitUntilBufferDisplayed(3, 500 /* ms */)
}
// Verify we reject buffers since scaling mode == NATIVE_WINDOW_SCALING_MODE_FREEZE
- LayersTraceSubject(trace).layer("SurfaceView", 2).doesNotExist()
-
+ Assert.assertThrows(AssertionError::class.java) {
+ LayersTraceSubject(trace).layer("SurfaceView", 2)
+ }
// Verify the next buffer is submitted with the correct size
LayersTraceSubject(trace).layer("SurfaceView", 3).also {
it.hasBufferSize(defaultBufferSize)
@@ -82,7 +84,9 @@ class BufferRejectionTests(useBlastAdapter: Boolean) : SurfaceTracingTestBase(us
// verify buffer size is reset to default buffer size
LayersTraceSubject(trace).layer("SurfaceView", 1).hasBufferSize(defaultBufferSize)
- LayersTraceSubject(trace).layer("SurfaceView", 2).doesNotExist()
+ Assert.assertThrows(AssertionError::class.java) {
+ LayersTraceSubject(trace).layer("SurfaceView", 2)
+ }
LayersTraceSubject(trace).layer("SurfaceView", 3).hasBufferSize(bufferSize)
}
@@ -110,7 +114,9 @@ class BufferRejectionTests(useBlastAdapter: Boolean) : SurfaceTracingTestBase(us
// verify buffer size is reset to default buffer size
LayersTraceSubject(trace).layer("SurfaceView", 1).hasBufferSize(defaultBufferSize)
- LayersTraceSubject(trace).layer("SurfaceView", 2).doesNotExist()
+ Assert.assertThrows(AssertionError::class.java) {
+ LayersTraceSubject(trace).layer("SurfaceView", 2)
+ }
LayersTraceSubject(trace).layer("SurfaceView", 3).hasBufferSize(rotatedBufferSize)
LayersTraceSubject(trace).layer("SurfaceView", 3)
.hasBufferOrientation(Transform.ROT_90.value)
@@ -144,10 +150,11 @@ class BufferRejectionTests(useBlastAdapter: Boolean) : SurfaceTracingTestBase(us
for (count in 0 until 5) {
LayersTraceSubject(trace).layer("SurfaceView", (count * 3) + 1L)
.hasBufferSize(defaultBufferSize)
- LayersTraceSubject(trace).layer("SurfaceView", (count * 3) + 2L)
- .doesNotExist()
+ Assert.assertThrows(AssertionError::class.java) {
+ LayersTraceSubject(trace).layer("SurfaceView", (count * 3) + 2L)
+ }
LayersTraceSubject(trace).layer("SurfaceView", (count * 3) + 3L)
.hasBufferSize(bufferSize)
}
}
-} \ No newline at end of file
+}
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/GeometryTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/GeometryTests.kt
index 2d6c664cca02..6f4d11c3aa1b 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/GeometryTests.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/GeometryTests.kt
@@ -19,11 +19,12 @@ import android.graphics.Color
import android.graphics.Point
import android.graphics.Rect
import android.os.SystemClock
-import com.android.server.wm.flicker.traces.layers.LayersTraceSubject
+import android.tools.common.flicker.subject.layers.LayersTraceSubject
import com.android.test.SurfaceViewBufferTestBase.Companion.ScalingMode
import com.android.test.SurfaceViewBufferTestBase.Companion.Transform
import junit.framework.Assert.assertEquals
import junit.framework.Assert.assertTrue
+import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
@@ -103,7 +104,9 @@ class GeometryTests(useBlastAdapter: Boolean) : SurfaceTracingTestBase(useBlastA
// verify buffer size is reset to default buffer size
LayersTraceSubject(trace).layer("SurfaceView", 1).hasBufferSize(defaultBufferSize)
- LayersTraceSubject(trace).layer("SurfaceView", 2).doesNotExist()
+ Assert.assertThrows(AssertionError::class.java) {
+ LayersTraceSubject(trace).layer("SurfaceView", 2)
+ }
LayersTraceSubject(trace).layer("SurfaceView", 3).hasBufferSize(bufferSize)
}
@@ -221,4 +224,4 @@ class GeometryTests(useBlastAdapter: Boolean) : SurfaceTracingTestBase(useBlastA
it.hasBufferSize(defaultBufferSize)
}
}
-} \ No newline at end of file
+}
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt
index cf4186d84e2d..e722ba537a8e 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt
@@ -16,9 +16,10 @@
package com.android.test
import android.graphics.Point
-import com.android.server.wm.flicker.traces.layers.LayersTraceSubject
+import android.tools.common.flicker.subject.layers.LayersTraceSubject
import com.android.test.SurfaceViewBufferTestBase.Companion.Transform
import junit.framework.Assert.assertEquals
+import org.junit.Assert
import org.junit.Assume.assumeFalse
import org.junit.Before
import org.junit.Test
@@ -70,7 +71,9 @@ class InverseDisplayTransformTests(useBlastAdapter: Boolean) :
// verify buffer size is reset to default buffer size
LayersTraceSubject(trace).layer("SurfaceView", 1).hasBufferSize(defaultBufferSize)
- LayersTraceSubject(trace).layer("SurfaceView", 2).doesNotExist()
+ Assert.assertThrows(AssertionError::class.java) {
+ LayersTraceSubject(trace).layer("SurfaceView", 2)
+ }
LayersTraceSubject(trace).layer("SurfaceView", 3).hasBufferSize(rotatedBufferSize)
}
-} \ No newline at end of file
+}
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeTests.kt
index 61d4095c7cf3..be3ed715d4e2 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeTests.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeTests.kt
@@ -17,7 +17,7 @@ package com.android.test
import android.graphics.Color
import android.graphics.Rect
-import com.android.server.wm.flicker.traces.layers.LayersTraceSubject
+import android.tools.common.flicker.subject.layers.LayersTraceSubject
import junit.framework.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
@@ -87,4 +87,4 @@ class SharedBufferModeTests(useBlastAdapter: Boolean) : SurfaceTracingTestBase(u
checkPixels(svBounds, Color.BLUE)
}
}
-} \ No newline at end of file
+}
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt
index 6383da5a0a98..cf4cb8c97ea1 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt
@@ -21,9 +21,11 @@ import android.graphics.Color
import android.graphics.Rect
import android.util.Log
import androidx.test.ext.junit.rules.ActivityScenarioRule
-import com.android.server.wm.flicker.monitor.LayersTraceMonitor
-import com.android.server.wm.flicker.monitor.withSFTracing
-import com.android.server.wm.traces.common.layers.LayersTrace
+import android.tools.common.flicker.subject.layers.LayerSubject
+import android.tools.common.traces.surfaceflinger.LayersTrace
+import android.tools.device.traces.io.ResultWriter
+import android.tools.device.traces.monitors.surfaceflinger.LayersTraceMonitor
+import android.tools.device.traces.monitors.withSFTracing
import junit.framework.Assert
import org.junit.After
import org.junit.Before
@@ -52,8 +54,7 @@ open class SurfaceTracingTestBase(useBlastAdapter: Boolean) :
}
fun withTrace(predicate: (it: MainActivity) -> Unit): LayersTrace {
- return withSFTracing(TRACE_FLAGS,
- outputDir = instrumentation.targetContext.dataDir.toPath()) {
+ return withSFTracing(TRACE_FLAGS) {
scenarioRule.getScenario().onActivity {
predicate(it)
}
@@ -61,8 +62,7 @@ open class SurfaceTracingTestBase(useBlastAdapter: Boolean) :
}
fun withTrace(predicate: () -> Unit): LayersTrace {
- return withSFTracing(TRACE_FLAGS,
- outputDir = instrumentation.targetContext.dataDir.toPath()) {
+ return withSFTracing(TRACE_FLAGS) {
predicate()
}
}
@@ -84,8 +84,7 @@ open class SurfaceTracingTestBase(useBlastAdapter: Boolean) :
}
private fun stopLayerTrace() {
- val tmpDir = instrumentation.targetContext.dataDir.toPath()
- LayersTraceMonitor(tmpDir).stop()
+ LayersTraceMonitor().stop(ResultWriter())
}
fun checkPixels(bounds: Rect, @ColorInt color: Int) {
@@ -117,4 +116,4 @@ open class SurfaceTracingTestBase(useBlastAdapter: Boolean) :
private const val TRACE_FLAGS =
(1 shl 0) or (1 shl 5) or (1 shl 6) // TRACE_CRITICAL | TRACE_BUFFERS | TRACE_SYNC
}
-} \ No newline at end of file
+}
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceViewBufferTestBase.kt b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceViewBufferTestBase.kt
index 093c3125f253..bba967815ba5 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceViewBufferTestBase.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceViewBufferTestBase.kt
@@ -18,6 +18,8 @@ package com.android.test
import android.app.Instrumentation
import android.graphics.Point
import android.provider.Settings
+import android.tools.common.datatypes.Size
+import android.tools.common.flicker.subject.layers.LayerSubject
import androidx.test.InstrumentationRegistry
import org.junit.After
import org.junit.Before
@@ -69,6 +71,10 @@ open class SurfaceViewBufferTestBase(val useBlastAdapter: Boolean) {
const val R8G8B8A8_UNORM = 1
val defaultBufferSize = Point(640, 480)
+ fun LayerSubject.hasBufferSize(point: Point) = hasBufferSize(Size.from(point.x, point.y))
+
+ fun LayerSubject.hasLayerSize(point: Point) = hasLayerSize(Size.from(point.x, point.y))
+
// system/window.h definitions
enum class ScalingMode() {
FREEZE, // = 0
@@ -94,4 +100,4 @@ open class SurfaceViewBufferTestBase(val useBlastAdapter: Boolean) {
INVERSE_DISPLAY(0x08)
}
}
-} \ No newline at end of file
+}
diff --git a/tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt b/tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt
index 722e671266e1..6f4f7b13af66 100644
--- a/tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt
+++ b/tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt
@@ -16,14 +16,15 @@
package com.android.test.taskembed
import android.app.Instrumentation
-import android.graphics.Point
import android.graphics.Rect
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.runner.AndroidJUnit4
-import com.android.server.wm.flicker.monitor.LayersTraceMonitor
-import com.android.server.wm.flicker.monitor.withSFTracing
-import com.android.server.wm.flicker.traces.layers.LayersTraceSubject
+import android.tools.common.datatypes.Size
+import android.tools.common.flicker.subject.layers.LayersTraceSubject
+import android.tools.device.traces.io.ResultWriter
+import android.tools.device.traces.monitors.surfaceflinger.LayersTraceMonitor
+import android.tools.device.traces.monitors.withSFTracing
import org.junit.After
import org.junit.Before
import org.junit.FixMethodOrder
@@ -46,8 +47,10 @@ class ResizeTasksSyncTest {
@Before
fun setup() {
- val tmpDir = instrumentation.targetContext.dataDir.toPath()
- LayersTraceMonitor(tmpDir).stop()
+ val monitor = LayersTraceMonitor()
+ if (monitor.isEnabled) {
+ monitor.stop(ResultWriter())
+ }
val firstTaskBounds = Rect(0, 0, 1080, 1000)
val secondTaskBounds = Rect(0, 1000, 1080, 2000)
@@ -68,8 +71,7 @@ class ResizeTasksSyncTest {
val firstBounds = Rect(0, 0, 1080, 800)
val secondBounds = Rect(0, 1000, 1080, 1800)
- val trace = withSFTracing(TRACE_FLAGS,
- outputDir = instrumentation.targetContext.dataDir.toPath()) {
+ val trace = withSFTracing(TRACE_FLAGS) {
lateinit var resizeReadyLatch: CountDownLatch
scenarioRule.getScenario().onActivity {
resizeReadyLatch = it.resizeTaskView(firstBounds, secondBounds)
@@ -91,13 +93,13 @@ class ResizeTasksSyncTest {
// verify buffer size should be changed to expected values.
LayersTraceSubject(trace).layer(FIRST_ACTIVITY, frame.toLong()).also {
- val firstTaskSize = Point(firstBounds.width(), firstBounds.height())
+ val firstTaskSize = Size.from(firstBounds.width(), firstBounds.height())
it.hasLayerSize(firstTaskSize)
it.hasBufferSize(firstTaskSize)
}
LayersTraceSubject(trace).layer(SECOND_ACTIVITY, frame.toLong()).also {
- val secondTaskSize = Point(secondBounds.width(), secondBounds.height())
+ val secondTaskSize = Size.from(secondBounds.width(), secondBounds.height())
it.hasLayerSize(secondTaskSize)
it.hasBufferSize(secondTaskSize)
}
@@ -108,4 +110,4 @@ class ResizeTasksSyncTest {
private const val FIRST_ACTIVITY = "Activity1"
private const val SECOND_ACTIVITY = "Activity2"
}
-} \ No newline at end of file
+}
diff --git a/tests/UsbTests/src/com/android/server/usb/UsbMidiPacketConverterTest.java b/tests/UsbTests/src/com/android/server/usb/UsbMidiPacketConverterTest.java
new file mode 100644
index 000000000000..ad701e5117fc
--- /dev/null
+++ b/tests/UsbTests/src/com/android/server/usb/UsbMidiPacketConverterTest.java
@@ -0,0 +1,407 @@
+/*
+ * Copyright (C) 2023 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.usb;
+
+import static org.junit.Assert.assertEquals;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+import java.util.Random;
+
+/**
+ * Unit tests for com.android.server.usb.UsbMidiPacketConverter.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class UsbMidiPacketConverterTest {
+ private byte[] generateRandomByteStream(Random rnd, int size) {
+ byte[] output = new byte[size];
+ rnd.nextBytes(output);
+ return output;
+ }
+
+ private void compareByteArrays(byte[] expectedArray, byte[] outputArray) {
+ assertEquals(expectedArray.length, outputArray.length);
+ for (int i = 0; i < outputArray.length; i++) {
+ assertEquals(expectedArray[i], outputArray[i]);
+ }
+ }
+
+ @Test
+ public void testDecoderSinglePacket() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createDecoders(2);
+ byte[] input = new byte[] {0x19 /* Cable 1 Note-On */, (byte) 0x91, 0x33, 0x66};
+ byte[] expectedOutputCable0 = new byte[] {};
+ byte[] expectedOutputCable1 = new byte[] {(byte) 0x91, 0x33, 0x66};
+ usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+ byte[] actualOutputCable0 = usbMidiPacketConverter.pullDecodedMidiPackets(0);
+ byte[] actualOutputCable1 = usbMidiPacketConverter.pullDecodedMidiPackets(1);
+ compareByteArrays(expectedOutputCable0, actualOutputCable0);
+ compareByteArrays(expectedOutputCable1, actualOutputCable1);
+ }
+
+ @Test
+ public void testDecoderMultiplePackets() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createDecoders(4);
+ byte[] input = new byte[] {
+ 0x1B /* Cable 1 Control Change */, (byte) 0xB4, 0x55, 0x6E,
+ 0x35 /* Cable 3 Single byte SysEx */, (byte) 0xF8, 0x00, 0x00,
+ 0x02 /* Cable 0 Two byte System Common */, (byte) 0xF3, 0x12, 0x00};
+ byte[] expectedOutputCable0 = new byte[] {(byte) 0xF3, 0x12};
+ byte[] expectedOutputCable1 = new byte[] {(byte) 0xB4, 0x55, 0x6E};
+ byte[] expectedOutputCable2 = new byte[] {};
+ byte[] expectedOutputCable3 = new byte[] {(byte) 0xF8};
+ usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+ byte[] actualOutputCable0 = usbMidiPacketConverter.pullDecodedMidiPackets(0);
+ byte[] actualOutputCable1 = usbMidiPacketConverter.pullDecodedMidiPackets(1);
+ byte[] actualOutputCable2 = usbMidiPacketConverter.pullDecodedMidiPackets(2);
+ byte[] actualOutputCable3 = usbMidiPacketConverter.pullDecodedMidiPackets(3);
+ compareByteArrays(expectedOutputCable0, actualOutputCable0);
+ compareByteArrays(expectedOutputCable1, actualOutputCable1);
+ compareByteArrays(expectedOutputCable2, actualOutputCable2);
+ compareByteArrays(expectedOutputCable3, actualOutputCable3);
+ }
+
+ @Test
+ public void testDecoderSysExEndFirstByte() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createDecoders(2);
+ byte[] input = new byte[] {
+ 0x14 /* Cable 1 SysEx Start */, (byte) 0xF0, 0x00, 0x01,
+ 0x15 /* Cable 1 Single byte SysEx End */, (byte) 0xF7, 0x00, 0x00};
+ byte[] expectedOutputCable0 = new byte[] {};
+ byte[] expectedOutputCable1 = new byte[] {
+ (byte) 0xF0, 0x00, 0x01,
+ (byte) 0xF7};
+ usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+ byte[] actualOutputCable0 = usbMidiPacketConverter.pullDecodedMidiPackets(0);
+ byte[] actualOutputCable1 = usbMidiPacketConverter.pullDecodedMidiPackets(1);
+ compareByteArrays(expectedOutputCable0, actualOutputCable0);
+ compareByteArrays(expectedOutputCable1, actualOutputCable1);
+ }
+
+ @Test
+ public void testDecoderSysExEndSecondByte() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createDecoders(1);
+ byte[] input = new byte[] {
+ 0x04 /* Cable 0 SysEx Start */, (byte) 0xF0, 0x00, 0x01,
+ 0x06 /* Cable 0 Two byte SysEx End */, 0x02, (byte) 0xF7, 0x00};
+ byte[] expectedOutputCable0 = new byte[] {
+ (byte) 0xF0, 0x00, 0x01,
+ 0x02, (byte) 0xF7};
+ usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+ byte[] actualOutputCable0 = usbMidiPacketConverter.pullDecodedMidiPackets(0);
+ compareByteArrays(expectedOutputCable0, actualOutputCable0);
+ }
+
+ @Test
+ public void testDecoderSysExEndThirdByte() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ byte[] input = new byte[] {
+ 0x04 /* Cable 0 SysEx Start */, (byte) 0xF0, 0x00, 0x01,
+ 0x07 /* Cable 0 Three byte SysEx End */, 0x02, 0x03, (byte) 0xF7};
+ usbMidiPacketConverter.createDecoders(1);
+ byte[] expectedOutputCable0 = new byte[] {
+ (byte) 0xF0, 0x00, 0x01,
+ 0x02, 0x03, (byte) 0xF7};
+ usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+ byte[] actualOutputCable0 = usbMidiPacketConverter.pullDecodedMidiPackets(0);
+ compareByteArrays(expectedOutputCable0, actualOutputCable0);
+ }
+
+ @Test
+ public void testDecoderSysExStartEnd() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ byte[] input = new byte[] {
+ 0x06 /* Cable 0 Two byte SysEx End */, (byte) 0xF0, (byte) 0xF7, 0x00};
+ usbMidiPacketConverter.createDecoders(1);
+ byte[] expectedOutputCable0 = new byte[] {
+ (byte) 0xF0, (byte) 0xF7};
+ usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+ byte[] actualOutputCable0 = usbMidiPacketConverter.pullDecodedMidiPackets(0);
+ compareByteArrays(expectedOutputCable0, actualOutputCable0);
+ }
+
+ @Test
+ public void testDecoderSysExStartByteEnd() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ byte[] input = new byte[] {
+ 0x07 /* Cable 0 Three byte SysEx End */, (byte) 0xF0, 0x44, (byte) 0xF7};
+ usbMidiPacketConverter.createDecoders(1);
+ byte[] expectedOutputCable0 = new byte[] {
+ (byte) 0xF0, 0x44, (byte) 0xF7};
+ usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+ byte[] actualOutputCable0 = usbMidiPacketConverter.pullDecodedMidiPackets(0);
+ compareByteArrays(expectedOutputCable0, actualOutputCable0);
+ }
+
+ @Test
+ public void testDecoderDefaultToFirstCable() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ byte[] input = new byte[] {0x49 /* Cable 4 Note-On */, (byte) 0x91, 0x22, 0x33};
+ usbMidiPacketConverter.createDecoders(1);
+ byte[] expectedOutputCable0 = new byte[] {
+ (byte) 0x91, 0x22, 0x33};
+ usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+ byte[] actualOutputCable0 = usbMidiPacketConverter.pullDecodedMidiPackets(0);
+ compareByteArrays(expectedOutputCable0, actualOutputCable0);
+ }
+
+ @Test
+ public void testDecoderLargePacketDoesNotCrash() {
+ for (long seed = 1001; seed < 5000; seed += 777) {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createDecoders(3);
+ Random rnd = new Random(seed);
+ byte[] input = generateRandomByteStream(rnd, 1003 /* arbitrary large size */);
+ usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+ usbMidiPacketConverter.pullDecodedMidiPackets(0);
+ usbMidiPacketConverter.pullDecodedMidiPackets(1);
+ usbMidiPacketConverter.pullDecodedMidiPackets(2);
+ }
+ }
+
+ @Test
+ public void testEncoderBasic() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createEncoders(1);
+ byte[] input = new byte[] {(byte) 0x91 /* Note-On */, 0x33, 0x66};
+ byte[] expectedOutput = new byte[] {
+ 0x09 /* Cable 0 Note-On */, (byte) 0x91, 0x33, 0x66};
+ usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+ byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+ compareByteArrays(expectedOutput, output);
+ }
+
+ @Test
+ public void testEncoderMultiplePackets() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createEncoders(3);
+ byte[] inputCable2 = new byte[] {
+ (byte) 0xB4 /* Control Change */, 0x55, 0x6E};
+ byte[] inputCable1 = new byte[] {
+ (byte) 0xF8 /* Timing Clock (Single Byte) */,
+ (byte) 0xF3 /* Song Select (Two Bytes) */, 0x12};
+ byte[] expectedOutput = new byte[] {
+ 0x2B /* Cable 2 Control Change */, (byte) 0xB4, 0x55, 0x6E,
+ 0x15 /* Cable 1 Timing Clock */, (byte) 0xF8, 0x00, 0x00,
+ 0x12 /* Cable 1 Two Byte System Common */, (byte) 0xF3, 0x12, 0x00};
+ usbMidiPacketConverter.encodeMidiPackets(inputCable2, inputCable2.length, 2);
+ usbMidiPacketConverter.encodeMidiPackets(inputCable1, inputCable1.length, 1);
+ byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+ compareByteArrays(expectedOutput, output);
+ }
+
+ @Test
+ public void testEncoderWeavePackets() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createEncoders(2);
+ byte[] inputCable1Msg1 = new byte[] {
+ (byte) 0x93 /* Note-On */, 0x23, 0x43};
+ byte[] inputCable0Msg = new byte[] {
+ (byte) 0xB4 /* Control Change */, 0x65, 0x26};
+ byte[] inputCable1Msg2 = new byte[] {
+ (byte) 0xA4 /* Poly-KeyPress */, 0x52, 0x76};
+ byte[] expectedOutput = new byte[] {
+ 0x19 /* Cable 1 Note-On */, (byte) 0x93, 0x23, 0x43,
+ 0x0B /* Cable 0 Control Change */, (byte) 0xB4, 0x65, 0x26,
+ 0x1A /* Cable 1 Poly-KeyPress */, (byte) 0xA4, 0x52, 0x76};
+ usbMidiPacketConverter.encodeMidiPackets(inputCable1Msg1, inputCable1Msg1.length, 1);
+ usbMidiPacketConverter.encodeMidiPackets(inputCable0Msg, inputCable0Msg.length, 0);
+ usbMidiPacketConverter.encodeMidiPackets(inputCable1Msg2, inputCable1Msg2.length, 1);
+ byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+ compareByteArrays(expectedOutput, output);
+ }
+
+ @Test
+ public void testEncoderSysExEndFirstByte() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createEncoders(1);
+ byte[] input = new byte[] {
+ (byte) 0xF0 /* SysEx Start */, 0x00, 0x01,
+ (byte) 0xF7 /* SysEx End */};
+ byte[] expectedOutput = new byte[] {
+ 0x04 /* Cable 0 Three Byte SysEx Start */, (byte) 0xF0, 0x00, 0x01,
+ 0x05 /* Cable 0 One Byte SysEx End */, (byte) 0xF7, 0x00, 0x00};
+ usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+ byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+ compareByteArrays(expectedOutput, output);
+ }
+
+ @Test
+ public void testEncoderSysExEndSecondByte() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createEncoders(1);
+ byte[] input = new byte[] {
+ (byte) 0xF0 /* SysEx Start */, 0x00, 0x01,
+ 0x02, (byte) 0xF7 /* SysEx End */};
+ byte[] expectedOutput = new byte[] {
+ 0x04 /* Cable 0 Three Byte SysEx Start */, (byte) 0xF0, 0x00, 0x01,
+ 0x06 /* Cable 0 Two Byte SysEx End */, 0x02, (byte) 0xF7, 0x00};
+ usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+ byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+ compareByteArrays(expectedOutput, output);
+ }
+
+ @Test
+ public void testEncoderSysExEndThirdByte() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createEncoders(1);
+ byte[] input = new byte[] {
+ (byte) 0xF0 /* SysEx Start */, 0x00, 0x01,
+ 0x02, 0x03, (byte) 0xF7 /* SysEx End */};
+ byte[] expectedOutput = new byte[] {
+ 0x04 /* Cable 0 Three Byte SysEx Start */, (byte) 0xF0, 0x00, 0x01,
+ 0x07 /* Cable 0 Three Byte SysEx End */, 0x02, 0x03, (byte) 0xF7};
+ usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+ byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+ compareByteArrays(expectedOutput, output);
+ }
+
+ @Test
+ public void testEncoderSysExStartEnd() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createEncoders(1);
+ byte[] input = new byte[] {
+ (byte) 0xF0 /* SysEx Start */, (byte) 0xF7 /* SysEx End */};
+ byte[] expectedOutput = new byte[] {
+ 0x06 /* Cable 0 Two Byte SysEx End */, (byte) 0xF0, (byte) 0xF7, 0x00};
+ usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+ byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+ compareByteArrays(expectedOutput, output);
+ }
+
+ @Test
+ public void testEncoderSysExStartByteEnd() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createEncoders(1);
+ byte[] input = new byte[] {
+ (byte) 0xF0 /* SysEx Start */, 0x44, (byte) 0xF7 /* SysEx End */};
+ byte[] expectedOutput = new byte[] {
+ 0x07 /* Cable 0 Three Byte SysEx End */, (byte) 0xF0, 0x44, (byte) 0xF7};
+ usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+ byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+ compareByteArrays(expectedOutput, output);
+ }
+
+ @Test
+ public void testEncoderMultiplePulls() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createEncoders(1);
+
+ byte[] input = new byte[] {
+ (byte) 0xF0 /* SysEx Start */, 0x44, 0x55,
+ 0x66, 0x77}; // 0x66 and 0x77 will not be pulled the first time
+ byte[] expectedOutput = new byte[] {
+ 0x04 /* SysEx Start */, (byte) 0xF0, 0x44, 0x55};
+ usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+ byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+ compareByteArrays(expectedOutput, output);
+
+ input = new byte[] {
+ 0x11, // Combined with 0x66 and 0x77 above
+ 0x22, (byte) 0xF7 /* SysEx End */};
+ expectedOutput = new byte[] {
+ 0x04 /* Cable 0 SysEx Continue */, 0x66, 0x77, 0x11,
+ 0x06 /* Cable 0 Two Byte SysEx End */, 0x22, (byte) 0xF7, 0x00};
+ usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+ output = usbMidiPacketConverter.pullEncodedMidiPackets();
+ compareByteArrays(expectedOutput, output);
+
+ input = new byte[] {
+ (byte) 0xF0 /* SysEx Start */, (byte) 0xF7 /* SysEx End */};
+ expectedOutput = new byte[] {
+ 0x06 /* Cable 0 Two Byte SysEx End */, (byte) 0xF0, (byte) 0xF7, 0x00};
+ usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+ output = usbMidiPacketConverter.pullEncodedMidiPackets();
+ compareByteArrays(expectedOutput, output);
+ }
+
+ @Test
+ public void testEncoderDefaultToFirstCable() {
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createEncoders(2);
+ byte[] input = new byte[] {(byte) 0x91 /* Note-On */, 0x22, 0x33};
+ byte[] expectedOutput = new byte[] {
+ 0x09 /* Cable 0 Note-On */, (byte) 0x91, 0x22, 0x33};
+ usbMidiPacketConverter.encodeMidiPackets(input, input.length, 4);
+ byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+ compareByteArrays(expectedOutput, output);
+ }
+
+ @Test
+ public void testEncoderLargePacketDoesNotCrash() {
+ for (long seed = 234; seed < 4000; seed += 666) {
+ Random rnd = new Random(seed);
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createEncoders(4);
+ for (int cableNumber = 0; cableNumber < 4; cableNumber++) {
+ byte[] input = generateRandomByteStream(rnd, 1003 /* arbitrary large size */);
+ usbMidiPacketConverter.encodeMidiPackets(input, input.length, cableNumber);
+ }
+ usbMidiPacketConverter.pullEncodedMidiPackets();
+ }
+ }
+
+ @Test
+ public void testEncodeDecode() {
+ final int bufferSize = 30;
+ final int numCables = 16;
+ final int bytesToEncodePerEncoding = 10;
+ byte[][] rawMidi = new byte[numCables][bufferSize];
+ for (long seed = 45; seed < 3000; seed += 300) {
+ Random rnd = new Random(seed);
+ for (int cableNumber = 0; cableNumber < numCables; cableNumber++) {
+ rawMidi[cableNumber] = generateRandomByteStream(rnd, bufferSize);
+
+ // Change the last byte to SysEx End.
+ // This way the encoder is guaranteed to flush all packets.
+ rawMidi[cableNumber][bufferSize - 1] = (byte) 0xF7;
+ }
+ UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+ usbMidiPacketConverter.createEncoders(numCables);
+ // Encode packets and interweave them
+ for (int startByte = 0; startByte < bufferSize;
+ startByte += bytesToEncodePerEncoding) {
+ for (int cableNumber = 0; cableNumber < numCables; cableNumber++) {
+ byte[] bytesToEncode = Arrays.copyOfRange(rawMidi[cableNumber], startByte,
+ startByte + bytesToEncodePerEncoding);
+ usbMidiPacketConverter.encodeMidiPackets(bytesToEncode, bytesToEncode.length,
+ cableNumber);
+ }
+ }
+ byte[] usbMidi = usbMidiPacketConverter.pullEncodedMidiPackets();
+
+ usbMidiPacketConverter.createDecoders(numCables);
+
+ // Now decode the MIDI packets to check if they are the same as the original
+ usbMidiPacketConverter.decodeMidiPackets(usbMidi, usbMidi.length);
+ for (int cableNumber = 0; cableNumber < numCables; cableNumber++) {
+ byte[] decodedRawMidi = usbMidiPacketConverter.pullDecodedMidiPackets(cableNumber);
+ compareByteArrays(rawMidi[cableNumber], decodedRawMidi);
+ }
+ }
+ }
+}
diff --git a/tools/aapt2/Android.mk b/tools/aapt2/Android.mk
index 7b94e718fd0e..34a1b112d880 100644
--- a/tools/aapt2/Android.mk
+++ b/tools/aapt2/Android.mk
@@ -15,7 +15,7 @@ $(aapt2_results): .KATI_IMPLICIT_OUTPUTS := $(aapt2_results)-nocache
$(aapt2_results): $(HOST_OUT_NATIVE_TESTS)/aapt2_tests/aapt2_tests
-$(HOST_OUT_NATIVE_TESTS)/aapt2_tests/aapt2_tests --gtest_output=xml:$@ > /dev/null 2>&1
-$(call declare-0p-target,$(aapt2_results))
+$(call declare-1p-target,$(aapt2_results))
aapt2_results :=
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetwork.aidl
index 35d5c15a161b..f9c4829c8f93 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetwork.aidl
@@ -16,4 +16,4 @@
package android.net.wifi.sharedconnectivity.app;
-parcelable DeviceInfo; \ No newline at end of file
+parcelable HotspotNetwork;
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetwork.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetwork.java
index af4fd4a2cc76..d3b7b12e5387 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetwork.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetwork.java
@@ -25,22 +25,22 @@ import android.annotation.SystemApi;
import android.net.wifi.sharedconnectivity.service.SharedConnectivityService;
import android.os.Parcel;
import android.os.Parcelable;
-
+import android.util.ArraySet;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.Arrays;
import java.util.Objects;
+import java.util.Set;
/**
- * A data class representing an Instant Tether network.
+ * A data class representing a hotspot network.
* This class is used in IPC calls between the implementer of {@link SharedConnectivityService} and
* the consumers of {@link com.android.wifitrackerlib}.
*
* @hide
*/
@SystemApi
-public final class TetherNetwork implements Parcelable {
+public final class HotspotNetwork implements Parcelable {
/**
* Remote device is connected to the internet via an unknown connection.
*/
@@ -71,34 +71,44 @@ public final class TetherNetwork implements Parcelable {
NETWORK_TYPE_WIFI,
NETWORK_TYPE_ETHERNET
})
- public @interface NetworkType {}
+ public @interface NetworkType {
+ }
private final long mDeviceId;
- private final DeviceInfo mDeviceInfo;
- @NetworkType private final int mNetworkType;
+ private final NetworkProviderInfo mNetworkProviderInfo;
+ @NetworkType
+ private final int mNetworkType;
private final String mNetworkName;
- @Nullable private final String mHotspotSsid;
- @Nullable private final String mHotspotBssid;
- @Nullable @SecurityType private final int[] mHotspotSecurityTypes;
+ @Nullable
+ private final String mHotspotSsid;
+ @Nullable
+ private final String mHotspotBssid;
+ @Nullable
+ @SecurityType
+ private final ArraySet<Integer> mHotspotSecurityTypes;
/**
- * Builder class for {@link TetherNetwork}.
+ * Builder class for {@link HotspotNetwork}.
*/
public static final class Builder {
private long mDeviceId = -1;
- private DeviceInfo mDeviceInfo;
- @NetworkType private int mNetworkType;
+ private NetworkProviderInfo mNetworkProviderInfo;
+ @NetworkType
+ private int mNetworkType;
private String mNetworkName;
- @Nullable private String mHotspotSsid;
- @Nullable private String mHotspotBssid;
- @Nullable @SecurityType private int[] mHotspotSecurityTypes;
-
- public Builder() {}
+ @Nullable
+ private String mHotspotSsid;
+ @Nullable
+ private String mHotspotBssid;
+ @Nullable
+ @SecurityType
+ private final ArraySet<Integer> mHotspotSecurityTypes =
+ new ArraySet<>();
/**
* Set the remote device ID.
*
- * @param deviceId Locally unique ID for this Instant Tether network.
+ * @param deviceId Locally unique ID for this Hotspot network.
* @return Returns the Builder object.
*/
@NonNull
@@ -110,12 +120,12 @@ public final class TetherNetwork implements Parcelable {
/**
* Sets information about the device providing connectivity.
*
- * @param deviceInfo The device information object.
+ * @param networkProviderInfo The device information object.
* @return Returns the Builder object.
*/
@NonNull
- public Builder setDeviceInfo(@NonNull DeviceInfo deviceInfo) {
- mDeviceInfo = deviceInfo;
+ public Builder setNetworkProviderInfo(@NonNull NetworkProviderInfo networkProviderInfo) {
+ mNetworkProviderInfo = networkProviderInfo;
return this;
}
@@ -126,7 +136,7 @@ public final class TetherNetwork implements Parcelable {
* @return Returns the Builder object.
*/
@NonNull
- public Builder setNetworkType(@NetworkType int networkType) {
+ public Builder setHostNetworkType(@NetworkType int networkType) {
mNetworkType = networkType;
return this;
}
@@ -168,28 +178,27 @@ public final class TetherNetwork implements Parcelable {
}
/**
- * Sets the hotspot security types supported by the remote device, or null if hotspot is
- * off.
+ * Adds a security type supported by the hotspot created by the remote device.
*
- * @param hotspotSecurityTypes The array of security types supported by the hotspot.
+ * @param hotspotSecurityType A security type supported by the hotspot.
* @return Returns the Builder object.
*/
@NonNull
- public Builder setHotspotSecurityTypes(@NonNull @SecurityType int[] hotspotSecurityTypes) {
- mHotspotSecurityTypes = hotspotSecurityTypes;
+ public Builder addHotspotSecurityType(@SecurityType int hotspotSecurityType) {
+ mHotspotSecurityTypes.add(hotspotSecurityType);
return this;
}
/**
- * Builds the {@link TetherNetwork} object.
+ * Builds the {@link HotspotNetwork} object.
*
- * @return Returns the built {@link TetherNetwork} object.
+ * @return Returns the built {@link HotspotNetwork} object.
*/
@NonNull
- public TetherNetwork build() {
- return new TetherNetwork(
+ public HotspotNetwork build() {
+ return new HotspotNetwork(
mDeviceId,
- mDeviceInfo,
+ mNetworkProviderInfo,
mNetworkType,
mNetworkName,
mHotspotSsid,
@@ -198,7 +207,7 @@ public final class TetherNetwork implements Parcelable {
}
}
- private static void validate(long deviceId, int networkType, String networkName) {
+ private static void validate(long deviceId, @NetworkType int networkType, String networkName) {
if (deviceId < 0) {
throw new IllegalArgumentException("DeviceId must be set");
}
@@ -211,30 +220,30 @@ public final class TetherNetwork implements Parcelable {
}
}
- private TetherNetwork(
+ private HotspotNetwork(
long deviceId,
- DeviceInfo deviceInfo,
+ NetworkProviderInfo networkProviderInfo,
@NetworkType int networkType,
@NonNull String networkName,
@Nullable String hotspotSsid,
@Nullable String hotspotBssid,
- @Nullable @SecurityType int[] hotspotSecurityTypes) {
+ @Nullable @SecurityType ArraySet<Integer> hotspotSecurityTypes) {
validate(deviceId,
networkType,
networkName);
mDeviceId = deviceId;
- mDeviceInfo = deviceInfo;
+ mNetworkProviderInfo = networkProviderInfo;
mNetworkType = networkType;
mNetworkName = networkName;
mHotspotSsid = hotspotSsid;
mHotspotBssid = hotspotBssid;
- mHotspotSecurityTypes = hotspotSecurityTypes;
+ mHotspotSecurityTypes = new ArraySet<>(hotspotSecurityTypes);
}
/**
* Gets the remote device ID.
*
- * @return Returns the locally unique ID for this Instant Tether network.
+ * @return Returns the locally unique ID for this Hotspot network.
*/
public long getDeviceId() {
return mDeviceId;
@@ -243,11 +252,11 @@ public final class TetherNetwork implements Parcelable {
/**
* Gets information about the device providing connectivity.
*
- * @return Returns the information of the device providing the Instant Tether network.
+ * @return Returns the information of the device providing the Hotspot network.
*/
@NonNull
- public DeviceInfo getDeviceInfo() {
- return mDeviceInfo;
+ public NetworkProviderInfo getNetworkProviderInfo() {
+ return mNetworkProviderInfo;
}
/**
@@ -256,7 +265,7 @@ public final class TetherNetwork implements Parcelable {
* @return Returns the network type as represented by IntDef {@link NetworkType}.
*/
@NetworkType
- public int getNetworkType() {
+ public int getHostNetworkType() {
return mNetworkType;
}
@@ -293,31 +302,31 @@ public final class TetherNetwork implements Parcelable {
/**
* Gets the hotspot security types supported by the remote device.
*
- * @return Returns the array of security types supported by the hotspot.
+ * @return Returns a set of the security types supported by the hotspot.
*/
- @Nullable
+ @NonNull
@SecurityType
- public int[] getHotspotSecurityTypes() {
+ public Set<Integer> getHotspotSecurityTypes() {
return mHotspotSecurityTypes;
}
@Override
public boolean equals(Object obj) {
- if (!(obj instanceof TetherNetwork)) return false;
- TetherNetwork other = (TetherNetwork) obj;
+ if (!(obj instanceof HotspotNetwork)) return false;
+ HotspotNetwork other = (HotspotNetwork) obj;
return mDeviceId == other.getDeviceId()
- && Objects.equals(mDeviceInfo, other.getDeviceInfo())
- && mNetworkType == other.getNetworkType()
+ && Objects.equals(mNetworkProviderInfo, other.getNetworkProviderInfo())
+ && mNetworkType == other.getHostNetworkType()
&& Objects.equals(mNetworkName, other.getNetworkName())
&& Objects.equals(mHotspotSsid, other.getHotspotSsid())
&& Objects.equals(mHotspotBssid, other.getHotspotBssid())
- && Arrays.equals(mHotspotSecurityTypes, other.getHotspotSecurityTypes());
+ && Objects.equals(mHotspotSecurityTypes, other.getHotspotSecurityTypes());
}
@Override
public int hashCode() {
- return Objects.hash(mDeviceId, mDeviceInfo, mNetworkName, mHotspotSsid, mHotspotBssid,
- Arrays.hashCode(mHotspotSecurityTypes));
+ return Objects.hash(mDeviceId, mNetworkProviderInfo, mNetworkName, mHotspotSsid,
+ mHotspotBssid, mHotspotSecurityTypes);
}
@Override
@@ -328,49 +337,49 @@ public final class TetherNetwork implements Parcelable {
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeLong(mDeviceId);
- mDeviceInfo.writeToParcel(dest, flags);
+ mNetworkProviderInfo.writeToParcel(dest, flags);
dest.writeInt(mNetworkType);
dest.writeString(mNetworkName);
dest.writeString(mHotspotSsid);
dest.writeString(mHotspotBssid);
- dest.writeIntArray(mHotspotSecurityTypes);
+ dest.writeArraySet(mHotspotSecurityTypes);
}
/**
- * Creates a {@link TetherNetwork} object from a parcel.
+ * Creates a {@link HotspotNetwork} object from a parcel.
*
* @hide
*/
@NonNull
- public static TetherNetwork readFromParcel(@NonNull Parcel in) {
- return new TetherNetwork(in.readLong(), DeviceInfo.readFromParcel(in),
+ public static HotspotNetwork readFromParcel(@NonNull Parcel in) {
+ return new HotspotNetwork(in.readLong(), NetworkProviderInfo.readFromParcel(in),
in.readInt(), in.readString(), in.readString(), in.readString(),
- in.createIntArray());
+ (ArraySet<Integer>) in.readArraySet(null));
}
@NonNull
- public static final Creator<TetherNetwork> CREATOR = new Creator<>() {
+ public static final Creator<HotspotNetwork> CREATOR = new Creator<>() {
@Override
- public TetherNetwork createFromParcel(Parcel in) {
+ public HotspotNetwork createFromParcel(Parcel in) {
return readFromParcel(in);
}
@Override
- public TetherNetwork[] newArray(int size) {
- return new TetherNetwork[size];
+ public HotspotNetwork[] newArray(int size) {
+ return new HotspotNetwork[size];
}
};
@Override
public String toString() {
- return new StringBuilder("TetherNetwork[")
+ return new StringBuilder("HotspotNetwork[")
.append("deviceId=").append(mDeviceId)
.append(", networkType=").append(mNetworkType)
- .append(", deviceInfo=").append(mDeviceInfo.toString())
+ .append(", networkProviderInfo=").append(mNetworkProviderInfo.toString())
.append(", networkName=").append(mNetworkName)
.append(", hotspotSsid=").append(mHotspotSsid)
.append(", hotspotBssid=").append(mHotspotBssid)
- .append(", hotspotSecurityTypes=").append(Arrays.toString(mHotspotSecurityTypes))
+ .append(", hotspotSecurityTypes=").append(mHotspotSecurityTypes.toString())
.append("]").toString();
}
}
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatus.aidl b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatus.aidl
index c677a6c508ad..d32d15e7c058 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatus.aidl
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatus.aidl
@@ -16,4 +16,4 @@
package android.net.wifi.sharedconnectivity.app;
-parcelable TetherNetworkConnectionStatus;
+parcelable HotspotNetworkConnectionStatus;
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatus.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatus.java
index 3cf44ed3ed32..69767f302bd8 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatus.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatus.java
@@ -28,23 +28,23 @@ import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
/**
- * The status of a connection to an instant tether network after the client called
- * {@link SharedConnectivityManager#connectTetherNetwork}.
+ * The status of a connection to a hotspot network after the client called
+ * {@link SharedConnectivityManager#connectHotspotNetwork}.
*
* @hide
*/
@SystemApi
-public final class TetherNetworkConnectionStatus implements Parcelable {
+public final class HotspotNetworkConnectionStatus implements Parcelable {
/**
* Connection status is unknown.
*/
- public static final int CONNECTION_STATUS_UNKNOWN = 0;
+ public static final int CONNECTION_STATUS_UNKNOWN = 0;
/**
* The connection is being initiated.
*/
- public static final int CONNECTION_STATUS_ENABLING_HOTSPOT = 1;
+ public static final int CONNECTION_STATUS_ENABLING_HOTSPOT = 1;
/**
* Device providing the hotspot failed to initiate it.
@@ -102,22 +102,23 @@ public final class TetherNetworkConnectionStatus implements Parcelable {
CONNECTION_STATUS_ENABLING_HOTSPOT_TIMEOUT,
CONNECTION_STATUS_CONNECT_TO_HOTSPOT_FAILED,
})
- public @interface ConnectionStatus {}
+ public @interface ConnectionStatus {
+ }
- @ConnectionStatus private final int mStatus;
- private final TetherNetwork mTetherNetwork;
+ @ConnectionStatus
+ private final int mStatus;
+ private final HotspotNetwork mHotspotNetwork;
private final Bundle mExtras;
/**
- * Builder class for {@link TetherNetworkConnectionStatus}.
+ * Builder class for {@link HotspotNetworkConnectionStatus}.
*/
public static final class Builder {
- @ConnectionStatus private int mStatus;
- private TetherNetwork mTetherNetwork;
+ @ConnectionStatus
+ private int mStatus;
+ private HotspotNetwork mHotspotNetwork;
private Bundle mExtras;
- public Builder() {}
-
/**
* Sets the status of the connection
*
@@ -130,13 +131,13 @@ public final class TetherNetworkConnectionStatus implements Parcelable {
}
/**
- * Sets the {@link TetherNetwork} object of the connection.
+ * Sets the {@link HotspotNetwork} object of the connection.
*
* @return Returns the Builder object.
*/
@NonNull
- public Builder setTetherNetwork(@NonNull TetherNetwork tetherNetwork) {
- mTetherNetwork = tetherNetwork;
+ public Builder setHotspotNetwork(@NonNull HotspotNetwork hotspotNetwork) {
+ mHotspotNetwork = hotspotNetwork;
return this;
}
@@ -152,20 +153,36 @@ public final class TetherNetworkConnectionStatus implements Parcelable {
}
/**
- * Builds the {@link TetherNetworkConnectionStatus} object.
+ * Builds the {@link HotspotNetworkConnectionStatus} object.
*
- * @return Returns the built {@link TetherNetworkConnectionStatus} object.
+ * @return Returns the built {@link HotspotNetworkConnectionStatus} object.
*/
@NonNull
- public TetherNetworkConnectionStatus build() {
- return new TetherNetworkConnectionStatus(mStatus, mTetherNetwork, mExtras);
+ public HotspotNetworkConnectionStatus build() {
+ return new HotspotNetworkConnectionStatus(mStatus, mHotspotNetwork, mExtras);
+ }
+ }
+
+ private static void validate(@ConnectionStatus int status) {
+ if (status != CONNECTION_STATUS_UNKNOWN
+ && status != CONNECTION_STATUS_ENABLING_HOTSPOT
+ && status != CONNECTION_STATUS_UNKNOWN_ERROR
+ && status != CONNECTION_STATUS_PROVISIONING_FAILED
+ && status != CONNECTION_STATUS_TETHERING_TIMEOUT
+ && status != CONNECTION_STATUS_TETHERING_UNSUPPORTED
+ && status != CONNECTION_STATUS_NO_CELL_DATA
+ && status != CONNECTION_STATUS_ENABLING_HOTSPOT_FAILED
+ && status != CONNECTION_STATUS_ENABLING_HOTSPOT_TIMEOUT
+ && status != CONNECTION_STATUS_CONNECT_TO_HOTSPOT_FAILED) {
+ throw new IllegalArgumentException("Illegal connection status");
}
}
- private TetherNetworkConnectionStatus(@ConnectionStatus int status, TetherNetwork tetherNetwork,
- Bundle extras) {
+ private HotspotNetworkConnectionStatus(@ConnectionStatus int status,
+ HotspotNetwork hotspotNetwork, Bundle extras) {
+ validate(status);
mStatus = status;
- mTetherNetwork = tetherNetwork;
+ mHotspotNetwork = hotspotNetwork;
mExtras = extras;
}
@@ -180,13 +197,13 @@ public final class TetherNetworkConnectionStatus implements Parcelable {
}
/**
- * Gets the {@link TetherNetwork} object of the connection.
+ * Gets the {@link HotspotNetwork} object of the connection.
*
- * @return Returns a TetherNetwork object.
+ * @return Returns a HotspotNetwork object.
*/
@NonNull
- public TetherNetwork getTetherNetwork() {
- return mTetherNetwork;
+ public HotspotNetwork getHotspotNetwork() {
+ return mHotspotNetwork;
}
/**
@@ -201,15 +218,15 @@ public final class TetherNetworkConnectionStatus implements Parcelable {
@Override
public boolean equals(Object obj) {
- if (!(obj instanceof TetherNetworkConnectionStatus)) return false;
- TetherNetworkConnectionStatus other = (TetherNetworkConnectionStatus) obj;
+ if (!(obj instanceof HotspotNetworkConnectionStatus)) return false;
+ HotspotNetworkConnectionStatus other = (HotspotNetworkConnectionStatus) obj;
return mStatus == other.getStatus()
- && Objects.equals(mTetherNetwork, other.getTetherNetwork());
+ && Objects.equals(mHotspotNetwork, other.getHotspotNetwork());
}
@Override
public int hashCode() {
- return Objects.hash(mStatus, mTetherNetwork);
+ return Objects.hash(mStatus, mHotspotNetwork);
}
@Override
@@ -220,39 +237,39 @@ public final class TetherNetworkConnectionStatus implements Parcelable {
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mStatus);
- mTetherNetwork.writeToParcel(dest, flags);
+ mHotspotNetwork.writeToParcel(dest, flags);
dest.writeBundle(mExtras);
}
/**
- * Creates a {@link TetherNetworkConnectionStatus} object from a parcel.
+ * Creates a {@link HotspotNetworkConnectionStatus} object from a parcel.
*
* @hide
*/
@NonNull
- public static TetherNetworkConnectionStatus readFromParcel(@NonNull Parcel in) {
- return new TetherNetworkConnectionStatus(in.readInt(),
- TetherNetwork.readFromParcel(in), in.readBundle());
+ public static HotspotNetworkConnectionStatus readFromParcel(@NonNull Parcel in) {
+ return new HotspotNetworkConnectionStatus(in.readInt(),
+ HotspotNetwork.readFromParcel(in), in.readBundle());
}
@NonNull
- public static final Creator<TetherNetworkConnectionStatus> CREATOR = new Creator<>() {
+ public static final Creator<HotspotNetworkConnectionStatus> CREATOR = new Creator<>() {
@Override
- public TetherNetworkConnectionStatus createFromParcel(Parcel in) {
+ public HotspotNetworkConnectionStatus createFromParcel(Parcel in) {
return readFromParcel(in);
}
@Override
- public TetherNetworkConnectionStatus[] newArray(int size) {
- return new TetherNetworkConnectionStatus[size];
+ public HotspotNetworkConnectionStatus[] newArray(int size) {
+ return new HotspotNetworkConnectionStatus[size];
}
};
@Override
public String toString() {
- return new StringBuilder("TetherNetworkConnectionStatus[")
+ return new StringBuilder("HotspotNetworkConnectionStatus[")
.append("status=").append(mStatus)
- .append("tether network=").append(mTetherNetwork.toString())
+ .append("hotspot network=").append(mHotspotNetwork.toString())
.append("extras=").append(mExtras.toString())
.append("]").toString();
}
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetwork.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetwork.java
index 161c83ce2fab..64412bc55fb2 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetwork.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetwork.java
@@ -20,15 +20,17 @@ import static android.net.wifi.WifiAnnotations.SecurityType;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
+import android.util.ArraySet;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.Arrays;
import java.util.Objects;
+import java.util.Set;
/**
* A data class representing a known Wi-Fi network.
@@ -37,41 +39,51 @@ import java.util.Objects;
*/
@SystemApi
public final class KnownNetwork implements Parcelable {
+
+ /**
+ * Network source is unknown.
+ */
+ public static final int NETWORK_SOURCE_UNKNOWN = 0;
+
/**
* Network is known by a nearby device with the same user account.
*/
- public static final int NETWORK_SOURCE_NEARBY_SELF = 0;
+ public static final int NETWORK_SOURCE_NEARBY_SELF = 1;
/**
* Network is known via cloud storage associated with this device's user account.
*/
- public static final int NETWORK_SOURCE_CLOUD_SELF = 1;
+ public static final int NETWORK_SOURCE_CLOUD_SELF = 2;
/**
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef({
+ NETWORK_SOURCE_UNKNOWN,
NETWORK_SOURCE_NEARBY_SELF,
NETWORK_SOURCE_CLOUD_SELF
})
- public @interface NetworkSource {}
+ public @interface NetworkSource {
+ }
- @NetworkSource private final int mNetworkSource;
+ @NetworkSource
+ private final int mNetworkSource;
private final String mSsid;
- @SecurityType private final int[] mSecurityTypes;
- private final DeviceInfo mDeviceInfo;
+ @SecurityType
+ private final ArraySet<Integer> mSecurityTypes;
+ private final NetworkProviderInfo mNetworkProviderInfo;
/**
* Builder class for {@link KnownNetwork}.
*/
public static final class Builder {
- @NetworkSource private int mNetworkSource = -1;
+ @NetworkSource
+ private int mNetworkSource = -1;
private String mSsid;
- @SecurityType private int[] mSecurityTypes;
- private android.net.wifi.sharedconnectivity.app.DeviceInfo mDeviceInfo;
-
- public Builder() {}
+ @SecurityType
+ private final ArraySet<Integer> mSecurityTypes = new ArraySet<>();
+ private NetworkProviderInfo mNetworkProviderInfo;
/**
* Sets the indicated source of the known network.
@@ -98,26 +110,27 @@ public final class KnownNetwork implements Parcelable {
}
/**
- * Sets the security types of the known network.
+ * Adds a security type of the known network.
*
- * @param securityTypes The array of security types supported by the known network.
+ * @param securityType A security type supported by the known network.
* @return Returns the Builder object.
*/
@NonNull
- public Builder setSecurityTypes(@NonNull @SecurityType int[] securityTypes) {
- mSecurityTypes = securityTypes;
+ public Builder addSecurityType(@SecurityType int securityType) {
+ mSecurityTypes.add(securityType);
return this;
}
/**
* Sets the device information of the device providing connectivity.
+ * Must be set if network source is {@link KnownNetwork#NETWORK_SOURCE_NEARBY_SELF}.
*
- * @param deviceInfo The device information object.
+ * @param networkProviderInfo The device information object.
* @return Returns the Builder object.
*/
@NonNull
- public Builder setDeviceInfo(@NonNull DeviceInfo deviceInfo) {
- mDeviceInfo = deviceInfo;
+ public Builder setNetworkProviderInfo(@Nullable NetworkProviderInfo networkProviderInfo) {
+ mNetworkProviderInfo = networkProviderInfo;
return this;
}
@@ -132,33 +145,40 @@ public final class KnownNetwork implements Parcelable {
mNetworkSource,
mSsid,
mSecurityTypes,
- mDeviceInfo);
+ mNetworkProviderInfo);
}
}
- private static void validate(int networkSource, String ssid, int [] securityTypes) {
- if (networkSource != NETWORK_SOURCE_CLOUD_SELF && networkSource
- != NETWORK_SOURCE_NEARBY_SELF) {
+ private static void validate(@NetworkSource int networkSource, String ssid,
+ @SecurityType Set<Integer> securityTypes,
+ NetworkProviderInfo networkProviderInfo) {
+ if (networkSource != NETWORK_SOURCE_UNKNOWN
+ && networkSource != NETWORK_SOURCE_CLOUD_SELF
+ && networkSource != NETWORK_SOURCE_NEARBY_SELF) {
throw new IllegalArgumentException("Illegal network source");
}
if (TextUtils.isEmpty(ssid)) {
throw new IllegalArgumentException("SSID must be set");
}
- if (securityTypes == null || securityTypes.length == 0) {
+ if (securityTypes.isEmpty()) {
throw new IllegalArgumentException("SecurityTypes must be set");
}
+ if (networkSource == NETWORK_SOURCE_NEARBY_SELF && networkProviderInfo == null) {
+ throw new IllegalArgumentException("Device info must be provided when network source"
+ + " is NETWORK_SOURCE_NEARBY_SELF");
+ }
}
private KnownNetwork(
@NetworkSource int networkSource,
@NonNull String ssid,
- @NonNull @SecurityType int[] securityTypes,
- @NonNull DeviceInfo deviceInfo) {
- validate(networkSource, ssid, securityTypes);
+ @NonNull @SecurityType ArraySet<Integer> securityTypes,
+ @Nullable NetworkProviderInfo networkProviderInfo) {
+ validate(networkSource, ssid, securityTypes, networkProviderInfo);
mNetworkSource = networkSource;
mSsid = ssid;
- mSecurityTypes = securityTypes;
- mDeviceInfo = deviceInfo;
+ mSecurityTypes = new ArraySet<>(securityTypes);
+ mNetworkProviderInfo = networkProviderInfo;
}
/**
@@ -184,22 +204,23 @@ public final class KnownNetwork implements Parcelable {
/**
* Gets the security types of the known network.
*
- * @return Returns the array of security types supported by the known network.
+ * @return Returns a set with security types supported by the known network.
*/
@NonNull
@SecurityType
- public int[] getSecurityTypes() {
+ public Set<Integer> getSecurityTypes() {
return mSecurityTypes;
}
/**
* Gets the device information of the device providing connectivity.
*
- * @return Returns the information of the device providing the known network.
+ * @return Returns the information of the device providing the known network. Can be null if the
+ * network source is cloud or unknown.
*/
- @NonNull
- public DeviceInfo getDeviceInfo() {
- return mDeviceInfo;
+ @Nullable
+ public NetworkProviderInfo getNetworkProviderInfo() {
+ return mNetworkProviderInfo;
}
@Override
@@ -208,14 +229,13 @@ public final class KnownNetwork implements Parcelable {
KnownNetwork other = (KnownNetwork) obj;
return mNetworkSource == other.getNetworkSource()
&& Objects.equals(mSsid, other.getSsid())
- && Arrays.equals(mSecurityTypes, other.getSecurityTypes())
- && Objects.equals(mDeviceInfo, other.getDeviceInfo());
+ && Objects.equals(mSecurityTypes, other.getSecurityTypes())
+ && Objects.equals(mNetworkProviderInfo, other.getNetworkProviderInfo());
}
@Override
public int hashCode() {
- return Objects.hash(mNetworkSource, mSsid, Arrays.hashCode(mSecurityTypes),
- mDeviceInfo.hashCode());
+ return Objects.hash(mNetworkSource, mSsid, mSecurityTypes, mNetworkProviderInfo);
}
@Override
@@ -227,8 +247,8 @@ public final class KnownNetwork implements Parcelable {
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mNetworkSource);
dest.writeString(mSsid);
- dest.writeIntArray(mSecurityTypes);
- mDeviceInfo.writeToParcel(dest, flags);
+ dest.writeArraySet(mSecurityTypes);
+ mNetworkProviderInfo.writeToParcel(dest, flags);
}
/**
@@ -238,8 +258,9 @@ public final class KnownNetwork implements Parcelable {
*/
@NonNull
public static KnownNetwork readFromParcel(@NonNull Parcel in) {
- return new KnownNetwork(in.readInt(), in.readString(), in.createIntArray(),
- DeviceInfo.readFromParcel(in));
+ return new KnownNetwork(in.readInt(), in.readString(),
+ (ArraySet<Integer>) in.readArraySet(null),
+ NetworkProviderInfo.readFromParcel(in));
}
@NonNull
@@ -260,8 +281,8 @@ public final class KnownNetwork implements Parcelable {
return new StringBuilder("KnownNetwork[")
.append("NetworkSource=").append(mNetworkSource)
.append(", ssid=").append(mSsid)
- .append(", securityTypes=").append(Arrays.toString(mSecurityTypes))
- .append(", deviceInfo=").append(mDeviceInfo.toString())
+ .append(", securityTypes=").append(mSecurityTypes.toString())
+ .append(", networkProviderInfo=").append(mNetworkProviderInfo.toString())
.append("]").toString();
}
}
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatus.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatus.java
index b2f04ff49195..6bd0a5ecd4c8 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatus.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatus.java
@@ -120,8 +120,16 @@ public final class KnownNetworkConnectionStatus implements Parcelable {
}
}
+ private static void validate(@ConnectionStatus int status) {
+ if (status != CONNECTION_STATUS_UNKNOWN && status != CONNECTION_STATUS_SAVED
+ && status != CONNECTION_STATUS_SAVE_FAILED) {
+ throw new IllegalArgumentException("Illegal connection status");
+ }
+ }
+
private KnownNetworkConnectionStatus(@ConnectionStatus int status, KnownNetwork knownNetwork,
Bundle extras) {
+ validate(status);
mStatus = status;
mKnownNetwork = knownNetwork;
mExtras = extras;
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetwork.aidl b/wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.aidl
index 6cc4cfe7dce5..f3cbbc2963a3 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetwork.aidl
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.aidl
@@ -16,4 +16,4 @@
package android.net.wifi.sharedconnectivity.app;
-parcelable TetherNetwork;
+parcelable NetworkProviderInfo; \ No newline at end of file
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.java
index 52abf33bc761..ed4d699ad4de 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.java
@@ -36,7 +36,7 @@ import java.util.Objects;
* @hide
*/
@SystemApi
-public final class DeviceInfo implements Parcelable {
+public final class NetworkProviderInfo implements Parcelable {
/**
* Device type providing connectivity is unknown.
@@ -59,6 +59,16 @@ public final class DeviceInfo implements Parcelable {
public static final int DEVICE_TYPE_LAPTOP = 3;
/**
+ * Device providing connectivity is a watch.
+ */
+ public static final int DEVICE_TYPE_WATCH = 4;
+
+ /**
+ * Device providing connectivity is a watch.
+ */
+ public static final int DEVICE_TYPE_AUTO = 5;
+
+ /**
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
@@ -66,18 +76,22 @@ public final class DeviceInfo implements Parcelable {
DEVICE_TYPE_UNKNOWN,
DEVICE_TYPE_PHONE,
DEVICE_TYPE_TABLET,
- DEVICE_TYPE_LAPTOP
+ DEVICE_TYPE_LAPTOP,
+ DEVICE_TYPE_WATCH,
+ DEVICE_TYPE_AUTO
})
- public @interface DeviceType {}
+ public @interface DeviceType {
+ }
- @DeviceType private final int mDeviceType;
+ @DeviceType
+ private final int mDeviceType;
private final String mDeviceName;
private final String mModelName;
private final int mBatteryPercentage;
private final int mConnectionStrength;
/**
- * Builder class for {@link DeviceInfo}.
+ * Builder class for {@link NetworkProviderInfo}.
*/
public static final class Builder {
private int mDeviceType;
@@ -86,7 +100,12 @@ public final class DeviceInfo implements Parcelable {
private int mBatteryPercentage;
private int mConnectionStrength;
- public Builder() {}
+ public Builder(@NonNull String deviceName, @NonNull String modelName) {
+ Objects.requireNonNull(deviceName);
+ Objects.requireNonNull(modelName);
+ mDeviceName = deviceName;
+ mModelName = modelName;
+ }
/**
* Sets the device type that provides connectivity.
@@ -108,6 +127,7 @@ public final class DeviceInfo implements Parcelable {
*/
@NonNull
public Builder setDeviceName(@NonNull String deviceName) {
+ Objects.requireNonNull(deviceName);
mDeviceName = deviceName;
return this;
}
@@ -120,6 +140,7 @@ public final class DeviceInfo implements Parcelable {
*/
@NonNull
public Builder setModelName(@NonNull String modelName) {
+ Objects.requireNonNull(modelName);
mModelName = modelName;
return this;
}
@@ -149,29 +170,24 @@ public final class DeviceInfo implements Parcelable {
}
/**
- * Builds the {@link DeviceInfo} object.
+ * Builds the {@link NetworkProviderInfo} object.
*
- * @return Returns the built {@link DeviceInfo} object.
+ * @return Returns the built {@link NetworkProviderInfo} object.
*/
@NonNull
- public DeviceInfo build() {
- return new DeviceInfo(mDeviceType, mDeviceName, mModelName, mBatteryPercentage,
+ public NetworkProviderInfo build() {
+ return new NetworkProviderInfo(mDeviceType, mDeviceName, mModelName, mBatteryPercentage,
mConnectionStrength);
}
}
- private static void validate(int deviceType, String deviceName, String modelName,
+ private static void validate(@DeviceType int deviceType, String deviceName, String modelName,
int batteryPercentage, int connectionStrength) {
if (deviceType != DEVICE_TYPE_UNKNOWN && deviceType != DEVICE_TYPE_PHONE
- && deviceType != DEVICE_TYPE_TABLET && deviceType != DEVICE_TYPE_LAPTOP) {
+ && deviceType != DEVICE_TYPE_TABLET && deviceType != DEVICE_TYPE_LAPTOP
+ && deviceType != DEVICE_TYPE_WATCH && deviceType != DEVICE_TYPE_AUTO) {
throw new IllegalArgumentException("Illegal device type");
}
- if (Objects.isNull(deviceName)) {
- throw new IllegalArgumentException("DeviceName must be set");
- }
- if (Objects.isNull(modelName)) {
- throw new IllegalArgumentException("ModelName must be set");
- }
if (batteryPercentage < 0 || batteryPercentage > 100) {
throw new IllegalArgumentException("BatteryPercentage must be in range 0-100");
}
@@ -180,7 +196,7 @@ public final class DeviceInfo implements Parcelable {
}
}
- private DeviceInfo(@DeviceType int deviceType, @NonNull String deviceName,
+ private NetworkProviderInfo(@DeviceType int deviceType, @NonNull String deviceName,
@NonNull String modelName, int batteryPercentage, int connectionStrength) {
validate(deviceType, deviceName, modelName, batteryPercentage, connectionStrength);
mDeviceType = deviceType;
@@ -242,8 +258,8 @@ public final class DeviceInfo implements Parcelable {
@Override
public boolean equals(Object obj) {
- if (!(obj instanceof DeviceInfo)) return false;
- DeviceInfo other = (DeviceInfo) obj;
+ if (!(obj instanceof NetworkProviderInfo)) return false;
+ NetworkProviderInfo other = (NetworkProviderInfo) obj;
return mDeviceType == other.getDeviceType()
&& Objects.equals(mDeviceName, other.mDeviceName)
&& Objects.equals(mModelName, other.mModelName)
@@ -256,6 +272,7 @@ public final class DeviceInfo implements Parcelable {
return Objects.hash(mDeviceType, mDeviceName, mModelName, mBatteryPercentage,
mConnectionStrength);
}
+
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mDeviceType);
@@ -271,32 +288,32 @@ public final class DeviceInfo implements Parcelable {
}
/**
- * Creates a {@link DeviceInfo} object from a parcel.
+ * Creates a {@link NetworkProviderInfo} object from a parcel.
*
* @hide
*/
@NonNull
- public static DeviceInfo readFromParcel(@NonNull Parcel in) {
- return new DeviceInfo(in.readInt(), in.readString(), in.readString(), in.readInt(),
+ public static NetworkProviderInfo readFromParcel(@NonNull Parcel in) {
+ return new NetworkProviderInfo(in.readInt(), in.readString(), in.readString(), in.readInt(),
in.readInt());
}
@NonNull
- public static final Creator<DeviceInfo> CREATOR = new Creator<DeviceInfo>() {
+ public static final Creator<NetworkProviderInfo> CREATOR = new Creator<NetworkProviderInfo>() {
@Override
- public DeviceInfo createFromParcel(Parcel in) {
+ public NetworkProviderInfo createFromParcel(Parcel in) {
return readFromParcel(in);
}
@Override
- public DeviceInfo[] newArray(int size) {
- return new DeviceInfo[size];
+ public NetworkProviderInfo[] newArray(int size) {
+ return new NetworkProviderInfo[size];
}
};
@Override
public String toString() {
- return new StringBuilder("DeviceInfo[")
+ return new StringBuilder("NetworkProviderInfo[")
.append("deviceType=").append(mDeviceType)
.append(", deviceName=").append(mDeviceName)
.append(", modelName=").append(mModelName)
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityClientCallback.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityClientCallback.java
index d2b9be783bca..eb04df64d6d0 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityClientCallback.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityClientCallback.java
@@ -32,14 +32,16 @@ import java.util.List;
public interface SharedConnectivityClientCallback {
/**
* This method is being called by {@link SharedConnectivityService} to notify of a change in the
- * list of available Tether Networks.
- * @param networks Updated Tether Network list.
+ * list of available Hotspot Networks.
+ *
+ * @param networks Updated Hotspot Network list.
*/
- void onTetherNetworksUpdated(@NonNull List<TetherNetwork> networks);
+ void onHotspotNetworksUpdated(@NonNull List<HotspotNetwork> networks);
/**
* This method is being called by {@link SharedConnectivityService} to notify of a change in the
* list of available Known Networks.
+ *
* @param networks Updated Known Network list.
*/
void onKnownNetworksUpdated(@NonNull List<KnownNetwork> networks);
@@ -47,20 +49,23 @@ public interface SharedConnectivityClientCallback {
/**
* This method is being called by {@link SharedConnectivityService} to notify of a change in the
* state of share connectivity settings.
+ *
* @param state The new state.
*/
void onSharedConnectivitySettingsChanged(@NonNull SharedConnectivitySettingsState state);
/**
* This method is being called by {@link SharedConnectivityService} to notify of a change in the
- * status of the current tether network connection.
+ * status of the current hotspot network connection.
+ *
* @param status The new status.
*/
- void onTetherNetworkConnectionStatusChanged(@NonNull TetherNetworkConnectionStatus status);
+ void onHotspotNetworkConnectionStatusChanged(@NonNull HotspotNetworkConnectionStatus status);
/**
* This method is being called by {@link SharedConnectivityService} to notify of a change in the
* status of the current known network connection.
+ *
* @param status The new status.
*/
void onKnownNetworkConnectionStatusChanged(@NonNull KnownNetworkConnectionStatus status);
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java
index 9593c8ae77a8..684b385d60e8 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java
@@ -19,6 +19,8 @@ package android.net.wifi.sharedconnectivity.app;
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.content.ComponentName;
@@ -47,7 +49,7 @@ import java.util.concurrent.Executor;
* This class is the library used by consumers of Shared Connectivity data to bind to the service,
* receive callbacks from, and send user actions to the service.
*
- * The methods {@link #connectTetherNetwork}, {@link #disconnectTetherNetwork},
+ * The methods {@link #connectHotspotNetwork}, {@link #disconnectHotspotNetwork},
* {@link #connectKnownNetwork} and {@link #forgetKnownNetwork} are not valid and will return false
* if not called between {@link SharedConnectivityClientCallback#onServiceConnected()}
* and {@link SharedConnectivityClientCallback#onServiceDisconnected()} or if
@@ -72,12 +74,11 @@ public class SharedConnectivityManager {
mCallback = callback;
}
- @Override
- public void onTetherNetworksUpdated(@NonNull List<TetherNetwork> networks) {
+ public void onHotspotNetworksUpdated(@NonNull List<HotspotNetwork> networks) {
if (mCallback != null) {
final long token = Binder.clearCallingIdentity();
try {
- mExecutor.execute(() -> mCallback.onTetherNetworksUpdated(networks));
+ mExecutor.execute(() -> mCallback.onHotspotNetworksUpdated(networks));
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -109,14 +110,13 @@ public class SharedConnectivityManager {
}
}
- @Override
- public void onTetherNetworkConnectionStatusChanged(
- @NonNull TetherNetworkConnectionStatus status) {
+ public void onHotspotNetworkConnectionStatusChanged(
+ @NonNull HotspotNetworkConnectionStatus status) {
if (mCallback != null) {
final long token = Binder.clearCallingIdentity();
try {
mExecutor.execute(() ->
- mCallback.onTetherNetworkConnectionStatusChanged(status));
+ mCallback.onHotspotNetworkConnectionStatusChanged(status));
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -150,7 +150,7 @@ public class SharedConnectivityManager {
* Creates a new instance of {@link SharedConnectivityManager}.
*
* Automatically binds to implementation of {@link SharedConnectivityService} specified in
- * device overlay.
+ * the device overlay.
*
* @return An instance of {@link SharedConnectivityManager} or null if the shared connectivity
* service is not found.
@@ -172,6 +172,17 @@ public class SharedConnectivityManager {
return null;
}
+ /**
+ * @hide
+ */
+ @SuppressLint("ManagerLookup")
+ @TestApi
+ @Nullable
+ public static SharedConnectivityManager create(@NonNull Context context,
+ @NonNull String servicePackageName, @NonNull String serviceIntentAction) {
+ return new SharedConnectivityManager(context, servicePackageName, serviceIntentAction);
+ }
+
private SharedConnectivityManager(@NonNull Context context, String servicePackageName,
String serviceIntentAction) {
mServiceConnection = new ServiceConnection() {
@@ -180,9 +191,9 @@ public class SharedConnectivityManager {
mService = ISharedConnectivityService.Stub.asInterface(service);
if (!mCallbackProxyCache.isEmpty()) {
synchronized (mCallbackProxyCache) {
- mCallbackProxyCache.keySet().forEach(callback -> {
- registerCallbackInternal(callback, mCallbackProxyCache.get(callback));
- });
+ mCallbackProxyCache.keySet().forEach(callback ->
+ registerCallbackInternal(
+ callback, mCallbackProxyCache.get(callback)));
mCallbackProxyCache.clear();
}
}
@@ -246,15 +257,18 @@ public class SharedConnectivityManager {
}
/**
- * Registers a callback for receiving updates to the list of Tether Networks and Known Networks.
+ * Registers a callback for receiving updates to the list of Hotspot Networks, Known Networks,
+ * shared connectivity settings state, hotspot network connection status and known network
+ * connection status.
* The {@link SharedConnectivityClientCallback#onRegisterCallbackFailed} will be called if the
* registration failed.
*
* @param executor The Executor used to invoke the callback.
* @param callback The callback of type {@link SharedConnectivityClientCallback} that is invoked
- * when the service updates either the list of Tether Networks or Known
- * Networks.
+ * when the service updates its data.
*/
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
public void registerCallback(@NonNull @CallbackExecutor Executor executor,
@NonNull SharedConnectivityClientCallback callback) {
Objects.requireNonNull(executor, "executor cannot be null");
@@ -283,6 +297,8 @@ public class SharedConnectivityManager {
*
* @return Returns true if the callback was successfully unregistered, false otherwise.
*/
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
public boolean unregisterCallback(
@NonNull SharedConnectivityClientCallback callback) {
Objects.requireNonNull(callback, "callback cannot be null");
@@ -311,26 +327,28 @@ public class SharedConnectivityManager {
return true;
}
- /**
+ /**
* Send command to the implementation of {@link SharedConnectivityService} requesting connection
- * to the specified Tether Network.
+ * to the specified Hotspot Network.
*
- * @param network {@link TetherNetwork} object representing the network the user has requested
+ * @param network {@link HotspotNetwork} object representing the network the user has requested
* a connection to.
* @return Returns true if the service received the command. Does not guarantee that the
- * connection was successful.
+ * connection was successful.
*/
- public boolean connectTetherNetwork(@NonNull TetherNetwork network) {
- Objects.requireNonNull(network, "Tether network cannot be null");
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
+ public boolean connectHotspotNetwork(@NonNull HotspotNetwork network) {
+ Objects.requireNonNull(network, "Hotspot network cannot be null");
if (mService == null) {
return false;
}
try {
- mService.connectTetherNetwork(network);
+ mService.connectHotspotNetwork(network);
} catch (RemoteException e) {
- Log.e(TAG, "Exception in connectTetherNetwork", e);
+ Log.e(TAG, "Exception in connectHotspotNetwork", e);
return false;
}
return true;
@@ -338,22 +356,24 @@ public class SharedConnectivityManager {
/**
* Send command to the implementation of {@link SharedConnectivityService} requesting
- * disconnection from the active Tether Network.
+ * disconnection from the active Hotspot Network.
*
- * @param network {@link TetherNetwork} object representing the network the user has requested
+ * @param network {@link HotspotNetwork} object representing the network the user has requested
* to disconnect from.
* @return Returns true if the service received the command. Does not guarantee that the
- * disconnection was successful.
+ * disconnection was successful.
*/
- public boolean disconnectTetherNetwork(@NonNull TetherNetwork network) {
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
+ public boolean disconnectHotspotNetwork(@NonNull HotspotNetwork network) {
if (mService == null) {
return false;
}
try {
- mService.disconnectTetherNetwork(network);
+ mService.disconnectHotspotNetwork(network);
} catch (RemoteException e) {
- Log.e(TAG, "Exception in disconnectTetherNetwork", e);
+ Log.e(TAG, "Exception in disconnectHotspotNetwork", e);
return false;
}
return true;
@@ -366,8 +386,10 @@ public class SharedConnectivityManager {
* @param network {@link KnownNetwork} object representing the network the user has requested
* a connection to.
* @return Returns true if the service received the command. Does not guarantee that the
- * connection was successful.
+ * connection was successful.
*/
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
public boolean connectKnownNetwork(@NonNull KnownNetwork network) {
Objects.requireNonNull(network, "Known network cannot be null");
@@ -389,8 +411,10 @@ public class SharedConnectivityManager {
* the specified Known Network from the list of Known Networks.
*
* @return Returns true if the service received the command. Does not guarantee that the
- * forget action was successful.
+ * forget action was successful.
*/
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
public boolean forgetKnownNetwork(@NonNull KnownNetwork network) {
Objects.requireNonNull(network, "Known network cannot be null");
@@ -406,4 +430,114 @@ public class SharedConnectivityManager {
}
return true;
}
+
+ /**
+ * Gets the list of hotspot networks the user can select to connect to.
+ *
+ * @return Returns a {@link List} of {@link HotspotNetwork} objects, empty list on failure.
+ */
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
+ @NonNull
+ public List<HotspotNetwork> getHotspotNetworks() {
+ if (mService == null) {
+ return List.of();
+ }
+
+ try {
+ return mService.getHotspotNetworks();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Exception in getHotspotNetworks", e);
+ }
+ return List.of();
+ }
+
+ /**
+ * Gets the list of known networks the user can select to connect to.
+ *
+ * @return Returns a {@link List} of {@link KnownNetwork} objects, empty list on failure.
+ */
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
+ @NonNull
+ public List<KnownNetwork> getKnownNetworks() {
+ if (mService == null) {
+ return List.of();
+ }
+
+ try {
+ return mService.getKnownNetworks();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Exception in getKnownNetworks", e);
+ }
+ return List.of();
+ }
+
+ /**
+ * Gets the shared connectivity settings state.
+ *
+ * @return Returns a {@link SharedConnectivitySettingsState} object with the state, null on
+ * failure.
+ */
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
+ @Nullable
+ public SharedConnectivitySettingsState getSettingsState() {
+ if (mService == null) {
+ return null;
+ }
+
+ try {
+ return mService.getSettingsState();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Exception in getSettingsState", e);
+ }
+ return null;
+ }
+
+ /**
+ * Gets the connection status of the hotspot network the user selected to connect to.
+ *
+ * @return Returns a {@link HotspotNetworkConnectionStatus} object with the connection status,
+ * null on failure. If no connection is active the status will be
+ * {@link HotspotNetworkConnectionStatus#CONNECTION_STATUS_UNKNOWN}.
+ */
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
+ @Nullable
+ public HotspotNetworkConnectionStatus getHotspotNetworkConnectionStatus() {
+ if (mService == null) {
+ return null;
+ }
+
+ try {
+ return mService.getHotspotNetworkConnectionStatus();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Exception in getHotspotNetworkConnectionStatus", e);
+ }
+ return null;
+ }
+
+ /**
+ * Gets the connection status of the known network the user selected to connect to.
+ *
+ * @return Returns a {@link KnownNetworkConnectionStatus} object with the connection status,
+ * null on failure. If no connection is active the status will be
+ * {@link KnownNetworkConnectionStatus#CONNECTION_STATUS_UNKNOWN}.
+ */
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
+ @Nullable
+ public KnownNetworkConnectionStatus getKnownNetworkConnectionStatus() {
+ if (mService == null) {
+ return null;
+ }
+
+ try {
+ return mService.getKnownNetworkConnectionStatus();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Exception in getKnownNetworkConnectionStatus", e);
+ }
+ return null;
+ }
}
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityCallback.aidl b/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityCallback.aidl
index 6f6f1627c6a5..737aa6d9964c 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityCallback.aidl
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityCallback.aidl
@@ -19,15 +19,15 @@ package android.net.wifi.sharedconnectivity.service;
import android.net.wifi.sharedconnectivity.app.KnownNetwork;
import android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus;
import android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState;
-import android.net.wifi.sharedconnectivity.app.TetherNetwork;
-import android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus;
+import android.net.wifi.sharedconnectivity.app.HotspotNetwork;
+import android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus;
/*
* @hide
*/
interface ISharedConnectivityCallback {
- oneway void onTetherNetworksUpdated(in List<TetherNetwork> networks);
- oneway void onTetherNetworkConnectionStatusChanged(in TetherNetworkConnectionStatus status);
+ oneway void onHotspotNetworksUpdated(in List<HotspotNetwork> networks);
+ oneway void onHotspotNetworkConnectionStatusChanged(in HotspotNetworkConnectionStatus status);
oneway void onKnownNetworksUpdated(in List<KnownNetwork> networks);
oneway void onKnownNetworkConnectionStatusChanged(in KnownNetworkConnectionStatus status);
oneway void onSharedConnectivitySettingsChanged(in SharedConnectivitySettingsState state);
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityService.aidl b/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityService.aidl
index 52da596081a4..c81380df3c79 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityService.aidl
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityService.aidl
@@ -17,7 +17,10 @@
package android.net.wifi.sharedconnectivity.service;
import android.net.wifi.sharedconnectivity.app.KnownNetwork;
-import android.net.wifi.sharedconnectivity.app.TetherNetwork;
+import android.net.wifi.sharedconnectivity.app.HotspotNetwork;
+import android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus;
+import android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState;
+import android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus;
import android.net.wifi.sharedconnectivity.service.ISharedConnectivityCallback;
/*
@@ -26,8 +29,13 @@ import android.net.wifi.sharedconnectivity.service.ISharedConnectivityCallback;
interface ISharedConnectivityService {
void registerCallback(in ISharedConnectivityCallback callback);
void unregisterCallback(in ISharedConnectivityCallback callback);
- void connectTetherNetwork(in TetherNetwork network);
- void disconnectTetherNetwork(in TetherNetwork network);
+ void connectHotspotNetwork(in HotspotNetwork network);
+ void disconnectHotspotNetwork(in HotspotNetwork network);
void connectKnownNetwork(in KnownNetwork network);
void forgetKnownNetwork(in KnownNetwork network);
+ List<HotspotNetwork> getHotspotNetworks();
+ List<KnownNetwork> getKnownNetworks();
+ SharedConnectivitySettingsState getSettingsState();
+ HotspotNetworkConnectionStatus getHotspotNetworkConnectionStatus();
+ KnownNetworkConnectionStatus getKnownNetworkConnectionStatus();
}
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java b/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java
index f3af06247576..c53da9c15d4d 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java
@@ -23,25 +23,25 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.app.Service;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.net.wifi.sharedconnectivity.app.HotspotNetwork;
+import android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus;
import android.net.wifi.sharedconnectivity.app.KnownNetwork;
import android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus;
import android.net.wifi.sharedconnectivity.app.SharedConnectivityManager;
import android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState;
-import android.net.wifi.sharedconnectivity.app.TetherNetwork;
-import android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus;
+import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.util.Log;
-import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
/**
@@ -59,182 +59,232 @@ public abstract class SharedConnectivityService extends Service {
private static final String TAG = SharedConnectivityService.class.getSimpleName();
private static final boolean DEBUG = true;
- private Handler mHandler;
- private final List<ISharedConnectivityCallback> mCallbacks = new ArrayList<>();
- // Used to find DeathRecipient when unregistering a callback to call unlinkToDeath.
- private final Map<ISharedConnectivityCallback, DeathRecipient> mDeathRecipientMap =
- new HashMap<>();
-
- private List<TetherNetwork> mTetherNetworks = Collections.emptyList();
+ private Handler mHandler;
+ private final RemoteCallbackList<ISharedConnectivityCallback> mRemoteCallbackList =
+ new RemoteCallbackList<>();
+ private List<HotspotNetwork> mHotspotNetworks = Collections.emptyList();
private List<KnownNetwork> mKnownNetworks = Collections.emptyList();
- private SharedConnectivitySettingsState mSettingsState;
- private TetherNetworkConnectionStatus mTetherNetworkConnectionStatus;
- private KnownNetworkConnectionStatus mKnownNetworkConnectionStatus;
-
- private final class DeathRecipient implements IBinder.DeathRecipient {
- ISharedConnectivityCallback mCallback;
-
- DeathRecipient(ISharedConnectivityCallback callback) {
- mCallback = callback;
- }
-
- @Override
- public void binderDied() {
- mCallbacks.remove(mCallback);
- mDeathRecipientMap.remove(mCallback);
- }
- }
+ private SharedConnectivitySettingsState mSettingsState =
+ new SharedConnectivitySettingsState.Builder().setInstantTetherEnabled(false)
+ .setExtras(Bundle.EMPTY).build();
+ private HotspotNetworkConnectionStatus mHotspotNetworkConnectionStatus =
+ new HotspotNetworkConnectionStatus.Builder()
+ .setStatus(HotspotNetworkConnectionStatus.CONNECTION_STATUS_UNKNOWN)
+ .setExtras(Bundle.EMPTY).build();
+ private KnownNetworkConnectionStatus mKnownNetworkConnectionStatus =
+ new KnownNetworkConnectionStatus.Builder()
+ .setStatus(KnownNetworkConnectionStatus.CONNECTION_STATUS_UNKNOWN)
+ .setExtras(Bundle.EMPTY).build();
@Override
@Nullable
public final IBinder onBind(@NonNull Intent intent) {
if (DEBUG) Log.i(TAG, "onBind intent=" + intent);
mHandler = new Handler(getMainLooper());
- return new ISharedConnectivityService.Stub() {
+ IBinder serviceStub = new ISharedConnectivityService.Stub() {
+
+ /**
+ * Registers a callback for receiving updates to the list of Hotspot Networks, Known
+ * Networks, shared connectivity settings state, hotspot network connection status and
+ * known network connection status.
+ *
+ * @param callback The callback of type {@link ISharedConnectivityCallback} to be called
+ * when there is update to the data.
+ */
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
@Override
public void registerCallback(ISharedConnectivityCallback callback) {
checkPermissions();
mHandler.post(() -> onRegisterCallback(callback));
}
+ /**
+ * Unregisters a previously registered callback.
+ *
+ * @param callback The callback to unregister.
+ */
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
@Override
public void unregisterCallback(ISharedConnectivityCallback callback) {
checkPermissions();
mHandler.post(() -> onUnregisterCallback(callback));
}
+ /**
+ * Connects to a hotspot network.
+ *
+ * @param network The network to connect to.
+ */
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
@Override
- public void connectTetherNetwork(TetherNetwork network) {
+ public void connectHotspotNetwork(HotspotNetwork network) {
checkPermissions();
- mHandler.post(() -> onConnectTetherNetwork(network));
+ mHandler.post(() -> onConnectHotspotNetwork(network));
}
- @Override
- public void disconnectTetherNetwork(TetherNetwork network) {
+ /**
+ * Disconnects from a previously connected hotspot network.
+ *
+ * @param network The network to disconnect from.
+ */
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
+ public void disconnectHotspotNetwork(HotspotNetwork network) {
checkPermissions();
- mHandler.post(() -> onDisconnectTetherNetwork(network));
+ mHandler.post(() -> onDisconnectHotspotNetwork(network));
}
+ /**
+ * Adds a known network to the available networks on the device and connects to it.
+ *
+ * @param network The network to connect to.
+ */
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
@Override
public void connectKnownNetwork(KnownNetwork network) {
checkPermissions();
mHandler.post(() -> onConnectKnownNetwork(network));
}
+ /**
+ * Removes a known network from the available networks on the device which will also
+ * disconnect the device from the network if it is connected to it.
+ *
+ * @param network The network to forget.
+ */
@Override
public void forgetKnownNetwork(KnownNetwork network) {
checkPermissions();
mHandler.post(() -> onForgetKnownNetwork(network));
}
+ /**
+ * Gets the list of hotspot networks the user can select to connect to.
+ *
+ * @return Returns a {@link List} of {@link HotspotNetwork} objects
+ */
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
+ @Override
+ public List<HotspotNetwork> getHotspotNetworks() {
+ checkPermissions();
+ return mHotspotNetworks;
+ }
+
+ /**
+ * Gets the list of known networks the user can select to connect to.
+ *
+ * @return Returns a {@link List} of {@link KnownNetwork} objects.
+ */
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
+ @Override
+ public List<KnownNetwork> getKnownNetworks() {
+ checkPermissions();
+ return mKnownNetworks;
+ }
+
+ /**
+ * Gets the shared connectivity settings state.
+ *
+ * @return Returns a {@link SharedConnectivitySettingsState} object with the state.
+ */
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
+ @Override
+ public SharedConnectivitySettingsState getSettingsState() {
+ checkPermissions();
+ return mSettingsState;
+ }
+
+ /**
+ * Gets the connection status of the hotspot network the user selected to connect to.
+ *
+ * @return Returns a {@link HotspotNetworkConnectionStatus} object with the connection
+ * status.
+ */
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
+ @Override
+ public HotspotNetworkConnectionStatus getHotspotNetworkConnectionStatus() {
+ checkPermissions();
+ return mHotspotNetworkConnectionStatus;
+ }
+
+ /**
+ * Gets the connection status of the known network the user selected to connect to.
+ *
+ * @return Returns a {@link KnownNetworkConnectionStatus} object with the connection
+ * status.
+ */
+ @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
+ @Override
+ public KnownNetworkConnectionStatus getKnownNetworkConnectionStatus() {
+ checkPermissions();
+ return mKnownNetworkConnectionStatus;
+ }
+
@RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
android.Manifest.permission.NETWORK_SETUP_WIZARD})
+ /**
+ * checkPermissions is using checkCallingOrSelfPermission to support CTS testing of this
+ * service. This does allow a process to bind to itself if it holds the proper
+ * permission. We do not consider this to be an issue given that the process can already
+ * access the service data since they are in the same process.
+ */
private void checkPermissions() {
- if (checkCallingPermission(NETWORK_SETTINGS) != PackageManager.PERMISSION_GRANTED
- && checkCallingPermission(NETWORK_SETUP_WIZARD)
- != PackageManager.PERMISSION_GRANTED) {
+ if (checkCallingOrSelfPermission(NETWORK_SETTINGS)
+ != PackageManager.PERMISSION_GRANTED
+ && checkCallingOrSelfPermission(NETWORK_SETUP_WIZARD)
+ != PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Calling process must have NETWORK_SETTINGS or"
+ " NETWORK_SETUP_WIZARD permission");
}
}
};
+ onBind(); // For CTS testing
+ return serviceStub;
}
- private void onRegisterCallback(ISharedConnectivityCallback callback) {
- // Listener gets triggered on first register using cashed data
- if (!notifyTetherNetworkUpdate(callback) || !notifyKnownNetworkUpdate(callback)
- || !notifySettingsStateUpdate(callback)
- || !notifyTetherNetworkConnectionStatusChanged(callback)
- || !notifyKnownNetworkConnectionStatusChanged(callback)) {
- if (DEBUG) Log.w(TAG, "Failed to notify client");
- return;
- }
-
- DeathRecipient deathRecipient = new DeathRecipient(callback);
- try {
- callback.asBinder().linkToDeath(deathRecipient, 0);
- mCallbacks.add(callback);
- mDeathRecipientMap.put(callback, deathRecipient);
- } catch (RemoteException e) {
- if (DEBUG) Log.w(TAG, "Exception in registerCallback", e);
- }
- }
-
- private void onUnregisterCallback(ISharedConnectivityCallback callback) {
- DeathRecipient deathRecipient = mDeathRecipientMap.get(callback);
- if (deathRecipient != null) {
- callback.asBinder().unlinkToDeath(deathRecipient, 0);
- mDeathRecipientMap.remove(callback);
- }
- mCallbacks.remove(callback);
- }
-
- private boolean notifyTetherNetworkUpdate(ISharedConnectivityCallback callback) {
- try {
- callback.onTetherNetworksUpdated(mTetherNetworks);
- } catch (RemoteException e) {
- if (DEBUG) Log.w(TAG, "Exception in notifyTetherNetworkUpdate", e);
- return false;
- }
- return true;
- }
-
- private boolean notifyKnownNetworkUpdate(ISharedConnectivityCallback callback) {
- try {
- callback.onKnownNetworksUpdated(mKnownNetworks);
- } catch (RemoteException e) {
- if (DEBUG) Log.w(TAG, "Exception in notifyKnownNetworkUpdate", e);
- return false;
- }
- return true;
+ /** @hide */
+ @TestApi
+ public void onBind() {
}
- private boolean notifySettingsStateUpdate(ISharedConnectivityCallback callback) {
- try {
- callback.onSharedConnectivitySettingsChanged(mSettingsState);
- } catch (RemoteException e) {
- if (DEBUG) Log.w(TAG, "Exception in notifySettingsStateUpdate", e);
- return false;
- }
- return true;
+ private void onRegisterCallback(ISharedConnectivityCallback callback) {
+ mRemoteCallbackList.register(callback);
}
- private boolean notifyTetherNetworkConnectionStatusChanged(
- ISharedConnectivityCallback callback) {
- try {
- callback.onTetherNetworkConnectionStatusChanged(mTetherNetworkConnectionStatus);
- } catch (RemoteException e) {
- if (DEBUG) Log.w(TAG, "Exception in notifyTetherNetworkConnectionStatusChanged", e);
- return false;
- }
- return true;
+ private void onUnregisterCallback(ISharedConnectivityCallback callback) {
+ mRemoteCallbackList.unregister(callback);
}
- private boolean notifyKnownNetworkConnectionStatusChanged(
- ISharedConnectivityCallback callback) {
- try {
- callback.onKnownNetworkConnectionStatusChanged(mKnownNetworkConnectionStatus);
- } catch (RemoteException e) {
- if (DEBUG) Log.w(TAG, "Exception in notifyKnownNetworkConnectionStatusChanged", e);
- return false;
- }
- return true;
- }
/**
- * Implementing application should call this method to provide an up-to-date list of Tether
+ * Implementing application should call this method to provide an up-to-date list of Hotspot
* Networks to be displayed to the user.
*
* This method updates the cached list and notifies all registered callbacks. Any callbacks that
* are inaccessible will be unregistered.
*
- * @param networks The updated list of {@link TetherNetwork} objects.
+ * @param networks The updated list of {@link HotspotNetwork} objects.
*/
- public final void setTetherNetworks(@NonNull List<TetherNetwork> networks) {
- mTetherNetworks = networks;
-
- for (ISharedConnectivityCallback callback:mCallbacks) {
- notifyTetherNetworkUpdate(callback);
+ public final void setHotspotNetworks(@NonNull List<HotspotNetwork> networks) {
+ mHotspotNetworks = networks;
+
+ int count = mRemoteCallbackList.beginBroadcast();
+ for (int i = 0; i < count; i++) {
+ try {
+ mRemoteCallbackList.getBroadcastItem(i).onHotspotNetworksUpdated(mHotspotNetworks);
+ } catch (RemoteException e) {
+ if (DEBUG) Log.w(TAG, "Exception in setHotspotNetworks", e);
+ }
}
+ mRemoteCallbackList.finishBroadcast();
}
/**
@@ -249,9 +299,15 @@ public abstract class SharedConnectivityService extends Service {
public final void setKnownNetworks(@NonNull List<KnownNetwork> networks) {
mKnownNetworks = networks;
- for (ISharedConnectivityCallback callback:mCallbacks) {
- notifyKnownNetworkUpdate(callback);
+ int count = mRemoteCallbackList.beginBroadcast();
+ for (int i = 0; i < count; i++) {
+ try {
+ mRemoteCallbackList.getBroadcastItem(i).onKnownNetworksUpdated(mKnownNetworks);
+ } catch (RemoteException e) {
+ if (DEBUG) Log.w(TAG, "Exception in setKnownNetworks", e);
+ }
}
+ mRemoteCallbackList.finishBroadcast();
}
/**
@@ -262,29 +318,44 @@ public abstract class SharedConnectivityService extends Service {
* that are inaccessible will be unregistered.
*
* @param settingsState The updated state {@link SharedConnectivitySettingsState}
- * objects.
+ * objects.
*/
public final void setSettingsState(@NonNull SharedConnectivitySettingsState settingsState) {
mSettingsState = settingsState;
- for (ISharedConnectivityCallback callback:mCallbacks) {
- notifySettingsStateUpdate(callback);
+ int count = mRemoteCallbackList.beginBroadcast();
+ for (int i = 0; i < count; i++) {
+ try {
+ mRemoteCallbackList.getBroadcastItem(i).onSharedConnectivitySettingsChanged(
+ mSettingsState);
+ } catch (RemoteException e) {
+ if (DEBUG) Log.w(TAG, "Exception in setSettingsState", e);
+ }
}
+ mRemoteCallbackList.finishBroadcast();
}
/**
* Implementing application should call this method to provide an up-to-date status of enabling
- * and connecting to the tether network.
- *
- * @param status The updated status {@link TetherNetworkConnectionStatus} of the connection.
+ * and connecting to the hotspot network.
*
+ * @param status The updated status {@link HotspotNetworkConnectionStatus} of the connection.
*/
- public final void updateTetherNetworkConnectionStatus(
- @NonNull TetherNetworkConnectionStatus status) {
- mTetherNetworkConnectionStatus = status;
- for (ISharedConnectivityCallback callback:mCallbacks) {
- notifyTetherNetworkConnectionStatusChanged(callback);
+ public final void updateHotspotNetworkConnectionStatus(
+ @NonNull HotspotNetworkConnectionStatus status) {
+ mHotspotNetworkConnectionStatus = status;
+
+ int count = mRemoteCallbackList.beginBroadcast();
+ for (int i = 0; i < count; i++) {
+ try {
+ mRemoteCallbackList
+ .getBroadcastItem(i).onHotspotNetworkConnectionStatusChanged(
+ mHotspotNetworkConnectionStatus);
+ } catch (RemoteException e) {
+ if (DEBUG) Log.w(TAG, "Exception in updateHotspotNetworkConnectionStatus", e);
+ }
}
+ mRemoteCallbackList.finishBroadcast();
}
/**
@@ -292,34 +363,41 @@ public abstract class SharedConnectivityService extends Service {
* connecting to a known network.
*
* @param status The updated status {@link KnownNetworkConnectionStatus} of the connection.
- *
*/
public final void updateKnownNetworkConnectionStatus(
@NonNull KnownNetworkConnectionStatus status) {
mKnownNetworkConnectionStatus = status;
- for (ISharedConnectivityCallback callback:mCallbacks) {
- notifyKnownNetworkConnectionStatusChanged(callback);
+ int count = mRemoteCallbackList.beginBroadcast();
+ for (int i = 0; i < count; i++) {
+ try {
+ mRemoteCallbackList
+ .getBroadcastItem(i).onKnownNetworkConnectionStatusChanged(
+ mKnownNetworkConnectionStatus);
+ } catch (RemoteException e) {
+ if (DEBUG) Log.w(TAG, "Exception in updateKnownNetworkConnectionStatus", e);
+ }
}
+ mRemoteCallbackList.finishBroadcast();
}
/**
* Implementing application should implement this method.
*
- * Implementation should initiate a connection to the Tether Network indicated.
+ * Implementation should initiate a connection to the Hotspot Network indicated.
*
- * @param network Object identifying the Tether Network the user has requested a connection to.
+ * @param network Object identifying the Hotspot Network the user has requested a connection to.
*/
- public abstract void onConnectTetherNetwork(@NonNull TetherNetwork network);
+ public abstract void onConnectHotspotNetwork(@NonNull HotspotNetwork network);
/**
* Implementing application should implement this method.
*
- * Implementation should initiate a disconnection from the active Tether Network.
+ * Implementation should initiate a disconnection from the active Hotspot Network.
*
- * @param network Object identifying the Tether Network the user has requested to disconnect.
+ * @param network Object identifying the Hotspot Network the user has requested to disconnect.
*/
- public abstract void onDisconnectTetherNetwork(@NonNull TetherNetwork network);
+ public abstract void onDisconnectHotspotNetwork(@NonNull HotspotNetwork network);
/**
* Implementing application should implement this method.
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/DeviceInfoTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/DeviceInfoTest.java
deleted file mode 100644
index f8f07008e34b..000000000000
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/DeviceInfoTest.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.sharedconnectivity.app;
-
-import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_LAPTOP;
-import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_PHONE;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-
-import android.os.Parcel;
-
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-
-/**
- * Unit tests for {@link android.app.sharedconnectivity.DeviceInfo}.
- */
-@SmallTest
-public class DeviceInfoTest {
-
- private static final int DEVICE_TYPE = DEVICE_TYPE_PHONE;
- private static final String DEVICE_NAME = "TEST_NAME";
- private static final String DEVICE_MODEL = "TEST_MODEL";
- private static final int BATTERY_PERCENTAGE = 50;
- private static final int CONNECTION_STRENGTH = 2;
-
- private static final int DEVICE_TYPE_1 = DEVICE_TYPE_LAPTOP;
- private static final String DEVICE_NAME_1 = "TEST_NAME1";
- private static final String DEVICE_MODEL_1 = "TEST_MODEL1";
- private static final int BATTERY_PERCENTAGE_1 = 30;
- private static final int CONNECTION_STRENGTH_1 = 1;
-
- /**
- * Verifies parcel serialization/deserialization.
- */
- @Test
- public void testParcelOperation() {
- DeviceInfo info = buildDeviceInfoBuilder().build();
-
- Parcel parcelW = Parcel.obtain();
- info.writeToParcel(parcelW, 0);
- byte[] bytes = parcelW.marshall();
- parcelW.recycle();
-
- Parcel parcelR = Parcel.obtain();
- parcelR.unmarshall(bytes, 0, bytes.length);
- parcelR.setDataPosition(0);
- DeviceInfo fromParcel = DeviceInfo.CREATOR.createFromParcel(parcelR);
-
- assertEquals(info, fromParcel);
- assertEquals(info.hashCode(), fromParcel.hashCode());
- }
-
- /**
- * Verifies the Equals operation
- */
- @Test
- public void testEqualsOperation() {
- DeviceInfo info1 = buildDeviceInfoBuilder().build();
- DeviceInfo info2 = buildDeviceInfoBuilder().build();
- assertEquals(info1, info2);
-
- DeviceInfo.Builder builder = buildDeviceInfoBuilder().setDeviceType(DEVICE_TYPE_1);
- assertNotEquals(info1, builder.build());
-
- builder = buildDeviceInfoBuilder().setDeviceName(DEVICE_NAME_1);
- assertNotEquals(info1, builder.build());
-
- builder = buildDeviceInfoBuilder().setModelName(DEVICE_MODEL_1);
- assertNotEquals(info1, builder.build());
-
- builder = buildDeviceInfoBuilder()
- .setBatteryPercentage(BATTERY_PERCENTAGE_1);
- assertNotEquals(info1, builder.build());
-
- builder = buildDeviceInfoBuilder()
- .setConnectionStrength(CONNECTION_STRENGTH_1);
- assertNotEquals(info1, builder.build());
- }
-
- /**
- * Verifies the get methods return the expected data.
- */
- @Test
- public void testGetMethods() {
- DeviceInfo info = buildDeviceInfoBuilder().build();
- assertEquals(info.getDeviceType(), DEVICE_TYPE);
- assertEquals(info.getDeviceName(), DEVICE_NAME);
- assertEquals(info.getModelName(), DEVICE_MODEL);
- assertEquals(info.getBatteryPercentage(), BATTERY_PERCENTAGE);
- assertEquals(info.getConnectionStrength(), CONNECTION_STRENGTH);
- assertEquals(info.getConnectionStrength(), CONNECTION_STRENGTH);
- }
-
- private DeviceInfo.Builder buildDeviceInfoBuilder() {
- return new DeviceInfo.Builder().setDeviceType(DEVICE_TYPE).setDeviceName(DEVICE_NAME)
- .setModelName(DEVICE_MODEL).setBatteryPercentage(BATTERY_PERCENTAGE)
- .setConnectionStrength(CONNECTION_STRENGTH);
- }
-}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatusTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatusTest.java
new file mode 100644
index 000000000000..b18ab5060924
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatusTest.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.sharedconnectivity.app;
+
+import static android.net.wifi.WifiInfo.SECURITY_TYPE_EAP;
+import static android.net.wifi.WifiInfo.SECURITY_TYPE_WEP;
+import static android.net.wifi.sharedconnectivity.app.HotspotNetwork.NETWORK_TYPE_CELLULAR;
+import static android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus.CONNECTION_STATUS_ENABLING_HOTSPOT;
+import static android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus.CONNECTION_STATUS_TETHERING_TIMEOUT;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_TABLET;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.Bundle;
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+import java.util.Arrays;
+
+/**
+ * Unit tests for {@link HotspotNetworkConnectionStatus}.
+ */
+@SmallTest
+public class HotspotNetworkConnectionStatusTest {
+ private static final long DEVICE_ID = 11L;
+ private static final NetworkProviderInfo NETWORK_PROVIDER_INFO =
+ new NetworkProviderInfo.Builder("TEST_NAME", "TEST_MODEL")
+ .setDeviceType(DEVICE_TYPE_TABLET).setConnectionStrength(2)
+ .setBatteryPercentage(50).build();
+ private static final int NETWORK_TYPE = NETWORK_TYPE_CELLULAR;
+ private static final String NETWORK_NAME = "TEST_NETWORK";
+ private static final String HOTSPOT_SSID = "TEST_SSID";
+ private static final String HOTSPOT_BSSID = "TEST _BSSID";
+ private static final int[] HOTSPOT_SECURITY_TYPES = {SECURITY_TYPE_WEP, SECURITY_TYPE_EAP};
+ private static final long DEVICE_ID_1 = 111L;
+ private static final String BUNDLE_KEY = "INT-KEY";
+ private static final int BUNDLE_VALUE = 1;
+
+ /**
+ * Verifies parcel serialization/deserialization.
+ */
+ @Test
+ public void testParcelOperation() {
+ HotspotNetworkConnectionStatus status = buildConnectionStatusBuilder().build();
+
+ Parcel parcelW = Parcel.obtain();
+ status.writeToParcel(parcelW, 0);
+ byte[] bytes = parcelW.marshall();
+ parcelW.recycle();
+
+ Parcel parcelR = Parcel.obtain();
+ parcelR.unmarshall(bytes, 0, bytes.length);
+ parcelR.setDataPosition(0);
+ HotspotNetworkConnectionStatus fromParcel =
+ HotspotNetworkConnectionStatus.CREATOR.createFromParcel(parcelR);
+
+ assertThat(fromParcel).isEqualTo(status);
+ assertThat(fromParcel.hashCode()).isEqualTo(status.hashCode());
+ }
+
+ /**
+ * Verifies the Equals operation
+ */
+ @Test
+ public void testEqualsOperation() {
+ HotspotNetworkConnectionStatus status1 = buildConnectionStatusBuilder().build();
+ HotspotNetworkConnectionStatus status2 = buildConnectionStatusBuilder().build();
+ assertThat(status1).isEqualTo(status2);
+
+ HotspotNetworkConnectionStatus.Builder builder = buildConnectionStatusBuilder()
+ .setStatus(CONNECTION_STATUS_TETHERING_TIMEOUT);
+ assertThat(builder.build()).isNotEqualTo(status1);
+
+ builder = buildConnectionStatusBuilder()
+ .setHotspotNetwork(buildHotspotNetworkBuilder().setDeviceId(DEVICE_ID_1).build());
+ assertThat(builder.build()).isNotEqualTo(status1);
+ }
+
+ /**
+ * Verifies the get methods return the expected data.
+ */
+ @Test
+ public void testGetMethods() {
+ HotspotNetworkConnectionStatus status = buildConnectionStatusBuilder().build();
+ assertThat(status.getStatus()).isEqualTo(CONNECTION_STATUS_ENABLING_HOTSPOT);
+ assertThat(status.getHotspotNetwork()).isEqualTo(buildHotspotNetworkBuilder().build());
+ assertThat(status.getExtras().getInt(BUNDLE_KEY)).isEqualTo(BUNDLE_VALUE);
+ }
+
+ @Test
+ public void testHashCode() {
+ HotspotNetworkConnectionStatus status1 = buildConnectionStatusBuilder().build();
+ HotspotNetworkConnectionStatus status2 = buildConnectionStatusBuilder().build();
+
+ assertThat(status1.hashCode()).isEqualTo(status2.hashCode());
+ }
+
+ private HotspotNetworkConnectionStatus.Builder buildConnectionStatusBuilder() {
+ return new HotspotNetworkConnectionStatus.Builder()
+ .setStatus(CONNECTION_STATUS_ENABLING_HOTSPOT)
+ .setHotspotNetwork(buildHotspotNetworkBuilder().build())
+ .setExtras(buildBundle());
+ }
+
+ private Bundle buildBundle() {
+ Bundle bundle = new Bundle();
+ bundle.putInt(BUNDLE_KEY, BUNDLE_VALUE);
+ return bundle;
+ }
+
+ private HotspotNetwork.Builder buildHotspotNetworkBuilder() {
+ HotspotNetwork.Builder builder = new HotspotNetwork.Builder()
+ .setDeviceId(DEVICE_ID)
+ .setNetworkProviderInfo(NETWORK_PROVIDER_INFO)
+ .setHostNetworkType(NETWORK_TYPE)
+ .setNetworkName(NETWORK_NAME)
+ .setHotspotSsid(HOTSPOT_SSID)
+ .setHotspotBssid(HOTSPOT_BSSID);
+ Arrays.stream(HOTSPOT_SECURITY_TYPES).forEach(builder::addHotspotSecurityType);
+ return builder;
+ }
+}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkTest.java
new file mode 100644
index 000000000000..8e396b68ad3a
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkTest.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.sharedconnectivity.app;
+
+import static android.net.wifi.WifiInfo.SECURITY_TYPE_EAP;
+import static android.net.wifi.WifiInfo.SECURITY_TYPE_PSK;
+import static android.net.wifi.WifiInfo.SECURITY_TYPE_WEP;
+import static android.net.wifi.sharedconnectivity.app.HotspotNetwork.NETWORK_TYPE_CELLULAR;
+import static android.net.wifi.sharedconnectivity.app.HotspotNetwork.NETWORK_TYPE_WIFI;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_PHONE;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_TABLET;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.Parcel;
+import android.util.ArraySet;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+import java.util.Arrays;
+
+/**
+ * Unit tests for {@link HotspotNetwork}.
+ */
+@SmallTest
+public class HotspotNetworkTest {
+ private static final long DEVICE_ID = 11L;
+ private static final NetworkProviderInfo NETWORK_PROVIDER_INFO =
+ new NetworkProviderInfo.Builder("TEST_NAME", "TEST_MODEL")
+ .setDeviceType(DEVICE_TYPE_TABLET).setConnectionStrength(2)
+ .setBatteryPercentage(50).build();
+ private static final int NETWORK_TYPE = NETWORK_TYPE_CELLULAR;
+ private static final String NETWORK_NAME = "TEST_NETWORK";
+ private static final String HOTSPOT_SSID = "TEST_SSID";
+ private static final String HOTSPOT_BSSID = "TEST _BSSID";
+ private static final int[] HOTSPOT_SECURITY_TYPES = {SECURITY_TYPE_WEP, SECURITY_TYPE_EAP};
+
+ private static final long DEVICE_ID_1 = 111L;
+ private static final NetworkProviderInfo NETWORK_PROVIDER_INFO1 =
+ new NetworkProviderInfo.Builder("TEST_NAME", "TEST_MODEL")
+ .setDeviceType(DEVICE_TYPE_PHONE).setConnectionStrength(2)
+ .setBatteryPercentage(50).build();
+ private static final int NETWORK_TYPE_1 = NETWORK_TYPE_WIFI;
+ private static final String NETWORK_NAME_1 = "TEST_NETWORK1";
+ private static final String HOTSPOT_SSID_1 = "TEST_SSID1";
+ private static final String HOTSPOT_BSSID_1 = "TEST _BSSID1";
+ private static final int[] HOTSPOT_SECURITY_TYPES_1 = {SECURITY_TYPE_PSK, SECURITY_TYPE_EAP};
+
+ /**
+ * Verifies parcel serialization/deserialization.
+ */
+ @Test
+ public void testParcelOperation() {
+ HotspotNetwork network = buildHotspotNetworkBuilder().build();
+
+ Parcel parcelW = Parcel.obtain();
+ network.writeToParcel(parcelW, 0);
+ byte[] bytes = parcelW.marshall();
+ parcelW.recycle();
+
+ Parcel parcelR = Parcel.obtain();
+ parcelR.unmarshall(bytes, 0, bytes.length);
+ parcelR.setDataPosition(0);
+ HotspotNetwork fromParcel = HotspotNetwork.CREATOR.createFromParcel(parcelR);
+
+ assertThat(fromParcel).isEqualTo(network);
+ assertThat(fromParcel.hashCode()).isEqualTo(network.hashCode());
+ }
+
+ /**
+ * Verifies the Equals operation
+ */
+ @Test
+ public void testEqualsOperation() {
+ HotspotNetwork network1 = buildHotspotNetworkBuilder().build();
+ HotspotNetwork network2 = buildHotspotNetworkBuilder().build();
+ assertThat(network1).isEqualTo(network2);
+
+ HotspotNetwork.Builder builder = buildHotspotNetworkBuilder().setDeviceId(DEVICE_ID_1);
+ assertThat(builder.build()).isNotEqualTo(network1);
+
+ builder = buildHotspotNetworkBuilder().setNetworkProviderInfo(NETWORK_PROVIDER_INFO1);
+ assertThat(builder.build()).isNotEqualTo(network1);
+
+ builder = buildHotspotNetworkBuilder().setHostNetworkType(NETWORK_TYPE_1);
+ assertThat(builder.build()).isNotEqualTo(network1);
+
+ builder = buildHotspotNetworkBuilder().setNetworkName(NETWORK_NAME_1);
+ assertThat(builder.build()).isNotEqualTo(network1);
+
+ builder = buildHotspotNetworkBuilder().setHotspotSsid(HOTSPOT_SSID_1);
+ assertThat(builder.build()).isNotEqualTo(network1);
+
+ builder = buildHotspotNetworkBuilder().setHotspotBssid(HOTSPOT_BSSID_1);
+ assertThat(builder.build()).isNotEqualTo(network1);
+
+ builder = buildHotspotNetworkBuilder();
+ HotspotNetwork.Builder builder1 = buildHotspotNetworkBuilder();
+ Arrays.stream(HOTSPOT_SECURITY_TYPES_1).forEach(builder1::addHotspotSecurityType);
+
+ assertThat(builder1.build()).isNotEqualTo(builder.build());
+ }
+
+ /**
+ * Verifies the get methods return the expected data.
+ */
+ @Test
+ public void testGetMethods() {
+ HotspotNetwork network = buildHotspotNetworkBuilder().build();
+ ArraySet<Integer> securityTypes = new ArraySet<>();
+ Arrays.stream(HOTSPOT_SECURITY_TYPES).forEach(securityTypes::add);
+
+ assertThat(network.getDeviceId()).isEqualTo(DEVICE_ID);
+ assertThat(network.getNetworkProviderInfo()).isEqualTo(NETWORK_PROVIDER_INFO);
+ assertThat(network.getHostNetworkType()).isEqualTo(NETWORK_TYPE);
+ assertThat(network.getNetworkName()).isEqualTo(NETWORK_NAME);
+ assertThat(network.getHotspotSsid()).isEqualTo(HOTSPOT_SSID);
+ assertThat(network.getHotspotBssid()).isEqualTo(HOTSPOT_BSSID);
+ assertThat(network.getHotspotSecurityTypes()).containsExactlyElementsIn(securityTypes);
+ }
+
+ @Test
+ public void testHashCode() {
+ HotspotNetwork network1 = buildHotspotNetworkBuilder().build();
+ HotspotNetwork network2 = buildHotspotNetworkBuilder().build();
+
+ assertThat(network1.hashCode()).isEqualTo(network2.hashCode());
+ }
+
+ private HotspotNetwork.Builder buildHotspotNetworkBuilder() {
+ HotspotNetwork.Builder builder = new HotspotNetwork.Builder()
+ .setDeviceId(DEVICE_ID)
+ .setNetworkProviderInfo(NETWORK_PROVIDER_INFO)
+ .setHostNetworkType(NETWORK_TYPE)
+ .setNetworkName(NETWORK_NAME)
+ .setHotspotSsid(HOTSPOT_SSID)
+ .setHotspotBssid(HOTSPOT_BSSID);
+ Arrays.stream(HOTSPOT_SECURITY_TYPES).forEach(builder::addHotspotSecurityType);
+ return builder;
+ }
+}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatusTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatusTest.java
index 37dca8def0bd..f98a0fcc7574 100644
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatusTest.java
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatusTest.java
@@ -17,13 +17,12 @@
package android.net.wifi.sharedconnectivity.app;
import static android.net.wifi.WifiInfo.SECURITY_TYPE_WEP;
-import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_TABLET;
import static android.net.wifi.sharedconnectivity.app.KnownNetwork.NETWORK_SOURCE_NEARBY_SELF;
import static android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus.CONNECTION_STATUS_SAVED;
import static android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus.CONNECTION_STATUS_SAVE_FAILED;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_TABLET;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
+import static com.google.common.truth.Truth.assertThat;
import android.os.Bundle;
import android.os.Parcel;
@@ -32,19 +31,23 @@ import androidx.test.filters.SmallTest;
import org.junit.Test;
+import java.util.Arrays;
+
/**
- * Unit tests for {@link android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus}.
+ * Unit tests for {@link KnownNetworkConnectionStatus}.
*/
@SmallTest
public class KnownNetworkConnectionStatusTest {
private static final int NETWORK_SOURCE = NETWORK_SOURCE_NEARBY_SELF;
private static final String SSID = "TEST_SSID";
private static final int[] SECURITY_TYPES = {SECURITY_TYPE_WEP};
- private static final DeviceInfo DEVICE_INFO = new DeviceInfo.Builder()
- .setDeviceType(DEVICE_TYPE_TABLET).setDeviceName("TEST_NAME").setModelName("TEST_MODEL")
- .setConnectionStrength(2).setBatteryPercentage(50).build();
+ private static final NetworkProviderInfo NETWORK_PROVIDER_INFO =
+ new NetworkProviderInfo.Builder("TEST_NAME", "TEST_MODEL")
+ .setDeviceType(DEVICE_TYPE_TABLET).setConnectionStrength(2)
+ .setBatteryPercentage(50).build();
private static final String SSID_1 = "TEST_SSID1";
private static final String BUNDLE_KEY = "INT-KEY";
+ private static final int BUNDLE_VALUE = 1;
/**
* Verifies parcel serialization/deserialization.
@@ -64,8 +67,8 @@ public class KnownNetworkConnectionStatusTest {
KnownNetworkConnectionStatus fromParcel =
KnownNetworkConnectionStatus.CREATOR.createFromParcel(parcelR);
- assertEquals(status, fromParcel);
- assertEquals(status.hashCode(), fromParcel.hashCode());
+ assertThat(fromParcel).isEqualTo(status);
+ assertThat(fromParcel.hashCode()).isEqualTo(status.hashCode());
}
/**
@@ -75,15 +78,15 @@ public class KnownNetworkConnectionStatusTest {
public void testEqualsOperation() {
KnownNetworkConnectionStatus status1 = buildConnectionStatusBuilder().build();
KnownNetworkConnectionStatus status2 = buildConnectionStatusBuilder().build();
- assertEquals(status2, status2);
+ assertThat(status1).isEqualTo(status2);
KnownNetworkConnectionStatus.Builder builder = buildConnectionStatusBuilder()
.setStatus(CONNECTION_STATUS_SAVE_FAILED);
- assertNotEquals(status1, builder.build());
+ assertThat(builder.build()).isNotEqualTo(status1);
builder = buildConnectionStatusBuilder()
.setKnownNetwork(buildKnownNetworkBuilder().setSsid(SSID_1).build());
- assertNotEquals(status1, builder.build());
+ assertThat(builder.build()).isNotEqualTo(status1);
}
/**
@@ -92,9 +95,17 @@ public class KnownNetworkConnectionStatusTest {
@Test
public void testGetMethods() {
KnownNetworkConnectionStatus status = buildConnectionStatusBuilder().build();
- assertEquals(status.getStatus(), CONNECTION_STATUS_SAVED);
- assertEquals(status.getKnownNetwork(), buildKnownNetworkBuilder().build());
- assertEquals(status.getExtras().getInt(BUNDLE_KEY), buildBundle().getInt(BUNDLE_KEY));
+ assertThat(status.getStatus()).isEqualTo(CONNECTION_STATUS_SAVED);
+ assertThat(status.getKnownNetwork()).isEqualTo(buildKnownNetworkBuilder().build());
+ assertThat(status.getExtras().getInt(BUNDLE_KEY)).isEqualTo(BUNDLE_VALUE);
+ }
+
+ @Test
+ public void testHashCode() {
+ KnownNetworkConnectionStatus status1 = buildConnectionStatusBuilder().build();
+ KnownNetworkConnectionStatus status2 = buildConnectionStatusBuilder().build();
+
+ assertThat(status1.hashCode()).isEqualTo(status2.hashCode());
}
private KnownNetworkConnectionStatus.Builder buildConnectionStatusBuilder() {
@@ -106,13 +117,15 @@ public class KnownNetworkConnectionStatusTest {
private Bundle buildBundle() {
Bundle bundle = new Bundle();
- bundle.putInt(BUNDLE_KEY, 1);
+ bundle.putInt(BUNDLE_KEY, BUNDLE_VALUE);
return bundle;
}
private KnownNetwork.Builder buildKnownNetworkBuilder() {
- return new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE).setSsid(SSID)
- .setSecurityTypes(SECURITY_TYPES).setDeviceInfo(DEVICE_INFO);
+ KnownNetwork.Builder builder = new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE)
+ .setSsid(SSID).setNetworkProviderInfo(NETWORK_PROVIDER_INFO);
+ Arrays.stream(SECURITY_TYPES).forEach(builder::addSecurityType);
+ return builder;
}
}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkTest.java
index 266afcc9a1a6..1ecba7644cf9 100644
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkTest.java
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkTest.java
@@ -18,23 +18,24 @@ package android.net.wifi.sharedconnectivity.app;
import static android.net.wifi.WifiInfo.SECURITY_TYPE_PSK;
import static android.net.wifi.WifiInfo.SECURITY_TYPE_WEP;
-import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_PHONE;
-import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_TABLET;
import static android.net.wifi.sharedconnectivity.app.KnownNetwork.NETWORK_SOURCE_CLOUD_SELF;
import static android.net.wifi.sharedconnectivity.app.KnownNetwork.NETWORK_SOURCE_NEARBY_SELF;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_PHONE;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_TABLET;
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
+import static com.google.common.truth.Truth.assertThat;
import android.os.Parcel;
+import android.util.ArraySet;
import androidx.test.filters.SmallTest;
import org.junit.Test;
+import java.util.Arrays;
+
/**
- * Unit tests for {@link android.app.sharedconnectivity.KnownNetwork}.
+ * Unit tests for {@link KnownNetwork}.
*/
@SmallTest
public class KnownNetworkTest {
@@ -42,15 +43,17 @@ public class KnownNetworkTest {
private static final int NETWORK_SOURCE = NETWORK_SOURCE_NEARBY_SELF;
private static final String SSID = "TEST_SSID";
private static final int[] SECURITY_TYPES = {SECURITY_TYPE_WEP};
- private static final DeviceInfo DEVICE_INFO = new DeviceInfo.Builder()
- .setDeviceType(DEVICE_TYPE_TABLET).setDeviceName("TEST_NAME").setModelName("TEST_MODEL")
- .setConnectionStrength(2).setBatteryPercentage(50).build();
+ private static final NetworkProviderInfo NETWORK_PROVIDER_INFO =
+ new NetworkProviderInfo.Builder("TEST_NAME", "TEST_MODEL")
+ .setDeviceType(DEVICE_TYPE_TABLET).setConnectionStrength(2)
+ .setBatteryPercentage(50).build();
private static final int NETWORK_SOURCE_1 = NETWORK_SOURCE_CLOUD_SELF;
private static final String SSID_1 = "TEST_SSID1";
private static final int[] SECURITY_TYPES_1 = {SECURITY_TYPE_PSK};
- private static final DeviceInfo DEVICE_INFO_1 = new DeviceInfo.Builder()
- .setDeviceType(DEVICE_TYPE_PHONE).setDeviceName("TEST_NAME_1")
- .setModelName("TEST_MODEL_1").setConnectionStrength(3).setBatteryPercentage(33).build();
+ private static final NetworkProviderInfo NETWORK_PROVIDER_INFO1 =
+ new NetworkProviderInfo.Builder("TEST_NAME_1", "TEST_MODEL_1")
+ .setDeviceType(DEVICE_TYPE_PHONE).setConnectionStrength(3)
+ .setBatteryPercentage(33).build();
/**
* Verifies parcel serialization/deserialization.
@@ -69,8 +72,8 @@ public class KnownNetworkTest {
parcelR.setDataPosition(0);
KnownNetwork fromParcel = KnownNetwork.CREATOR.createFromParcel(parcelR);
- assertEquals(network, fromParcel);
- assertEquals(network.hashCode(), fromParcel.hashCode());
+ assertThat(fromParcel).isEqualTo(network);
+ assertThat(fromParcel.hashCode()).isEqualTo(network.hashCode());
}
/**
@@ -80,20 +83,21 @@ public class KnownNetworkTest {
public void testEqualsOperation() {
KnownNetwork network1 = buildKnownNetworkBuilder().build();
KnownNetwork network2 = buildKnownNetworkBuilder().build();
- assertEquals(network1, network2);
+ assertThat(network1).isEqualTo(network2);
KnownNetwork.Builder builder = buildKnownNetworkBuilder()
.setNetworkSource(NETWORK_SOURCE_1);
- assertNotEquals(network1, builder.build());
+ assertThat(builder.build()).isNotEqualTo(network1);
builder = buildKnownNetworkBuilder().setSsid(SSID_1);
- assertNotEquals(network1, builder.build());
+ assertThat(builder.build()).isNotEqualTo(network1);
- builder = buildKnownNetworkBuilder().setSecurityTypes(SECURITY_TYPES_1);
- assertNotEquals(network1, builder.build());
+ builder = buildKnownNetworkBuilder();
+ Arrays.stream(SECURITY_TYPES_1).forEach(builder::addSecurityType);
+ assertThat(builder.build()).isNotEqualTo(network1);
- builder = buildKnownNetworkBuilder().setDeviceInfo(DEVICE_INFO_1);
- assertNotEquals(network1, builder.build());
+ builder = buildKnownNetworkBuilder().setNetworkProviderInfo(NETWORK_PROVIDER_INFO1);
+ assertThat(builder.build()).isNotEqualTo(network1);
}
/**
@@ -102,14 +106,27 @@ public class KnownNetworkTest {
@Test
public void testGetMethods() {
KnownNetwork network = buildKnownNetworkBuilder().build();
- assertEquals(network.getNetworkSource(), NETWORK_SOURCE);
- assertEquals(network.getSsid(), SSID);
- assertArrayEquals(network.getSecurityTypes(), SECURITY_TYPES);
- assertEquals(network.getDeviceInfo(), DEVICE_INFO);
+ ArraySet<Integer> securityTypes = new ArraySet<>();
+ Arrays.stream(SECURITY_TYPES).forEach(securityTypes::add);
+
+ assertThat(network.getNetworkSource()).isEqualTo(NETWORK_SOURCE);
+ assertThat(network.getSsid()).isEqualTo(SSID);
+ assertThat(network.getSecurityTypes()).containsExactlyElementsIn(securityTypes);
+ assertThat(network.getNetworkProviderInfo()).isEqualTo(NETWORK_PROVIDER_INFO);
+ }
+
+ @Test
+ public void testHashCode() {
+ KnownNetwork network1 = buildKnownNetworkBuilder().build();
+ KnownNetwork network2 = buildKnownNetworkBuilder().build();
+
+ assertThat(network1.hashCode()).isEqualTo(network2.hashCode());
}
private KnownNetwork.Builder buildKnownNetworkBuilder() {
- return new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE).setSsid(SSID)
- .setSecurityTypes(SECURITY_TYPES).setDeviceInfo(DEVICE_INFO);
+ KnownNetwork.Builder builder = new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE)
+ .setSsid(SSID).setNetworkProviderInfo(NETWORK_PROVIDER_INFO);
+ Arrays.stream(SECURITY_TYPES).forEach(builder::addSecurityType);
+ return builder;
}
}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfoTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfoTest.java
new file mode 100644
index 000000000000..8f35d8d94a8b
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfoTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.sharedconnectivity.app;
+
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_LAPTOP;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_PHONE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link NetworkProviderInfo}.
+ */
+@SmallTest
+public class NetworkProviderInfoTest {
+
+ private static final int DEVICE_TYPE = DEVICE_TYPE_PHONE;
+ private static final String DEVICE_NAME = "TEST_NAME";
+ private static final String DEVICE_MODEL = "TEST_MODEL";
+ private static final int BATTERY_PERCENTAGE = 50;
+ private static final int CONNECTION_STRENGTH = 2;
+
+ private static final int DEVICE_TYPE_1 = DEVICE_TYPE_LAPTOP;
+ private static final String DEVICE_NAME_1 = "TEST_NAME1";
+ private static final String DEVICE_MODEL_1 = "TEST_MODEL1";
+ private static final int BATTERY_PERCENTAGE_1 = 30;
+ private static final int CONNECTION_STRENGTH_1 = 1;
+
+ /**
+ * Verifies parcel serialization/deserialization.
+ */
+ @Test
+ public void testParcelOperation() {
+ NetworkProviderInfo info = buildNetworkProviderInfoBuilder().build();
+
+ Parcel parcelW = Parcel.obtain();
+ info.writeToParcel(parcelW, 0);
+ byte[] bytes = parcelW.marshall();
+ parcelW.recycle();
+
+ Parcel parcelR = Parcel.obtain();
+ parcelR.unmarshall(bytes, 0, bytes.length);
+ parcelR.setDataPosition(0);
+ NetworkProviderInfo fromParcel = NetworkProviderInfo.CREATOR.createFromParcel(parcelR);
+
+ assertThat(fromParcel).isEqualTo(info);
+ assertThat(fromParcel.hashCode()).isEqualTo(info.hashCode());
+ }
+
+ /**
+ * Verifies the Equals operation
+ */
+ @Test
+ public void testEqualsOperation() {
+ NetworkProviderInfo info1 = buildNetworkProviderInfoBuilder().build();
+ NetworkProviderInfo info2 = buildNetworkProviderInfoBuilder().build();
+ assertThat(info1).isEqualTo(info2);
+
+ NetworkProviderInfo.Builder builder = buildNetworkProviderInfoBuilder().setDeviceType(
+ DEVICE_TYPE_1);
+ assertThat(builder.build()).isNotEqualTo(info1);
+
+ builder = buildNetworkProviderInfoBuilder().setDeviceName(DEVICE_NAME_1);
+ assertThat(builder.build()).isNotEqualTo(info1);
+
+ builder = buildNetworkProviderInfoBuilder().setModelName(DEVICE_MODEL_1);
+ assertThat(builder.build()).isNotEqualTo(info1);
+
+ builder = buildNetworkProviderInfoBuilder()
+ .setBatteryPercentage(BATTERY_PERCENTAGE_1);
+ assertThat(builder.build()).isNotEqualTo(info1);
+
+ builder = buildNetworkProviderInfoBuilder()
+ .setConnectionStrength(CONNECTION_STRENGTH_1);
+ assertThat(builder.build()).isNotEqualTo(info1);
+ }
+
+ /**
+ * Verifies the get methods return the expected data.
+ */
+ @Test
+ public void testGetMethods() {
+ NetworkProviderInfo info = buildNetworkProviderInfoBuilder().build();
+ assertThat(info.getDeviceType()).isEqualTo(DEVICE_TYPE);
+ assertThat(info.getDeviceName()).isEqualTo(DEVICE_NAME);
+ assertThat(info.getModelName()).isEqualTo(DEVICE_MODEL);
+ assertThat(info.getBatteryPercentage()).isEqualTo(BATTERY_PERCENTAGE);
+ assertThat(info.getConnectionStrength()).isEqualTo(CONNECTION_STRENGTH);
+ }
+
+ @Test
+ public void testHashCode() {
+ NetworkProviderInfo info1 = buildNetworkProviderInfoBuilder().build();
+ NetworkProviderInfo info2 = buildNetworkProviderInfoBuilder().build();
+
+ assertThat(info1.hashCode()).isEqualTo(info2.hashCode());
+ }
+
+ private NetworkProviderInfo.Builder buildNetworkProviderInfoBuilder() {
+ return new NetworkProviderInfo.Builder(DEVICE_NAME, DEVICE_MODEL).setDeviceType(DEVICE_TYPE)
+ .setBatteryPercentage(BATTERY_PERCENTAGE)
+ .setConnectionStrength(CONNECTION_STRENGTH);
+ }
+}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManagerTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManagerTest.java
index 439d456d7657..8c573e302213 100644
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManagerTest.java
@@ -18,13 +18,12 @@ package android.net.wifi.sharedconnectivity.app;
import static android.net.wifi.WifiInfo.SECURITY_TYPE_EAP;
import static android.net.wifi.WifiInfo.SECURITY_TYPE_WEP;
-import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_TABLET;
+import static android.net.wifi.sharedconnectivity.app.HotspotNetwork.NETWORK_TYPE_CELLULAR;
import static android.net.wifi.sharedconnectivity.app.KnownNetwork.NETWORK_SOURCE_NEARBY_SELF;
-import static android.net.wifi.sharedconnectivity.app.TetherNetwork.NETWORK_TYPE_CELLULAR;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_TABLET;
+
+import static com.google.common.truth.Truth.assertThat;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doThrow;
@@ -36,6 +35,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.res.Resources;
import android.net.wifi.sharedconnectivity.service.ISharedConnectivityService;
+import android.os.Bundle;
import android.os.Parcel;
import android.os.RemoteException;
@@ -46,6 +46,8 @@ import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.Arrays;
+import java.util.List;
import java.util.concurrent.Executor;
/**
@@ -54,9 +56,10 @@ import java.util.concurrent.Executor;
@SmallTest
public class SharedConnectivityManagerTest {
private static final long DEVICE_ID = 11L;
- private static final DeviceInfo DEVICE_INFO = new DeviceInfo.Builder()
- .setDeviceType(DEVICE_TYPE_TABLET).setDeviceName("TEST_NAME").setModelName("TEST_MODEL")
- .setConnectionStrength(2).setBatteryPercentage(50).build();
+ private static final NetworkProviderInfo NETWORK_PROVIDER_INFO =
+ new NetworkProviderInfo.Builder("TEST_NAME", "TEST_MODEL")
+ .setDeviceType(DEVICE_TYPE_TABLET).setConnectionStrength(2)
+ .setBatteryPercentage(50).build();
private static final int NETWORK_TYPE = NETWORK_TYPE_CELLULAR;
private static final String NETWORK_NAME = "TEST_NETWORK";
private static final String HOTSPOT_SSID = "TEST_SSID";
@@ -70,13 +73,16 @@ public class SharedConnectivityManagerTest {
private static final String SERVICE_INTENT_ACTION = "TEST_INTENT_ACTION";
- @Mock Context mContext;
+ @Mock
+ Context mContext;
@Mock
ISharedConnectivityService mService;
- @Mock Executor mExecutor;
+ @Mock
+ Executor mExecutor;
@Mock
SharedConnectivityClientCallback mClientCallback;
- @Mock Resources mResources;
+ @Mock
+ Resources mResources;
@Mock
ISharedConnectivityService.Stub mIBinder;
@@ -95,6 +101,7 @@ public class SharedConnectivityManagerTest {
@Test
public void bindingToService() {
SharedConnectivityManager.create(mContext);
+
verify(mContext).bindService(any(), any(), anyInt());
}
@@ -104,7 +111,8 @@ public class SharedConnectivityManagerTest {
@Test
public void resourcesNotDefined() {
when(mResources.getString(anyInt())).thenThrow(new Resources.NotFoundException());
- assertNull(SharedConnectivityManager.create(mContext));
+
+ assertThat(SharedConnectivityManager.create(mContext)).isNull();
}
/**
@@ -115,8 +123,10 @@ public class SharedConnectivityManagerTest {
throws Exception {
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(null);
+
manager.registerCallback(mExecutor, mClientCallback);
manager.getServiceConnection().onServiceConnected(COMPONENT_NAME, mIBinder);
+
// Since the binder is embedded in a proxy class, the call to registerCallback is done on
// the proxy. So instead verifying that the proxy is calling the binder.
verify(mIBinder).transact(anyInt(), any(Parcel.class), any(Parcel.class), anyInt());
@@ -126,9 +136,11 @@ public class SharedConnectivityManagerTest {
public void registerCallback_serviceNotConnected_canUnregisterAndReregister() {
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(null);
+
manager.registerCallback(mExecutor, mClientCallback);
manager.unregisterCallback(mClientCallback);
manager.registerCallback(mExecutor, mClientCallback);
+
verify(mClientCallback, never()).onRegisterCallbackFailed(any(Exception.class));
}
@@ -136,7 +148,9 @@ public class SharedConnectivityManagerTest {
public void registerCallback_serviceConnected() throws Exception {
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(mService);
+
manager.registerCallback(mExecutor, mClientCallback);
+
verify(mService).registerCallback(any());
verify(mClientCallback, never()).onRegisterCallbackFailed(any(Exception.class));
}
@@ -145,8 +159,10 @@ public class SharedConnectivityManagerTest {
public void registerCallback_doubleRegistration_shouldFail() throws Exception {
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(mService);
+
manager.registerCallback(mExecutor, mClientCallback);
manager.registerCallback(mExecutor, mClientCallback);
+
verify(mClientCallback).onRegisterCallbackFailed(any(IllegalStateException.class));
}
@@ -155,7 +171,9 @@ public class SharedConnectivityManagerTest {
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(mService);
doThrow(new RemoteException()).when(mService).registerCallback(any());
+
manager.registerCallback(mExecutor, mClientCallback);
+
verify(mClientCallback).onRegisterCallbackFailed(any(RemoteException.class));
}
@@ -166,22 +184,26 @@ public class SharedConnectivityManagerTest {
public void unregisterCallback_withoutRegisteringFirst_serviceNotConnected_shouldFail() {
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(null);
- assertFalse(manager.unregisterCallback(mClientCallback));
+
+ assertThat(manager.unregisterCallback(mClientCallback)).isFalse();
}
@Test
public void unregisterCallback_withoutRegisteringFirst_serviceConnected_shouldFail() {
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(mService);
- assertFalse(manager.unregisterCallback(mClientCallback));
+
+ assertThat(manager.unregisterCallback(mClientCallback)).isFalse();
}
@Test
public void unregisterCallback() throws Exception {
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(mService);
+
manager.registerCallback(mExecutor, mClientCallback);
- assertTrue(manager.unregisterCallback(mClientCallback));
+
+ assertThat(manager.unregisterCallback(mClientCallback)).isTrue();
verify(mService).unregisterCallback(any());
}
@@ -189,26 +211,32 @@ public class SharedConnectivityManagerTest {
public void unregisterCallback_doubleUnregistration_serviceConnected_shouldFail() {
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(mService);
+
manager.registerCallback(mExecutor, mClientCallback);
manager.unregisterCallback(mClientCallback);
- assertFalse(manager.unregisterCallback(mClientCallback));
+
+ assertThat(manager.unregisterCallback(mClientCallback)).isFalse();
}
@Test
public void unregisterCallback_doubleUnregistration_serviceNotConnected_shouldFail() {
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(null);
+
manager.registerCallback(mExecutor, mClientCallback);
manager.unregisterCallback(mClientCallback);
- assertFalse(manager.unregisterCallback(mClientCallback));
+
+ assertThat(manager.unregisterCallback(mClientCallback)).isFalse();
}
@Test
public void unregisterCallback_remoteException_shouldFail() throws Exception {
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(mService);
+
doThrow(new RemoteException()).when(mService).unregisterCallback(any());
- assertFalse(manager.unregisterCallback(mClientCallback));
+
+ assertThat(manager.unregisterCallback(mClientCallback)).isFalse();
}
/**
@@ -217,16 +245,20 @@ public class SharedConnectivityManagerTest {
@Test
public void onServiceConnected_registerCallbackBeforeConnection() {
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+
manager.registerCallback(mExecutor, mClientCallback);
manager.getServiceConnection().onServiceConnected(COMPONENT_NAME, mIBinder);
+
verify(mClientCallback).onServiceConnected();
}
@Test
public void onServiceConnected_registerCallbackAfterConnection() {
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+
manager.getServiceConnection().onServiceConnected(COMPONENT_NAME, mIBinder);
manager.registerCallback(mExecutor, mClientCallback);
+
verify(mClientCallback).onServiceConnected();
}
@@ -236,77 +268,89 @@ public class SharedConnectivityManagerTest {
@Test
public void onServiceDisconnected_registerCallbackBeforeConnection() {
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+
manager.registerCallback(mExecutor, mClientCallback);
manager.getServiceConnection().onServiceConnected(COMPONENT_NAME, mIBinder);
manager.getServiceConnection().onServiceDisconnected(COMPONENT_NAME);
+
verify(mClientCallback).onServiceDisconnected();
}
@Test
public void onServiceDisconnected_registerCallbackAfterConnection() {
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+
manager.getServiceConnection().onServiceConnected(COMPONENT_NAME, mIBinder);
manager.registerCallback(mExecutor, mClientCallback);
manager.getServiceConnection().onServiceDisconnected(COMPONENT_NAME);
+
verify(mClientCallback).onServiceDisconnected();
}
/**
- * Verifies connectTetherNetwork behavior.
+ * Verifies connectHotspotNetwork behavior.
*/
@Test
- public void connectTetherNetwork_serviceNotConnected_shouldFail() {
- TetherNetwork network = buildTetherNetwork();
+ public void connectHotspotNetwork_serviceNotConnected_shouldFail() {
+ HotspotNetwork network = buildHotspotNetwork();
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(null);
- assertFalse(manager.connectTetherNetwork(network));
+
+ assertThat(manager.connectHotspotNetwork(network)).isFalse();
}
@Test
- public void connectTetherNetwork() throws RemoteException {
- TetherNetwork network = buildTetherNetwork();
+ public void connectHotspotNetwork() throws RemoteException {
+ HotspotNetwork network = buildHotspotNetwork();
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(mService);
- manager.connectTetherNetwork(network);
- verify(mService).connectTetherNetwork(network);
+
+ manager.connectHotspotNetwork(network);
+
+ verify(mService).connectHotspotNetwork(network);
}
@Test
- public void connectTetherNetwork_remoteException_shouldFail() throws RemoteException {
- TetherNetwork network = buildTetherNetwork();
+ public void connectHotspotNetwork_remoteException_shouldFail() throws RemoteException {
+ HotspotNetwork network = buildHotspotNetwork();
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(mService);
- doThrow(new RemoteException()).when(mService).connectTetherNetwork(network);
- assertFalse(manager.connectTetherNetwork(network));
+ doThrow(new RemoteException()).when(mService).connectHotspotNetwork(network);
+
+ assertThat(manager.connectHotspotNetwork(network)).isFalse();
}
/**
- * Verifies disconnectTetherNetwork behavior.
+ * Verifies disconnectHotspotNetwork behavior.
*/
@Test
- public void disconnectTetherNetwork_serviceNotConnected_shouldFail() {
- TetherNetwork network = buildTetherNetwork();
+ public void disconnectHotspotNetwork_serviceNotConnected_shouldFail() {
+ HotspotNetwork network = buildHotspotNetwork();
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(null);
- assertFalse(manager.disconnectTetherNetwork(network));
+
+ assertThat(manager.disconnectHotspotNetwork(network)).isFalse();
}
@Test
- public void disconnectTetherNetwork() throws RemoteException {
- TetherNetwork network = buildTetherNetwork();
+ public void disconnectHotspotNetwork() throws RemoteException {
+ HotspotNetwork network = buildHotspotNetwork();
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(mService);
- manager.disconnectTetherNetwork(network);
- verify(mService).disconnectTetherNetwork(network);
+
+ manager.disconnectHotspotNetwork(network);
+
+ verify(mService).disconnectHotspotNetwork(network);
}
@Test
- public void disconnectTetherNetwork_remoteException_shouldFail() throws RemoteException {
- TetherNetwork network = buildTetherNetwork();
+ public void disconnectHotspotNetwork_remoteException_shouldFail() throws RemoteException {
+ HotspotNetwork network = buildHotspotNetwork();
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(mService);
- doThrow(new RemoteException()).when(mService).disconnectTetherNetwork(any());
- assertFalse(manager.disconnectTetherNetwork(network));
+ doThrow(new RemoteException()).when(mService).disconnectHotspotNetwork(any());
+
+ assertThat(manager.disconnectHotspotNetwork(network)).isFalse();
}
/**
@@ -317,7 +361,8 @@ public class SharedConnectivityManagerTest {
KnownNetwork network = buildKnownNetwork();
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(null);
- assertFalse(manager.connectKnownNetwork(network));
+
+ assertThat(manager.connectKnownNetwork(network)).isFalse();
}
@Test
@@ -325,7 +370,9 @@ public class SharedConnectivityManagerTest {
KnownNetwork network = buildKnownNetwork();
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(mService);
+
manager.connectKnownNetwork(network);
+
verify(mService).connectKnownNetwork(network);
}
@@ -335,7 +382,8 @@ public class SharedConnectivityManagerTest {
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(mService);
doThrow(new RemoteException()).when(mService).connectKnownNetwork(network);
- assertFalse(manager.connectKnownNetwork(network));
+
+ assertThat(manager.connectKnownNetwork(network)).isFalse();
}
/**
@@ -346,7 +394,8 @@ public class SharedConnectivityManagerTest {
KnownNetwork network = buildKnownNetwork();
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(null);
- assertFalse(manager.forgetKnownNetwork(network));
+
+ assertThat(manager.forgetKnownNetwork(network)).isFalse();
}
@Test
@@ -354,7 +403,9 @@ public class SharedConnectivityManagerTest {
KnownNetwork network = buildKnownNetwork();
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(mService);
+
manager.forgetKnownNetwork(network);
+
verify(mService).forgetKnownNetwork(network);
}
@@ -364,7 +415,158 @@ public class SharedConnectivityManagerTest {
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.setService(mService);
doThrow(new RemoteException()).when(mService).forgetKnownNetwork(network);
- assertFalse(manager.forgetKnownNetwork(network));
+
+ assertThat(manager.forgetKnownNetwork(network)).isFalse();
+ }
+
+ /**
+ * Verify getters.
+ */
+ @Test
+ public void getHotspotNetworks_serviceNotConnected_shouldReturnEmptyList() {
+ SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+ manager.setService(null);
+
+ assertThat(manager.getKnownNetworks()).isEmpty();
+ }
+
+ @Test
+ public void getHotspotNetworks_remoteException_shouldReturnEmptyList() throws RemoteException {
+ SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+ manager.setService(mService);
+ doThrow(new RemoteException()).when(mService).getHotspotNetworks();
+
+ assertThat(manager.getKnownNetworks()).isEmpty();
+ }
+
+ @Test
+ public void getHotspotNetworks_shouldReturnNetworksList() throws RemoteException {
+ SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+ List<HotspotNetwork> networks = List.of(buildHotspotNetwork());
+ manager.setService(mService);
+ when(mService.getHotspotNetworks()).thenReturn(networks);
+
+ assertThat(manager.getHotspotNetworks()).containsExactly(buildHotspotNetwork());
+ }
+
+ @Test
+ public void getKnownNetworks_serviceNotConnected_shouldReturnEmptyList()
+ throws RemoteException {
+ SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+ manager.setService(null);
+
+ assertThat(manager.getKnownNetworks()).isEmpty();
+ }
+
+ @Test
+ public void getKnownNetworks_remoteException_shouldReturnEmptyList() throws RemoteException {
+ SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+ manager.setService(mService);
+ doThrow(new RemoteException()).when(mService).getKnownNetworks();
+
+ assertThat(manager.getKnownNetworks()).isEmpty();
+ }
+
+ @Test
+ public void getKnownNetworks_shouldReturnNetworksList() throws RemoteException {
+ SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+ List<KnownNetwork> networks = List.of(buildKnownNetwork());
+ manager.setService(mService);
+ when(mService.getKnownNetworks()).thenReturn(networks);
+
+ assertThat(manager.getKnownNetworks()).containsExactly(buildKnownNetwork());
+ }
+
+ @Test
+ public void getSettingsState_serviceNotConnected_shouldReturnNull() throws RemoteException {
+ SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+ manager.setService(null);
+
+ assertThat(manager.getSettingsState()).isNull();
+ }
+
+ @Test
+ public void getSettingsState_remoteException_shouldReturnNull() throws RemoteException {
+ SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+ manager.setService(mService);
+ doThrow(new RemoteException()).when(mService).getSettingsState();
+
+ assertThat(manager.getSettingsState()).isNull();
+ }
+
+ @Test
+ public void getSettingsState_serviceConnected_shouldReturnState() throws RemoteException {
+ SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+ SharedConnectivitySettingsState state = new SharedConnectivitySettingsState.Builder()
+ .setInstantTetherEnabled(true).setExtras(new Bundle()).build();
+ manager.setService(mService);
+ when(mService.getSettingsState()).thenReturn(state);
+
+ assertThat(manager.getSettingsState()).isEqualTo(state);
+ }
+
+ @Test
+ public void getHotspotNetworkConnectionStatus_serviceNotConnected_shouldReturnNull()
+ throws RemoteException {
+ SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+ manager.setService(null);
+
+ assertThat(manager.getHotspotNetworkConnectionStatus()).isNull();
+ }
+
+ @Test
+ public void getHotspotNetworkConnectionStatus_remoteException_shouldReturnNull()
+ throws RemoteException {
+ SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+ manager.setService(mService);
+ doThrow(new RemoteException()).when(mService).getHotspotNetworkConnectionStatus();
+
+ assertThat(manager.getHotspotNetworkConnectionStatus()).isNull();
+ }
+
+ @Test
+ public void getHotspotNetworkConnectionStatus_serviceConnected_shouldReturnStatus()
+ throws RemoteException {
+ SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+ HotspotNetworkConnectionStatus status = new HotspotNetworkConnectionStatus.Builder()
+ .setStatus(HotspotNetworkConnectionStatus.CONNECTION_STATUS_ENABLING_HOTSPOT)
+ .setExtras(new Bundle()).build();
+ manager.setService(mService);
+ when(mService.getHotspotNetworkConnectionStatus()).thenReturn(status);
+
+ assertThat(manager.getHotspotNetworkConnectionStatus()).isEqualTo(status);
+ }
+
+ @Test
+ public void getKnownNetworkConnectionStatus_serviceNotConnected_shouldReturnNull()
+ throws RemoteException {
+ SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+ manager.setService(null);
+
+ assertThat(manager.getKnownNetworkConnectionStatus()).isNull();
+ }
+
+ @Test
+ public void getKnownNetworkConnectionStatus_remoteException_shouldReturnNull()
+ throws RemoteException {
+ SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+ manager.setService(mService);
+ doThrow(new RemoteException()).when(mService).getKnownNetworkConnectionStatus();
+
+ assertThat(manager.getKnownNetworkConnectionStatus()).isNull();
+ }
+
+ @Test
+ public void getKnownNetworkConnectionStatus_serviceConnected_shouldReturnStatus()
+ throws RemoteException {
+ SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+ KnownNetworkConnectionStatus status = new KnownNetworkConnectionStatus.Builder()
+ .setStatus(KnownNetworkConnectionStatus.CONNECTION_STATUS_SAVED)
+ .setExtras(new Bundle()).build();
+ manager.setService(mService);
+ when(mService.getKnownNetworkConnectionStatus()).thenReturn(status);
+
+ assertThat(manager.getKnownNetworkConnectionStatus()).isEqualTo(status);
}
private void setResources(@Mock Context context) {
@@ -373,19 +575,21 @@ public class SharedConnectivityManagerTest {
.thenReturn(SERVICE_PACKAGE_NAME, SERVICE_INTENT_ACTION);
}
- private TetherNetwork buildTetherNetwork() {
- return new TetherNetwork.Builder()
+ private HotspotNetwork buildHotspotNetwork() {
+ HotspotNetwork.Builder builder = new HotspotNetwork.Builder()
.setDeviceId(DEVICE_ID)
- .setDeviceInfo(DEVICE_INFO)
- .setNetworkType(NETWORK_TYPE)
+ .setNetworkProviderInfo(NETWORK_PROVIDER_INFO)
+ .setHostNetworkType(NETWORK_TYPE)
.setNetworkName(NETWORK_NAME)
- .setHotspotSsid(HOTSPOT_SSID)
- .setHotspotSecurityTypes(HOTSPOT_SECURITY_TYPES)
- .build();
+ .setHotspotSsid(HOTSPOT_SSID);
+ Arrays.stream(HOTSPOT_SECURITY_TYPES).forEach(builder::addHotspotSecurityType);
+ return builder.build();
}
private KnownNetwork buildKnownNetwork() {
- return new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE).setSsid(SSID)
- .setSecurityTypes(SECURITY_TYPES).build();
+ KnownNetwork.Builder builder = new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE)
+ .setSsid(SSID).setNetworkProviderInfo(NETWORK_PROVIDER_INFO);
+ Arrays.stream(SECURITY_TYPES).forEach(builder::addSecurityType);
+ return builder.build();
}
}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivitySettingsStateTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivitySettingsStateTest.java
index 3137c7268ae0..752b74905c97 100644
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivitySettingsStateTest.java
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivitySettingsStateTest.java
@@ -16,8 +16,7 @@
package android.net.wifi.sharedconnectivity.app;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
+import static com.google.common.truth.Truth.assertThat;
import android.os.Parcel;
@@ -26,7 +25,7 @@ import androidx.test.filters.SmallTest;
import org.junit.Test;
/**
- * Unit tests for {@link android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState}.
+ * Unit tests for {@link SharedConnectivitySettingsState}.
*/
@SmallTest
public class SharedConnectivitySettingsStateTest {
@@ -51,8 +50,8 @@ public class SharedConnectivitySettingsStateTest {
SharedConnectivitySettingsState fromParcel =
SharedConnectivitySettingsState.CREATOR.createFromParcel(parcelR);
- assertEquals(state, fromParcel);
- assertEquals(state.hashCode(), fromParcel.hashCode());
+ assertThat(fromParcel).isEqualTo(state);
+ assertThat(fromParcel.hashCode()).isEqualTo(state.hashCode());
}
/**
@@ -62,11 +61,11 @@ public class SharedConnectivitySettingsStateTest {
public void testEqualsOperation() {
SharedConnectivitySettingsState state1 = buildSettingsStateBuilder().build();
SharedConnectivitySettingsState state2 = buildSettingsStateBuilder().build();
- assertEquals(state1, state2);
+ assertThat(state1).isEqualTo(state2);
SharedConnectivitySettingsState.Builder builder = buildSettingsStateBuilder()
.setInstantTetherEnabled(INSTANT_TETHER_STATE_1);
- assertNotEquals(state1, builder.build());
+ assertThat(builder.build()).isNotEqualTo(state1);
}
/**
@@ -75,7 +74,15 @@ public class SharedConnectivitySettingsStateTest {
@Test
public void testGetMethods() {
SharedConnectivitySettingsState state = buildSettingsStateBuilder().build();
- assertEquals(state.isInstantTetherEnabled(), INSTANT_TETHER_STATE);
+ assertThat(state.isInstantTetherEnabled()).isEqualTo(INSTANT_TETHER_STATE);
+ }
+
+ @Test
+ public void testHashCode() {
+ SharedConnectivitySettingsState state1 = buildSettingsStateBuilder().build();
+ SharedConnectivitySettingsState state2 = buildSettingsStateBuilder().build();
+
+ assertThat(state1.hashCode()).isEqualTo(state2.hashCode());
}
private SharedConnectivitySettingsState.Builder buildSettingsStateBuilder() {
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatusTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatusTest.java
deleted file mode 100644
index 1d9c2e6df38a..000000000000
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatusTest.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.sharedconnectivity.app;
-
-import static android.net.wifi.WifiInfo.SECURITY_TYPE_EAP;
-import static android.net.wifi.WifiInfo.SECURITY_TYPE_WEP;
-import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_TABLET;
-import static android.net.wifi.sharedconnectivity.app.TetherNetwork.NETWORK_TYPE_CELLULAR;
-import static android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus.CONNECTION_STATUS_ENABLING_HOTSPOT;
-import static android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus.CONNECTION_STATUS_TETHERING_TIMEOUT;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-
-import android.os.Bundle;
-import android.os.Parcel;
-
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-
-/**
- * Unit tests for {@link android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus}.
- */
-@SmallTest
-public class TetherNetworkConnectionStatusTest {
- private static final long DEVICE_ID = 11L;
- private static final DeviceInfo DEVICE_INFO = new DeviceInfo.Builder()
- .setDeviceType(DEVICE_TYPE_TABLET).setDeviceName("TEST_NAME").setModelName("TEST_MODEL")
- .setConnectionStrength(2).setBatteryPercentage(50).build();
- private static final int NETWORK_TYPE = NETWORK_TYPE_CELLULAR;
- private static final String NETWORK_NAME = "TEST_NETWORK";
- private static final String HOTSPOT_SSID = "TEST_SSID";
- private static final String HOTSPOT_BSSID = "TEST _BSSID";
- private static final int[] HOTSPOT_SECURITY_TYPES = {SECURITY_TYPE_WEP, SECURITY_TYPE_EAP};
- private static final long DEVICE_ID_1 = 111L;
- private static final String BUNDLE_KEY = "INT-KEY";
-
- /**
- * Verifies parcel serialization/deserialization.
- */
- @Test
- public void testParcelOperation() {
- TetherNetworkConnectionStatus status = buildConnectionStatusBuilder().build();
-
- Parcel parcelW = Parcel.obtain();
- status.writeToParcel(parcelW, 0);
- byte[] bytes = parcelW.marshall();
- parcelW.recycle();
-
- Parcel parcelR = Parcel.obtain();
- parcelR.unmarshall(bytes, 0, bytes.length);
- parcelR.setDataPosition(0);
- TetherNetworkConnectionStatus fromParcel =
- TetherNetworkConnectionStatus.CREATOR.createFromParcel(parcelR);
-
- assertEquals(status, fromParcel);
- assertEquals(status.hashCode(), fromParcel.hashCode());
- }
-
- /**
- * Verifies the Equals operation
- */
- @Test
- public void testEqualsOperation() {
- TetherNetworkConnectionStatus status1 = buildConnectionStatusBuilder().build();
- TetherNetworkConnectionStatus status2 = buildConnectionStatusBuilder().build();
- assertEquals(status2, status2);
-
- TetherNetworkConnectionStatus.Builder builder = buildConnectionStatusBuilder()
- .setStatus(CONNECTION_STATUS_TETHERING_TIMEOUT);
- assertNotEquals(status1, builder.build());
-
- builder = buildConnectionStatusBuilder()
- .setTetherNetwork(buildTetherNetworkBuilder().setDeviceId(DEVICE_ID_1).build());
- assertNotEquals(status1, builder.build());
- }
-
- /**
- * Verifies the get methods return the expected data.
- */
- @Test
- public void testGetMethods() {
- TetherNetworkConnectionStatus status = buildConnectionStatusBuilder().build();
- assertEquals(status.getStatus(), CONNECTION_STATUS_ENABLING_HOTSPOT);
- assertEquals(status.getTetherNetwork(), buildTetherNetworkBuilder().build());
- assertEquals(status.getExtras().getInt(BUNDLE_KEY), buildBundle().getInt(BUNDLE_KEY));
- }
-
- private TetherNetworkConnectionStatus.Builder buildConnectionStatusBuilder() {
-
- return new TetherNetworkConnectionStatus.Builder()
- .setStatus(CONNECTION_STATUS_ENABLING_HOTSPOT)
- .setTetherNetwork(buildTetherNetworkBuilder().build())
- .setExtras(buildBundle());
- }
-
- private Bundle buildBundle() {
- Bundle bundle = new Bundle();
- bundle.putInt(BUNDLE_KEY, 1);
- return bundle;
- }
-
- private TetherNetwork.Builder buildTetherNetworkBuilder() {
- return new TetherNetwork.Builder()
- .setDeviceId(DEVICE_ID)
- .setDeviceInfo(DEVICE_INFO)
- .setNetworkType(NETWORK_TYPE)
- .setNetworkName(NETWORK_NAME)
- .setHotspotSsid(HOTSPOT_SSID)
- .setHotspotBssid(HOTSPOT_BSSID)
- .setHotspotSecurityTypes(HOTSPOT_SECURITY_TYPES);
- }
-}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/TetherNetworkTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/TetherNetworkTest.java
deleted file mode 100644
index b01aec4ad1c1..000000000000
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/TetherNetworkTest.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.sharedconnectivity.app;
-
-import static android.net.wifi.WifiInfo.SECURITY_TYPE_EAP;
-import static android.net.wifi.WifiInfo.SECURITY_TYPE_PSK;
-import static android.net.wifi.WifiInfo.SECURITY_TYPE_WEP;
-import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_PHONE;
-import static android.net.wifi.sharedconnectivity.app.DeviceInfo.DEVICE_TYPE_TABLET;
-import static android.net.wifi.sharedconnectivity.app.TetherNetwork.NETWORK_TYPE_CELLULAR;
-import static android.net.wifi.sharedconnectivity.app.TetherNetwork.NETWORK_TYPE_WIFI;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-
-import android.os.Parcel;
-
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-
-/**
- * Unit tests for {@link android.net.wifi.sharedconnectivity.app.TetherNetwork}.
- */
-@SmallTest
-public class TetherNetworkTest {
- private static final long DEVICE_ID = 11L;
- private static final DeviceInfo DEVICE_INFO = new DeviceInfo.Builder()
- .setDeviceType(DEVICE_TYPE_TABLET).setDeviceName("TEST_NAME").setModelName("TEST_MODEL")
- .setConnectionStrength(2).setBatteryPercentage(50).build();
- private static final int NETWORK_TYPE = NETWORK_TYPE_CELLULAR;
- private static final String NETWORK_NAME = "TEST_NETWORK";
- private static final String HOTSPOT_SSID = "TEST_SSID";
- private static final String HOTSPOT_BSSID = "TEST _BSSID";
- private static final int[] HOTSPOT_SECURITY_TYPES = {SECURITY_TYPE_WEP, SECURITY_TYPE_EAP};
-
- private static final long DEVICE_ID_1 = 111L;
- private static final DeviceInfo DEVICE_INFO_1 = new DeviceInfo.Builder()
- .setDeviceType(DEVICE_TYPE_PHONE).setDeviceName("TEST_NAME").setModelName("TEST_MODEL")
- .setConnectionStrength(2).setBatteryPercentage(50).build();
- private static final int NETWORK_TYPE_1 = NETWORK_TYPE_WIFI;
- private static final String NETWORK_NAME_1 = "TEST_NETWORK1";
- private static final String HOTSPOT_SSID_1 = "TEST_SSID1";
- private static final String HOTSPOT_BSSID_1 = "TEST _BSSID1";
- private static final int[] HOTSPOT_SECURITY_TYPES_1 = {SECURITY_TYPE_PSK, SECURITY_TYPE_EAP};
-
- /**
- * Verifies parcel serialization/deserialization.
- */
- @Test
- public void testParcelOperation() {
- TetherNetwork network = buildTetherNetworkBuilder().build();
-
- Parcel parcelW = Parcel.obtain();
- network.writeToParcel(parcelW, 0);
- byte[] bytes = parcelW.marshall();
- parcelW.recycle();
-
- Parcel parcelR = Parcel.obtain();
- parcelR.unmarshall(bytes, 0, bytes.length);
- parcelR.setDataPosition(0);
- TetherNetwork fromParcel = TetherNetwork.CREATOR.createFromParcel(parcelR);
-
- assertEquals(network, fromParcel);
- assertEquals(network.hashCode(), fromParcel.hashCode());
- }
-
- /**
- * Verifies the Equals operation
- */
- @Test
- public void testEqualsOperation() {
- TetherNetwork network1 = buildTetherNetworkBuilder().build();
- TetherNetwork network2 = buildTetherNetworkBuilder().build();
- assertEquals(network1, network2);
-
- TetherNetwork.Builder builder = buildTetherNetworkBuilder().setDeviceId(DEVICE_ID_1);
- assertNotEquals(network1, builder.build());
-
- builder = buildTetherNetworkBuilder().setDeviceInfo(DEVICE_INFO_1);
- assertNotEquals(network1, builder.build());
-
- builder = buildTetherNetworkBuilder().setNetworkType(NETWORK_TYPE_1);
- assertNotEquals(network1, builder.build());
-
- builder = buildTetherNetworkBuilder().setNetworkName(NETWORK_NAME_1);
- assertNotEquals(network1, builder.build());
-
- builder = buildTetherNetworkBuilder().setHotspotSsid(HOTSPOT_SSID_1);
- assertNotEquals(network1, builder.build());
-
- builder = buildTetherNetworkBuilder().setHotspotBssid(HOTSPOT_BSSID_1);
- assertNotEquals(network1, builder.build());
-
- builder = buildTetherNetworkBuilder().setHotspotSecurityTypes(HOTSPOT_SECURITY_TYPES_1);
- assertNotEquals(network1, builder.build());
- }
-
- /**
- * Verifies the get methods return the expected data.
- */
- @Test
- public void testGetMethods() {
- TetherNetwork network = buildTetherNetworkBuilder().build();
- assertEquals(network.getDeviceId(), DEVICE_ID);
- assertEquals(network.getDeviceInfo(), DEVICE_INFO);
- assertEquals(network.getNetworkType(), NETWORK_TYPE);
- assertEquals(network.getNetworkName(), NETWORK_NAME);
- assertEquals(network.getHotspotSsid(), HOTSPOT_SSID);
- assertEquals(network.getHotspotBssid(), HOTSPOT_BSSID);
- assertArrayEquals(network.getHotspotSecurityTypes(), HOTSPOT_SECURITY_TYPES);
- }
-
- private TetherNetwork.Builder buildTetherNetworkBuilder() {
- return new TetherNetwork.Builder()
- .setDeviceId(DEVICE_ID)
- .setDeviceInfo(DEVICE_INFO)
- .setNetworkType(NETWORK_TYPE)
- .setNetworkName(NETWORK_NAME)
- .setHotspotSsid(HOTSPOT_SSID)
- .setHotspotBssid(HOTSPOT_BSSID)
- .setHotspotSecurityTypes(HOTSPOT_SECURITY_TYPES);
- }
-}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityServiceTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityServiceTest.java
index d7f7fea4df3e..19effe5d6f14 100644
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityServiceTest.java
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityServiceTest.java
@@ -16,14 +16,29 @@
package android.net.wifi.sharedconnectivity.service;
-import static org.junit.Assert.assertNotNull;
+import static android.net.wifi.WifiInfo.SECURITY_TYPE_EAP;
+import static android.net.wifi.WifiInfo.SECURITY_TYPE_WEP;
+import static android.net.wifi.sharedconnectivity.app.HotspotNetwork.NETWORK_TYPE_CELLULAR;
+import static android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus.CONNECTION_STATUS_UNKNOWN;
+import static android.net.wifi.sharedconnectivity.app.KnownNetwork.NETWORK_SOURCE_NEARBY_SELF;
+import static android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus.CONNECTION_STATUS_SAVED;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_TABLET;
+
+import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.Intent;
+import android.net.wifi.sharedconnectivity.app.HotspotNetwork;
+import android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus;
import android.net.wifi.sharedconnectivity.app.KnownNetwork;
-import android.net.wifi.sharedconnectivity.app.TetherNetwork;
+import android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus;
+import android.net.wifi.sharedconnectivity.app.NetworkProviderInfo;
+import android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState;
+import android.os.Bundle;
import android.os.Looper;
+import android.os.RemoteException;
import androidx.annotation.NonNull;
import androidx.test.filters.SmallTest;
@@ -33,11 +48,40 @@ import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.List;
+
/**
- * Unit tests for {@link android.net.wifi.sharedconnectivity.service.SharedConnectivityService}.
+ * Unit tests for {@link SharedConnectivityService}.
*/
@SmallTest
public class SharedConnectivityServiceTest {
+ private static final NetworkProviderInfo NETWORK_PROVIDER_INFO =
+ new NetworkProviderInfo.Builder("TEST_NAME", "TEST_MODEL")
+ .setDeviceType(DEVICE_TYPE_TABLET).setConnectionStrength(2)
+ .setBatteryPercentage(50).build();
+ private static final HotspotNetwork HOTSPOT_NETWORK =
+ new HotspotNetwork.Builder().setDeviceId(1).setNetworkProviderInfo(
+ NETWORK_PROVIDER_INFO)
+ .setHostNetworkType(NETWORK_TYPE_CELLULAR).setNetworkName("TEST_NETWORK")
+ .setHotspotSsid("TEST_SSID").setHotspotBssid("TEST_BSSID")
+ .addHotspotSecurityType(SECURITY_TYPE_WEP)
+ .addHotspotSecurityType(SECURITY_TYPE_EAP).build();
+ private static final List<HotspotNetwork> HOTSPOT_NETWORKS = List.of(HOTSPOT_NETWORK);
+ private static final KnownNetwork KNOWN_NETWORK =
+ new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE_NEARBY_SELF)
+ .setSsid("TEST_SSID").addSecurityType(SECURITY_TYPE_WEP)
+ .addSecurityType(SECURITY_TYPE_EAP).setNetworkProviderInfo(
+ NETWORK_PROVIDER_INFO).build();
+ private static final List<KnownNetwork> KNOWN_NETWORKS = List.of(KNOWN_NETWORK);
+ private static final SharedConnectivitySettingsState SETTINGS_STATE =
+ new SharedConnectivitySettingsState.Builder().setInstantTetherEnabled(true)
+ .setExtras(Bundle.EMPTY).build();
+ private static final HotspotNetworkConnectionStatus TETHER_NETWORK_CONNECTION_STATUS =
+ new HotspotNetworkConnectionStatus.Builder().setStatus(CONNECTION_STATUS_UNKNOWN)
+ .setHotspotNetwork(HOTSPOT_NETWORK).setExtras(Bundle.EMPTY).build();
+ private static final KnownNetworkConnectionStatus KNOWN_NETWORK_CONNECTION_STATUS =
+ new KnownNetworkConnectionStatus.Builder().setStatus(CONNECTION_STATUS_SAVED)
+ .setKnownNetwork(KNOWN_NETWORK).setExtras(Bundle.EMPTY).build();
@Mock
Context mContext;
@@ -48,16 +92,20 @@ public class SharedConnectivityServiceTest {
}
@Override
- public void onConnectTetherNetwork(@NonNull TetherNetwork network) {}
+ public void onConnectHotspotNetwork(@NonNull HotspotNetwork network) {
+ }
@Override
- public void onDisconnectTetherNetwork(@NonNull TetherNetwork network) {}
+ public void onDisconnectHotspotNetwork(@NonNull HotspotNetwork network) {
+ }
@Override
- public void onConnectKnownNetwork(@NonNull KnownNetwork network) {}
+ public void onConnectKnownNetwork(@NonNull KnownNetwork network) {
+ }
@Override
- public void onForgetKnownNetwork(@NonNull KnownNetwork network) {}
+ public void onForgetKnownNetwork(@NonNull KnownNetwork network) {
+ }
}
@Before
@@ -66,20 +114,70 @@ public class SharedConnectivityServiceTest {
when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
}
- /**
- * Verifies service returns
- */
@Test
- public void testOnBind() {
+ public void onBind_isNotNull() {
+ SharedConnectivityService service = createService();
+
+ assertThat(service.onBind(new Intent())).isNotNull();
+ }
+
+ @Test
+ public void getHotspotNetworks() throws RemoteException {
+ SharedConnectivityService service = createService();
+ ISharedConnectivityService.Stub binder =
+ (ISharedConnectivityService.Stub) service.onBind(new Intent());
+
+ service.setHotspotNetworks(HOTSPOT_NETWORKS);
+
+ assertThat(binder.getHotspotNetworks())
+ .containsExactlyElementsIn(List.copyOf(HOTSPOT_NETWORKS));
+ }
+
+ @Test
+ public void getKnownNetworks() throws RemoteException {
+ SharedConnectivityService service = createService();
+ ISharedConnectivityService.Stub binder =
+ (ISharedConnectivityService.Stub) service.onBind(new Intent());
+
+ service.setKnownNetworks(KNOWN_NETWORKS);
+
+ assertThat(binder.getKnownNetworks())
+ .containsExactlyElementsIn(List.copyOf(KNOWN_NETWORKS));
+ }
+
+ @Test
+ public void getSharedConnectivitySettingsState() throws RemoteException {
SharedConnectivityService service = createService();
- assertNotNull(service.onBind(new Intent()));
+ ISharedConnectivityService.Stub binder =
+ (ISharedConnectivityService.Stub) service.onBind(new Intent());
+
+ service.setSettingsState(SETTINGS_STATE);
+
+ assertThat(binder.getSettingsState()).isEqualTo(SETTINGS_STATE);
}
@Test
- public void testCallbacks() {
+ public void updateHotspotNetworkConnectionStatus() throws RemoteException {
SharedConnectivityService service = createService();
ISharedConnectivityService.Stub binder =
(ISharedConnectivityService.Stub) service.onBind(new Intent());
+
+ service.updateHotspotNetworkConnectionStatus(TETHER_NETWORK_CONNECTION_STATUS);
+
+ assertThat(binder.getHotspotNetworkConnectionStatus())
+ .isEqualTo(TETHER_NETWORK_CONNECTION_STATUS);
+ }
+
+ @Test
+ public void updateKnownNetworkConnectionStatus() throws RemoteException {
+ SharedConnectivityService service = createService();
+ ISharedConnectivityService.Stub binder =
+ (ISharedConnectivityService.Stub) service.onBind(new Intent());
+
+ service.updateKnownNetworkConnectionStatus(KNOWN_NETWORK_CONNECTION_STATUS);
+
+ assertThat(binder.getKnownNetworkConnectionStatus())
+ .isEqualTo(KNOWN_NETWORK_CONNECTION_STATUS);
}
private SharedConnectivityService createService() {